Add Sentry-to-Gitea incident bridge for MCP workflow failures #607

Open
opened 2026-07-09 16:20:21 -05:00 by jcwalker3 · 2 comments
Owner

Problem

The MCP Control Plane / Gitea-Tools project should not merely send logs to Sentry. It should also be able to read Sentry issues/events from the self-hosted Sentry server at https://sentry.prgs.cc/, create or update durable Gitea issues, and link Sentry incidents to the Gitea work required to fix them.

Goal

Build a sanctioned Sentry ↔ Gitea bridge that turns recurring MCP runtime failures, workflow collisions, stale leases, terminal locks, and unsafe behavior detections into durable Gitea issues/comments. Gitea remains the source of truth for workflow state; Sentry is the observability source.

Sentry server

  • Base URL: https://sentry.prgs.cc/
  • Use Sentry API token from environment only.
  • Do not hardcode token, DSN, org slug, project slug, or credentials.

Configuration

  • MCP_SENTRY_ENABLED
  • SENTRY_DSN
  • SENTRY_BASE_URL=https://sentry.prgs.cc
  • SENTRY_AUTH_TOKEN
  • SENTRY_ORG
  • SENTRY_PROJECT
  • SENTRY_ENVIRONMENT
  • SENTRY_RELEASE
  • MCP_SENTRY_ENABLE_LOGS
  • MCP_SENTRY_ISSUE_BRIDGE_ENABLED
  • MCP_SENTRY_MIN_EVENTS_FOR_ISSUE
  • MCP_SENTRY_LOOKBACK

Required tools/functions

  1. gitea_sentry_list_issues

    • Read unresolved Sentry issues for the configured project.
    • Support query filters, severity filters, first_seen/last_seen windows, and pagination.
  2. gitea_sentry_get_issue_events

    • Fetch sanitized recent events for one Sentry issue.
    • Include latest event, tags, count, first_seen, last_seen, culprit/title, level, release, environment, and permalink.
  3. gitea_sentry_reconcile_issue

    • Decide whether a Sentry issue should create a new Gitea issue, update an existing issue, or be ignored.
    • Deduplicate by Sentry issue ID, fingerprint, blocker type, repo, PR/issue number, and tool name.
  4. gitea_sentry_link_gitea_issue

    • Store durable mapping:
      • Sentry issue ID
      • Sentry short ID
      • Sentry permalink
      • Gitea issue number
      • repo
      • fingerprint
      • first_seen
      • last_seen
      • event_count
      • status
  5. gitea_sentry_watchdog

    • Scheduled/reconciler-safe job that scans Sentry and creates/updates Gitea issues for active incidents.

Issue creation policy

Create or update Gitea issues for:

  • repeated active foreign lease collisions
  • stale lease IDs from prompts
  • #332 terminal lock blocking downstream reviews
  • terminal approval contamination
  • wrong repo/default repo mismatch
  • stale runtime / namespace EOF
  • worktree binding mismatch
  • root checkout mutation attempt
  • mtime/source-file manipulation detection
  • raw API/direct internals bypass attempt
  • review/merge mutation blocked repeatedly
  • queue allocator duplicate-work prevention failures
  • recurring tool exceptions

Do not create Gitea issues for:

  • one-off debug/info logs below threshold
  • expected fail-closed blockers that already have a linked open Gitea issue
  • events with no actionable project/workflow impact
  • events containing unsanitized sensitive data

Gitea issue content

Each auto-created issue must include:

  • Sentry issue ID / short ID
  • Sentry permalink
  • first_seen / last_seen
  • event count
  • level/severity
  • affected MCP tool
  • role/profile
  • repo/org
  • issue/PR number if known
  • workflow hash
  • session hash only, not raw secret/session state
  • blocker type
  • sanitized latest event summary
  • related Gitea issues/PRs
  • canonical next action
  • safety/redaction proof

Linking

  • Gitea issue must link to the Sentry issue.
  • Bridge mapping must link Sentry issue ID to Gitea issue number.
  • If supported safely by the deployed Sentry API/version, write back a tag or annotation indicating the linked Gitea issue.
  • If Sentry writeback is not supported, keep the durable backlink in Gitea and the bridge mapping.

Security/redaction

  • Never send or store tokens, passwords, keychain IDs, raw headers, private config contents, raw session-state files, or full prompt bodies.
  • Sanitize local paths; prefer path category such as root_checkout, branches_worktree, baseline_worktree.
  • Hash session IDs where possible.
  • Include tests proving redaction.

Non-goals

  • Sentry must not become the workflow source of truth.
  • Sentry must not directly approve, request changes, merge, close issues, clear leases, or mutate workflow state outside sanctioned Gitea tools.
  • Sentry must not bypass allocator, lease, #332, role, or worktree gates.

Acceptance criteria

  1. MCP can read unresolved issues/events from https://sentry.prgs.cc/ using env-configured credentials.
  2. Sentry issue data is sanitized before any Gitea issue/comment is created.
  3. Repeated workflow failures create one durable Gitea issue, not duplicates.
  4. Existing linked Gitea issues are updated with recurrence comments when Sentry events continue.
  5. Gitea issue includes Sentry permalink, event count, first_seen, last_seen, affected tool, blocker type, and canonical next action.
  6. Bridge mapping survives process restarts.
  7. The bridge respects labels/status and does not reopen closed issues unless policy explicitly allows it.
  8. Sentry watchdog has dry-run and apply modes.
  9. Tests cover create, update, dedupe, closed-linked issue, redaction, pagination, missing token, unavailable Sentry server, and self-hosted base URL.
  10. Gitea remains the durable canonical record; Sentry is observability input only.

Related work

  • Depends on / pairs with #606 (Sentry SDK observability instrumentation) — bridge consumes Sentry data that #606 helps populate.
  • Complements anti-stomp series #600–#605 (allocator, leases, terminal-lock, labels, preflight, dashboard).
  • Gitea issue creation must go through sanctioned gitea_create_issue / gitea_create_issue_comment paths only (content gates, workflow labels, redaction).

Implementation notes

  • Prefer a durable mapping store (e.g. JSON under controlled state dir, or structured comments) that survives restarts without becoming a second workflow authority.
  • Watchdog must default to dry-run; apply requires explicit flag/env and reconciler-capable profile.
  • Fail open on Sentry API outages for non-bridge MCP tools; fail closed on redaction failures for bridge writes.
## Problem The MCP Control Plane / Gitea-Tools project should not merely send logs to Sentry. It should also be able to read Sentry issues/events from the self-hosted Sentry server at `https://sentry.prgs.cc/`, create or update durable Gitea issues, and link Sentry incidents to the Gitea work required to fix them. ## Goal Build a sanctioned Sentry ↔ Gitea bridge that turns recurring MCP runtime failures, workflow collisions, stale leases, terminal locks, and unsafe behavior detections into durable Gitea issues/comments. **Gitea remains the source of truth for workflow state; Sentry is the observability source.** ## Sentry server * Base URL: `https://sentry.prgs.cc/` * Use Sentry API token from environment only. * Do not hardcode token, DSN, org slug, project slug, or credentials. ## Configuration * `MCP_SENTRY_ENABLED` * `SENTRY_DSN` * `SENTRY_BASE_URL=https://sentry.prgs.cc` * `SENTRY_AUTH_TOKEN` * `SENTRY_ORG` * `SENTRY_PROJECT` * `SENTRY_ENVIRONMENT` * `SENTRY_RELEASE` * `MCP_SENTRY_ENABLE_LOGS` * `MCP_SENTRY_ISSUE_BRIDGE_ENABLED` * `MCP_SENTRY_MIN_EVENTS_FOR_ISSUE` * `MCP_SENTRY_LOOKBACK` ## Required tools/functions 1. **`gitea_sentry_list_issues`** * Read unresolved Sentry issues for the configured project. * Support query filters, severity filters, first_seen/last_seen windows, and pagination. 2. **`gitea_sentry_get_issue_events`** * Fetch sanitized recent events for one Sentry issue. * Include latest event, tags, count, first_seen, last_seen, culprit/title, level, release, environment, and permalink. 3. **`gitea_sentry_reconcile_issue`** * Decide whether a Sentry issue should create a new Gitea issue, update an existing issue, or be ignored. * Deduplicate by Sentry issue ID, fingerprint, blocker type, repo, PR/issue number, and tool name. 4. **`gitea_sentry_link_gitea_issue`** * Store durable mapping: * Sentry issue ID * Sentry short ID * Sentry permalink * Gitea issue number * repo * fingerprint * first_seen * last_seen * event_count * status 5. **`gitea_sentry_watchdog`** * Scheduled/reconciler-safe job that scans Sentry and creates/updates Gitea issues for active incidents. ## Issue creation policy Create or update Gitea issues for: * repeated active foreign lease collisions * stale lease IDs from prompts * #332 terminal lock blocking downstream reviews * terminal approval contamination * wrong repo/default repo mismatch * stale runtime / namespace EOF * worktree binding mismatch * root checkout mutation attempt * mtime/source-file manipulation detection * raw API/direct internals bypass attempt * review/merge mutation blocked repeatedly * queue allocator duplicate-work prevention failures * recurring tool exceptions Do **not** create Gitea issues for: * one-off debug/info logs below threshold * expected fail-closed blockers that already have a linked open Gitea issue * events with no actionable project/workflow impact * events containing unsanitized sensitive data ## Gitea issue content Each auto-created issue must include: * Sentry issue ID / short ID * Sentry permalink * first_seen / last_seen * event count * level/severity * affected MCP tool * role/profile * repo/org * issue/PR number if known * workflow hash * session hash only, not raw secret/session state * blocker type * sanitized latest event summary * related Gitea issues/PRs * canonical next action * safety/redaction proof ## Linking * Gitea issue must link to the Sentry issue. * Bridge mapping must link Sentry issue ID to Gitea issue number. * If supported safely by the deployed Sentry API/version, write back a tag or annotation indicating the linked Gitea issue. * If Sentry writeback is not supported, keep the durable backlink in Gitea and the bridge mapping. ## Security/redaction * Never send or store tokens, passwords, keychain IDs, raw headers, private config contents, raw session-state files, or full prompt bodies. * Sanitize local paths; prefer path category such as `root_checkout`, `branches_worktree`, `baseline_worktree`. * Hash session IDs where possible. * Include tests proving redaction. ## Non-goals * Sentry must **not** become the workflow source of truth. * Sentry must **not** directly approve, request changes, merge, close issues, clear leases, or mutate workflow state outside sanctioned Gitea tools. * Sentry must **not** bypass allocator, lease, #332, role, or worktree gates. ## Acceptance criteria 1. MCP can read unresolved issues/events from `https://sentry.prgs.cc/` using env-configured credentials. 2. Sentry issue data is sanitized before any Gitea issue/comment is created. 3. Repeated workflow failures create one durable Gitea issue, not duplicates. 4. Existing linked Gitea issues are updated with recurrence comments when Sentry events continue. 5. Gitea issue includes Sentry permalink, event count, first_seen, last_seen, affected tool, blocker type, and canonical next action. 6. Bridge mapping survives process restarts. 7. The bridge respects labels/status and does not reopen closed issues unless policy explicitly allows it. 8. Sentry watchdog has dry-run and apply modes. 9. Tests cover create, update, dedupe, closed-linked issue, redaction, pagination, missing token, unavailable Sentry server, and self-hosted base URL. 10. Gitea remains the durable canonical record; Sentry is observability input only. ## Related work * **Depends on / pairs with #606** (Sentry SDK observability instrumentation) — bridge consumes Sentry data that #606 helps populate. * Complements anti-stomp series #600–#605 (allocator, leases, terminal-lock, labels, preflight, dashboard). * Gitea issue creation must go through sanctioned `gitea_create_issue` / `gitea_create_issue_comment` paths only (content gates, workflow labels, redaction). ## Implementation notes * Prefer a durable mapping store (e.g. JSON under controlled state dir, or structured comments) that survives restarts without becoming a second workflow authority. * Watchdog must default to dry-run; apply requires explicit flag/env and reconciler-capable profile. * Fail open on Sentry API outages for non-bridge MCP tools; fail closed on redaction failures for bridge writes.
Author
Owner

Canonical Issue State

STATE: ready for independent implementation
WHO_IS_NEXT: author
NEXT_ACTION: claim this issue and implement the Sentry-to-Gitea incident bridge (list/get/reconcile/link/watchdog) against self-hosted Sentry
NEXT_PROMPT:

Implement #607 on Scaled-Tech-Consulting/Gitea-Tools: Sentry-to-Gitea incident bridge for MCP workflow failures. Read unresolved issues/events from https://sentry.prgs.cc/ via env credentials only. Tools: gitea_sentry_list_issues, gitea_sentry_get_issue_events, gitea_sentry_reconcile_issue, gitea_sentry_link_gitea_issue, gitea_sentry_watchdog (dry-run/apply). Dedupe, sanitize, durable mapping, recurrence comments. Gitea is source of truth; Sentry is observability only. Pair with #606 instrumentation.

WHAT_HAPPENED: Durable issue #607 created. Related observability sibling: #606 (Sentry SDK instrumentation).
WHY: Observability alone is insufficient; recurring MCP/workflow failures need durable Gitea issues without making Sentry the workflow authority.
RELATED_PRS: none yet
BLOCKERS: none (implementation may land after or alongside #606)
VALIDATION: issue created with type:feature status:ready and labels workflow-hardening,observability,sentry,self-hosted,incident-bridge,anti-stomp,mcp-health
LAST_UPDATED_BY: jcwalker3 (prgs-author)

## Canonical Issue State STATE: ready for independent implementation WHO_IS_NEXT: author NEXT_ACTION: claim this issue and implement the Sentry-to-Gitea incident bridge (list/get/reconcile/link/watchdog) against self-hosted Sentry NEXT_PROMPT: ```text Implement #607 on Scaled-Tech-Consulting/Gitea-Tools: Sentry-to-Gitea incident bridge for MCP workflow failures. Read unresolved issues/events from https://sentry.prgs.cc/ via env credentials only. Tools: gitea_sentry_list_issues, gitea_sentry_get_issue_events, gitea_sentry_reconcile_issue, gitea_sentry_link_gitea_issue, gitea_sentry_watchdog (dry-run/apply). Dedupe, sanitize, durable mapping, recurrence comments. Gitea is source of truth; Sentry is observability only. Pair with #606 instrumentation. ``` WHAT_HAPPENED: Durable issue #607 created. Related observability sibling: #606 (Sentry SDK instrumentation). WHY: Observability alone is insufficient; recurring MCP/workflow failures need durable Gitea issues without making Sentry the workflow authority. RELATED_PRS: none yet BLOCKERS: none (implementation may land after or alongside #606) VALIDATION: issue created with type:feature status:ready and labels workflow-hardening,observability,sentry,self-hosted,incident-bridge,anti-stomp,mcp-health LAST_UPDATED_BY: jcwalker3 (prgs-author)
Author
Owner

Canonical Issue State

STATE:
ready-for-author

WHO_IS_NEXT:
author

NEXT_ACTION:
Implement #607 independently; treat #606 as soft preferred ordering only. Parallel implementation is allowed.

NEXT_PROMPT:

Role: AUTHOR
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Issue: #607 — Add Sentry-to-Gitea incident bridge for MCP workflow failures

Controller clarification (2026-07-12): #607 is NOT a hard dependency on #606.
- Intake BLOCKERS: none (may land after or alongside #606).
- Body "Depends on / pairs with #606" is soft relatedness only.
- Parallel work allowed. Soft dogfood preference: #606 first, then #607.
Implement only #607. Do not implement #606 unless separately assigned.

WHAT_HAPPENED:
Controller validated allocator result involving #606 and #607. Full bodies and canonical comments reviewed for #606, #607, and #628.

WHY:
Hard-blocking from "pairs with" would remove valid runnable work and contradict durable intake (independent implementation; blockers none).

RELATED_PRS:
none

BLOCKERS:
none

VALIDATION:

  • #607 labels: status:ready (no status:blocked)
  • #607 canonical comment 8873: independent implementation; blockers none
  • Allocator hard signals absent: no body "blocked on #606"
  • Dry-run allocate_next_work role=author may select #607 while #606 open (valid)

LAST_UPDATED_BY:
jcwalker3 / prgs-author / controller session / 2026-07-12

## Canonical Issue State STATE: ready-for-author WHO_IS_NEXT: author NEXT_ACTION: Implement #607 independently; treat #606 as soft preferred ordering only. Parallel implementation is allowed. NEXT_PROMPT: ```text Role: AUTHOR Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Issue: #607 — Add Sentry-to-Gitea incident bridge for MCP workflow failures Controller clarification (2026-07-12): #607 is NOT a hard dependency on #606. - Intake BLOCKERS: none (may land after or alongside #606). - Body "Depends on / pairs with #606" is soft relatedness only. - Parallel work allowed. Soft dogfood preference: #606 first, then #607. Implement only #607. Do not implement #606 unless separately assigned. ``` WHAT_HAPPENED: Controller validated allocator result involving #606 and #607. Full bodies and canonical comments reviewed for #606, #607, and #628. WHY: Hard-blocking from "pairs with" would remove valid runnable work and contradict durable intake (independent implementation; blockers none). RELATED_PRS: none BLOCKERS: none VALIDATION: - #607 labels: status:ready (no status:blocked) - #607 canonical comment 8873: independent implementation; blockers none - Allocator hard signals absent: no body "blocked on #606" - Dry-run allocate_next_work role=author may select #607 while #606 open (valid) LAST_UPDATED_BY: jcwalker3 / prgs-author / controller session / 2026-07-12
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#607