Return structured MCP errors for authentication failures without terminating transport #699

Open
opened 2026-07-13 11:20:02 -05:00 by jcwalker3 · 6 comments
Owner

Problem

Known Gitea authentication failures (revoked/invalid Keychain credentials → HTTP 401) can escape the MCP tool boundary as an unhandled RuntimeError. The client then observes EOF / transport closed instead of a sanitized structured tool error. The session loses the namespace mid-workflow even though the underlying defect is a normal authentication failure that must remain recoverable without reconnect.

This is not the #685 resolver self-termination path. Managed logs for this incident identified a distinct authentication-exception path. #685 causation was initially suspected but not confirmed for this incident.

Observed reproduction

  1. Managed server starts normally.
  2. tools/list succeeds.
  3. First gitea_whoami (or other authenticated tool) retrieves a revoked/stale Keychain credential.
  4. Gitea returns HTTP 401 (invalid username, password or token).
  5. An unhandled RuntimeError escapes the tool boundary (raised from gitea_auth.api_request / related auth resolution).
  6. The client receives EOF instead of a structured tool error.
  7. Both author and reconciler namespaces are affected (any profile whose Keychain item resolves to invalid credentials).
  8. Subsequent calls on the closed transport fail until client reconnect — unacceptable for an auth-class failure.

Related operational note (Keychain multi-account)

Profile token resolution uses security find-generic-password -s <id> -w without an account selector (gitea_config._keychain_token). When multiple Keychain accounts exist for the same service id, the default lookup can return a revoked token even when a valid account-specific entry exists. Credential hygiene is operator-side; this issue owns tool-boundary error mapping and transport survival, not Keychain account selection (though tests must not leak secrets when simulating revoked credentials).

Distinct from related issues

Issue Class Why not a duplicate
#685 Read-only resolver touches mcp_config.json + os._exit(0) on stale runtime Self-kill / config-touch recovery; not HTTP 401 auth mapping
#695 Offline import of MCP internals reconstructs gates Trust-boundary / offline mutation; not structured auth tool errors
#697 Preflight ignores untracked files Workspace purity
#698 Final-report validator crashes Review-report schema
#584 / #543 / #544 Generic transport EOF / reconnect Symptom class; no durable AC for auth→structured error
#678 Expose sanctioned reconnect Recovery UX; not auth error representation
PR #696 (implementation track for related cluster) Do not launch PR #696 reviewer until Keychain recovery succeeds and this transport-survival defect is resolved through canonical workflow

Acceptance criteria

  1. Known Gitea authentication failures are mapped to a sanitized structured MCP tool error.
  2. The result uses the framework’s supported error representation, such as CallToolResult with isError=true, where appropriate.
  3. The response exposes no credential, header, response body secrets, Keychain data, or sensitive configuration.
  4. The stdio transport remains connected after the failed call.
  5. A subsequent tool call returns normally or produces another structured error without EOF.
  6. Authentication failures are distinguishable from authorization (e.g. HTTP 403 insufficient scope), network, configuration, and internal programming failures.
  7. Unexpected exceptions are not silently misclassified as authentication failures.
  8. Sanitized daemon logging includes an actionable reason code without secrets.
  9. Regression tests cover author and reconciler profiles, revoked credentials, invalid credentials, insufficient scope, repeated calls, and transport survival.
  10. Tests prove no environment flag, offline runner, or caller-controlled input can bypass native provenance.
  11. Cross-link #685, #695, #697, #698, and PR #696 where relevant.
  12. Implement in an isolated branches/ worktree and use independent author, reviewer, and merger roles.

Implementation guidance (non-prescriptive)

  • Catch known auth-class failures at the MCP tool boundary (or convert RuntimeError subclasses with stable reason codes before they leave the handler).
  • Prefer typed/sanitized error payloads (reason_code e.g. auth_failed / auth_invalid_token vs authz_insufficient_scope vs network_error vs internal_error).
  • Do not treat all RuntimeError as auth.
  • Do not call os._exit, touch MCP client configs, or restart the daemon on auth failure.
  • Align redaction with existing gitea_auth._redact / audit redactors.
  • Preserve fail-closed behavior: mutations must not proceed after auth failure.

Required tests

  • Author profile: revoked Keychain / invalid token → structured isError (or equivalent); no process exit; second call still gets a structured response.
  • Reconciler profile: same transport-survival contract.
  • Insufficient scope (HTTP 403 with scope message): classified as authorization, not authentication, when distinguishable.
  • Network/config/internal exceptions: not labeled as authentication.
  • Secret leakage scan of tool error text and daemon log reason codes.
  • Provenance: no env flag / offline runner / caller input path that skips native MCP transport for mutations (cross-check with #695 spirit).

Explicit non-goals

  • Do not absorb #685 resolver side-effect removal into this issue.
  • Do not implement offline recovery helpers.
  • Do not auto-refresh or rewrite Keychain secrets from tool code.
  • Do not launch or resume PR #696 formal review until this defect is fixed and Keychain recovery is confirmed.

Canonical issue state

STATE: ready-for-author
WHO_IS_NEXT: author
NEXT_ACTION: Map known Gitea auth failures to sanitized structured MCP tool errors; keep stdio transport alive; regression tests for author+reconciler + transport survival
NEXT_PROMPT:
Role: AUTHOR
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Issue: this issue

1. gitea_whoami + gitea_resolve_task_capability(work_issue) on prgs-author; bind an issue-backed worktree under branches/ (never the root checkout).
2. Map known authentication failures to sanitized structured MCP errors (CallToolResult isError=true or framework equivalent); distinguish auth vs authz vs network vs config vs internal.
3. Ensure stdio transport survives failed auth calls; subsequent calls must not EOF.
4. Sanitized daemon reason codes only — no secrets.
5. Tests per AC 9–10 across author and reconciler (and ideally all role profiles).
6. Cross-link #685/#695/#697/#698/PR #696 in PR body; do not implement those scopes here.
7. PR with Closes reference to this issue; stop; hand off to independent reviewer (not the author identity).
8. Do not launch PR #696 reviewer from this workstream until Keychain recovery + this transport fix are complete.

Required final evidence

PR implementing boundary mapping, sample structured auth error (redacted), transport-survival test output for author and reconciler, and proof that unexpected exceptions are not misclassified as auth.

## Problem Known Gitea authentication failures (revoked/invalid Keychain credentials → HTTP 401) can escape the MCP tool boundary as an unhandled `RuntimeError`. The client then observes **EOF / transport closed** instead of a sanitized structured tool error. The session loses the namespace mid-workflow even though the underlying defect is a normal authentication failure that must remain recoverable without reconnect. This is **not** the #685 resolver self-termination path. Managed logs for this incident identified a distinct authentication-exception path. #685 causation was initially suspected but **not confirmed** for this incident. ## Observed reproduction 1. Managed server starts normally. 2. `tools/list` succeeds. 3. First `gitea_whoami` (or other authenticated tool) retrieves a revoked/stale Keychain credential. 4. Gitea returns HTTP 401 (`invalid username, password or token`). 5. An unhandled `RuntimeError` escapes the tool boundary (raised from `gitea_auth.api_request` / related auth resolution). 6. The client receives **EOF** instead of a structured tool error. 7. Both **author** and **reconciler** namespaces are affected (any profile whose Keychain item resolves to invalid credentials). 8. Subsequent calls on the closed transport fail until client reconnect — unacceptable for an auth-class failure. ### Related operational note (Keychain multi-account) Profile token resolution uses `security find-generic-password -s <id> -w` without an account selector (`gitea_config._keychain_token`). When multiple Keychain accounts exist for the same service id, the default lookup can return a revoked token even when a valid account-specific entry exists. Credential hygiene is operator-side; this issue owns **tool-boundary error mapping and transport survival**, not Keychain account selection (though tests must not leak secrets when simulating revoked credentials). ## Distinct from related issues | Issue | Class | Why not a duplicate | |-------|--------|---------------------| | **#685** | Read-only resolver touches `mcp_config.json` + `os._exit(0)` on stale runtime | Self-kill / config-touch recovery; not HTTP 401 auth mapping | | **#695** | Offline import of MCP internals reconstructs gates | Trust-boundary / offline mutation; not structured auth tool errors | | **#697** | Preflight ignores untracked files | Workspace purity | | **#698** | Final-report validator crashes | Review-report schema | | **#584 / #543 / #544** | Generic transport EOF / reconnect | Symptom class; no durable AC for auth→structured error | | **#678** | Expose sanctioned reconnect | Recovery UX; not auth error representation | | **PR #696** | (implementation track for related cluster) | Do **not** launch PR #696 reviewer until Keychain recovery succeeds **and** this transport-survival defect is resolved through canonical workflow | ## Acceptance criteria 1. Known Gitea authentication failures are mapped to a sanitized structured MCP tool error. 2. The result uses the framework’s supported error representation, such as `CallToolResult` with `isError=true`, where appropriate. 3. The response exposes no credential, header, response body secrets, Keychain data, or sensitive configuration. 4. The stdio transport remains connected after the failed call. 5. A subsequent tool call returns normally or produces another structured error without EOF. 6. Authentication failures are distinguishable from authorization (e.g. HTTP 403 insufficient scope), network, configuration, and internal programming failures. 7. Unexpected exceptions are not silently misclassified as authentication failures. 8. Sanitized daemon logging includes an actionable reason code without secrets. 9. Regression tests cover author and reconciler profiles, revoked credentials, invalid credentials, insufficient scope, repeated calls, and transport survival. 10. Tests prove no environment flag, offline runner, or caller-controlled input can bypass native provenance. 11. Cross-link #685, #695, #697, #698, and PR #696 where relevant. 12. Implement in an isolated `branches/` worktree and use independent author, reviewer, and merger roles. ## Implementation guidance (non-prescriptive) - Catch known auth-class failures at the MCP tool boundary (or convert `RuntimeError` subclasses with stable reason codes before they leave the handler). - Prefer typed/sanitized error payloads (`reason_code` e.g. `auth_failed` / `auth_invalid_token` vs `authz_insufficient_scope` vs `network_error` vs `internal_error`). - Do **not** treat all `RuntimeError` as auth. - Do **not** call `os._exit`, touch MCP client configs, or restart the daemon on auth failure. - Align redaction with existing `gitea_auth._redact` / audit redactors. - Preserve fail-closed behavior: mutations must not proceed after auth failure. ## Required tests - Author profile: revoked Keychain / invalid token → structured `isError` (or equivalent); no process exit; second call still gets a structured response. - Reconciler profile: same transport-survival contract. - Insufficient scope (HTTP 403 with scope message): classified as authorization, not authentication, when distinguishable. - Network/config/internal exceptions: not labeled as authentication. - Secret leakage scan of tool error text and daemon log reason codes. - Provenance: no env flag / offline runner / caller input path that skips native MCP transport for mutations (cross-check with #695 spirit). ## Explicit non-goals - Do not absorb #685 resolver side-effect removal into this issue. - Do not implement offline recovery helpers. - Do not auto-refresh or rewrite Keychain secrets from tool code. - Do not launch or resume PR #696 formal review until this defect is fixed and Keychain recovery is confirmed. ## Canonical issue state ```text STATE: ready-for-author WHO_IS_NEXT: author NEXT_ACTION: Map known Gitea auth failures to sanitized structured MCP tool errors; keep stdio transport alive; regression tests for author+reconciler + transport survival NEXT_PROMPT: Role: AUTHOR Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Issue: this issue 1. gitea_whoami + gitea_resolve_task_capability(work_issue) on prgs-author; bind an issue-backed worktree under branches/ (never the root checkout). 2. Map known authentication failures to sanitized structured MCP errors (CallToolResult isError=true or framework equivalent); distinguish auth vs authz vs network vs config vs internal. 3. Ensure stdio transport survives failed auth calls; subsequent calls must not EOF. 4. Sanitized daemon reason codes only — no secrets. 5. Tests per AC 9–10 across author and reconciler (and ideally all role profiles). 6. Cross-link #685/#695/#697/#698/PR #696 in PR body; do not implement those scopes here. 7. PR with Closes reference to this issue; stop; hand off to independent reviewer (not the author identity). 8. Do not launch PR #696 reviewer from this workstream until Keychain recovery + this transport fix are complete. ``` ## Required final evidence PR implementing boundary mapping, sample structured auth error (redacted), transport-survival test output for author and reconciler, and proof that unexpected exceptions are not misclassified as auth.
Author
Owner

Controller filing / duplicate-check

Canonical Issue State

STATE:
ready-for-author

WHO_IS_NEXT:
author

NEXT_ACTION:
Implement structured auth tool errors and stdio transport survival in an isolated branches/ worktree; hand off to independent reviewer after PR.

NEXT_PROMPT:

Role: AUTHOR
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Issue: #699

1. gitea_whoami + gitea_resolve_task_capability(work_issue) on prgs-author; bind issue-backed worktree under branches/ (never root checkout).
2. Map known Gitea authentication failures to sanitized structured MCP tool errors (CallToolResult isError=true or framework equivalent).
3. Keep stdio transport connected; subsequent calls must not EOF.
4. Distinguish auth vs authorization vs network vs config vs internal; do not misclassify unexpected exceptions as auth.
5. Sanitized daemon reason codes only — no secrets.
6. Regression tests: author + reconciler; revoked/invalid credentials; insufficient scope; repeated calls; transport survival; native provenance non-bypass.
7. Cross-link #685, #695, #697, #698, PR #696; do not absorb those scopes.
8. PR with Closes #699; stop; independent reviewer. Do not launch PR #696 reviewer until #699 is resolved.

WHAT_HAPPENED:
Controller duplicate-checked the auth/transport defect across open and closed issues. No exact match. Filed durable issue #699 with full acceptance criteria. Keychain multi-account recovery restored default service-id lookups for author (jcwalker3) and reviewer (sysadmin). PR #696 formal reviewer was intentionally not launched.

WHY:
HTTP 401 authentication failures must return structured tool errors without terminating stdio. Distinct from #685 resolver self-termination. Durable tracking is required before author implementation.

RELATED_PRS:
PR #696 (hold reviewer until Keychain recovery stays healthy and #699 lands). Cross-links: #685, #695, #697, #698.

BLOCKERS:
none for author start on #699; re-verify gitea_whoami before mutating work

VALIDATION:

  • gitea_whoami prgs-author → jcwalker3 authenticated
  • gitea_whoami prgs-reviewer and prgs-reconciler → sysadmin authenticated
  • gitea_create_issue returned #699 with type:bug and status:ready
  • Open/closed issue search found no exact structured-auth-transport match

LAST_UPDATED_BY:
controller

## Controller filing / duplicate-check ### Canonical Issue State STATE: ready-for-author WHO_IS_NEXT: author NEXT_ACTION: Implement structured auth tool errors and stdio transport survival in an isolated branches/ worktree; hand off to independent reviewer after PR. NEXT_PROMPT: ```text Role: AUTHOR Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Issue: #699 1. gitea_whoami + gitea_resolve_task_capability(work_issue) on prgs-author; bind issue-backed worktree under branches/ (never root checkout). 2. Map known Gitea authentication failures to sanitized structured MCP tool errors (CallToolResult isError=true or framework equivalent). 3. Keep stdio transport connected; subsequent calls must not EOF. 4. Distinguish auth vs authorization vs network vs config vs internal; do not misclassify unexpected exceptions as auth. 5. Sanitized daemon reason codes only — no secrets. 6. Regression tests: author + reconciler; revoked/invalid credentials; insufficient scope; repeated calls; transport survival; native provenance non-bypass. 7. Cross-link #685, #695, #697, #698, PR #696; do not absorb those scopes. 8. PR with Closes #699; stop; independent reviewer. Do not launch PR #696 reviewer until #699 is resolved. ``` WHAT_HAPPENED: Controller duplicate-checked the auth/transport defect across open and closed issues. No exact match. Filed durable issue #699 with full acceptance criteria. Keychain multi-account recovery restored default service-id lookups for author (jcwalker3) and reviewer (sysadmin). PR #696 formal reviewer was intentionally not launched. WHY: HTTP 401 authentication failures must return structured tool errors without terminating stdio. Distinct from #685 resolver self-termination. Durable tracking is required before author implementation. RELATED_PRS: PR #696 (hold reviewer until Keychain recovery stays healthy and #699 lands). Cross-links: #685, #695, #697, #698. BLOCKERS: none for author start on #699; re-verify gitea_whoami before mutating work VALIDATION: - gitea_whoami prgs-author → jcwalker3 authenticated - gitea_whoami prgs-reviewer and prgs-reconciler → sysadmin authenticated - gitea_create_issue returned #699 with type:bug and status:ready - Open/closed issue search found no exact structured-auth-transport match LAST_UPDATED_BY: controller
jcwalker3 added status:in-progress and removed status:ready labels 2026-07-13 12:05:49 -05:00
Author
Owner

Issue claim heartbeat

<!-- gitea-issue-claim-heartbeat:v1 --> **Issue claim heartbeat** - kind: claim - issue: #699 - branch: fix/issue-699-structured-auth-mcp-errors - phase: claimed - profile: prgs-author - pr: none - blocker: none - next_action: create worktree and begin implementation
jcwalker3 added status:pr-open and removed status:in-progress labels 2026-07-13 12:10:18 -05:00
Author
Owner

CTH: Author Handoff

Status: pr_open_awaiting_independent_review
Next owner: reviewer
Current blocker: none
Decision: Implemented #699 structured auth MCP tool errors; opened PR #701 with Closes #699. Scope strictly #699. Author will not self-review, approve, or merge. Do not launch PR #696 reviewer from this workstream.
Proof: head b4d0cb22e452a07c8e816745c704ddb0f43edf0b; pytest structured-auth + api_reliability 39 passed; identity jcwalker3/prgs-author
Next action: Independent reviewer reviews PR #701 at pinned head.
Ready-to-paste prompt: see NEXT_PROMPT below.

Canonical Issue State

STATE:
pr-open

WHO_IS_NEXT:
reviewer

NEXT_ACTION:
Independent review of PR #701 at head b4d0cb22e4 against #699 acceptance criteria

NEXT_PROMPT:

Role: REVIEWER (prgs-reviewer / independent identity — not jcwalker3)
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
PR: #701
Issue: #699
Pinned head: b4d0cb22e452a07c8e816745c704ddb0f43edf0b

1. gitea_whoami + gitea_resolve_task_capability(review_pr) on prgs-reviewer.
2. Review PR #701 only; do not launch PR #696 review.
3. Verify AC: structured isError for auth failures; transport survival; auth vs authz vs network vs internal; no secrets; tests for author+reconciler; scope excludes #685/#695/#697/#698.
4. Submit formal Gitea review (APPROVE or REQUEST_CHANGES) at the pinned head; post CTH: Reviewer Handoff.
5. Do not merge as author identity.

WHAT_HAPPENED:
Author claimed #699, locked branch fix/issue-699-structured-auth-mcp-errors in branches/fix-issue-699-structured-auth-mcp-errors, implemented typed Gitea auth/authz/network/config errors plus FastMCP Tool.run boundary returning CallToolResult isError with reason_code, validated with targeted pytest, pushed, opened PR #701 with Closes #699.

WHY:
HTTP 401 authentication failures must return sanitized structured MCP tool errors without terminating stdio. Distinct from #685 resolver self-termination. Durable author delivery required before independent review.

RELATED_PRS:
PR #701 (Closes #699). PR #696 held — do not launch formal reviewer until #699 lands and Keychain recovery stays healthy.

BLOCKERS:
none

VALIDATION:

  • gitea_whoami prgs-author → jcwalker3 authenticated
  • gitea_lock_issue #699 → live lease on fix/issue-699-structured-auth-mcp-errors
  • gitea_mark_issue start → status:in-progress then status:pr-open after create_pr
  • pytest tests/test_structured_auth_mcp_errors.py tests/test_api_reliability.py → 39 passed
  • gitea_create_pr → PR #701 open base=master head=fix/issue-699-structured-auth-mcp-errors
  • head SHA b4d0cb22e4

LAST_UPDATED_BY:
author (jcwalker3 / prgs-author)

## CTH: Author Handoff Status: pr_open_awaiting_independent_review Next owner: reviewer Current blocker: none Decision: Implemented #699 structured auth MCP tool errors; opened PR #701 with Closes #699. Scope strictly #699. Author will not self-review, approve, or merge. Do not launch PR #696 reviewer from this workstream. Proof: head b4d0cb22e452a07c8e816745c704ddb0f43edf0b; pytest structured-auth + api_reliability 39 passed; identity jcwalker3/prgs-author Next action: Independent reviewer reviews PR #701 at pinned head. Ready-to-paste prompt: see NEXT_PROMPT below. ## Canonical Issue State STATE: pr-open WHO_IS_NEXT: reviewer NEXT_ACTION: Independent review of PR #701 at head b4d0cb22e452a07c8e816745c704ddb0f43edf0b against #699 acceptance criteria NEXT_PROMPT: ```text Role: REVIEWER (prgs-reviewer / independent identity — not jcwalker3) Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools PR: #701 Issue: #699 Pinned head: b4d0cb22e452a07c8e816745c704ddb0f43edf0b 1. gitea_whoami + gitea_resolve_task_capability(review_pr) on prgs-reviewer. 2. Review PR #701 only; do not launch PR #696 review. 3. Verify AC: structured isError for auth failures; transport survival; auth vs authz vs network vs internal; no secrets; tests for author+reconciler; scope excludes #685/#695/#697/#698. 4. Submit formal Gitea review (APPROVE or REQUEST_CHANGES) at the pinned head; post CTH: Reviewer Handoff. 5. Do not merge as author identity. ``` WHAT_HAPPENED: Author claimed #699, locked branch fix/issue-699-structured-auth-mcp-errors in branches/fix-issue-699-structured-auth-mcp-errors, implemented typed Gitea auth/authz/network/config errors plus FastMCP Tool.run boundary returning CallToolResult isError with reason_code, validated with targeted pytest, pushed, opened PR #701 with Closes #699. WHY: HTTP 401 authentication failures must return sanitized structured MCP tool errors without terminating stdio. Distinct from #685 resolver self-termination. Durable author delivery required before independent review. RELATED_PRS: PR #701 (Closes #699). PR #696 held — do not launch formal reviewer until #699 lands and Keychain recovery stays healthy. BLOCKERS: none VALIDATION: - gitea_whoami prgs-author → jcwalker3 authenticated - gitea_lock_issue #699 → live lease on fix/issue-699-structured-auth-mcp-errors - gitea_mark_issue start → status:in-progress then status:pr-open after create_pr - pytest tests/test_structured_auth_mcp_errors.py tests/test_api_reliability.py → 39 passed - gitea_create_pr → PR #701 open base=master head=fix/issue-699-structured-auth-mcp-errors - head SHA b4d0cb22e452a07c8e816745c704ddb0f43edf0b LAST_UPDATED_BY: author (jcwalker3 / prgs-author)
Owner

CTH: Blocker — PR #701 at b4d0cb22e4

Formal verdict: none submitted. The review found request-changes-class security/framework defects, but native reviewer lease state was lost and the formal-review gate now prohibits submission.

Findings

  1. gitea_auth.py:456-464 copies HTTP error bodies into exceptions, while mcp_tool_error_boundary.py:46-67 can return raw text and does not remove arbitrary secrets; :215-229 can log them. Adversarial checks reproduced response-body, Keychain-content, and daemon-log leakage.
  2. mcp_tool_error_boundary.py:277-309 replaces FastMCP Tool.run and catches all exceptions. A real stdio subprocess proved auth-error transport survival but also proved the wrapper swallows SDK UrlElicitationRequiredError and returns internal_error, breaking framework/unrelated-tool semantics.
  3. mcp_tool_error_boundary.py:129-160 classifies arbitrary RuntimeErrors by message substring; :256-261 calls every RuntimeError a known client failure. An unexpected parser RuntimeError was reproduced as authentication.
  4. Generic HTTP 403 remains RuntimeError at gitea_auth.py:313-333 and becomes internal_error, so 403 is not reliably distinct from unexpected internal failure.

Canonical Issue State

STATE:
review-blocked; no formal verdict; request-changes-class defects reproduced

WHO_IS_NEXT:
controller

NEXT_ACTION:
Reconcile or canonically expire the active reviewer lease and repair the reviewer worktree binding; then author fixes the four findings and a fresh independent reviewer reruns the complete workflow at the new pinned head.

NEXT_PROMPT:

Role: CONTROLLER, then AUTHOR, then fresh independent REVIEWER
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Issue: #699
PR: #701
Pinned reviewed candidate: b4d0cb22e452a07c8e816745c704ddb0f43edf0b

1. Do not bypass or seed reviewer lease/session state.
2. Diagnose lease comment 11131 / session 65664-4f248d213d60 and the environment binding to branches/review-pr-654; wait for canonical expiry or use only authorized controller cleanup.
3. Author fixes secret redaction, FastMCP URL-elicitation semantics, RuntimeError over-classification, and generic 403 classification at a new head.
4. Start a fresh prgs-reviewer session; rerun identity/inventory/lease, focused + related + full suite, and the real stdio subprocess test.
5. Submit exactly one formal verdict at the new live head. Do not review or mutate PR #696.

WHAT_HAPPENED:
Independent review used a fresh detached branches worktree at the exact pinned head. Focused and related suites passed, but three adversarial checks failed. During validation the MCP workflow proof and in-session lease disappeared; safe reload found the durable lease active but session_lease null and classified it foreign_active_current_head with exact next action wait.

WHY:
The implementation exposes secrets, changes unrelated FastMCP framework behavior, and can misclassify unexpected RuntimeErrors. Native controls also forbid transferring validation or decision state across the lost lease, so no formal review bypass was attempted.

RELATED_PRS:
PR #701 only. PR #696 was not reviewed, launched, or mutated.

BLOCKERS:
Code blockers: secret leakage; swallowed URL elicitation; RuntimeError misclassification; generic 403 internal misclassification. Workflow blocker: lease 11131 is active but absent in-session, environment/proposed worktree binding disagrees, mutation_eligibility=prohibited. UNBLOCK CONDITION: controller-authorized lease expiry/reconciliation and matching reviewer worktree binding, author remediation at a new head, then a complete fresh native review.

VALIDATION:
39 focused tests passed; 165 related config/MCP/provenance guards passed. Real stdio subprocess failed only after proving auth structured error + subsequent-call survival because URL elicitation became internal_error. Adversarial redaction failed for response-body/Keychain/log secrets. RuntimeError adversarial classification failed. Full suite was not run after the mandatory workflow hard-stop. Worktree and root checkout remained clean; no source edits, commits, pushes, merges, direct APIs, offline helpers, or formal review mutations.

LAST_UPDATED_BY:
prgs-reviewer / sysadmin

## CTH: Blocker — PR #701 at b4d0cb22e452a07c8e816745c704ddb0f43edf0b Formal verdict: none submitted. The review found request-changes-class security/framework defects, but native reviewer lease state was lost and the formal-review gate now prohibits submission. ### Findings 1. `gitea_auth.py:456-464` copies HTTP error bodies into exceptions, while `mcp_tool_error_boundary.py:46-67` can return raw text and does not remove arbitrary secrets; `:215-229` can log them. Adversarial checks reproduced response-body, Keychain-content, and daemon-log leakage. 2. `mcp_tool_error_boundary.py:277-309` replaces FastMCP `Tool.run` and catches all exceptions. A real stdio subprocess proved auth-error transport survival but also proved the wrapper swallows SDK `UrlElicitationRequiredError` and returns `internal_error`, breaking framework/unrelated-tool semantics. 3. `mcp_tool_error_boundary.py:129-160` classifies arbitrary RuntimeErrors by message substring; `:256-261` calls every RuntimeError a known client failure. An unexpected parser RuntimeError was reproduced as authentication. 4. Generic HTTP 403 remains RuntimeError at `gitea_auth.py:313-333` and becomes `internal_error`, so 403 is not reliably distinct from unexpected internal failure. ## Canonical Issue State STATE: review-blocked; no formal verdict; request-changes-class defects reproduced WHO_IS_NEXT: controller NEXT_ACTION: Reconcile or canonically expire the active reviewer lease and repair the reviewer worktree binding; then author fixes the four findings and a fresh independent reviewer reruns the complete workflow at the new pinned head. NEXT_PROMPT: ```text Role: CONTROLLER, then AUTHOR, then fresh independent REVIEWER Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Issue: #699 PR: #701 Pinned reviewed candidate: b4d0cb22e452a07c8e816745c704ddb0f43edf0b 1. Do not bypass or seed reviewer lease/session state. 2. Diagnose lease comment 11131 / session 65664-4f248d213d60 and the environment binding to branches/review-pr-654; wait for canonical expiry or use only authorized controller cleanup. 3. Author fixes secret redaction, FastMCP URL-elicitation semantics, RuntimeError over-classification, and generic 403 classification at a new head. 4. Start a fresh prgs-reviewer session; rerun identity/inventory/lease, focused + related + full suite, and the real stdio subprocess test. 5. Submit exactly one formal verdict at the new live head. Do not review or mutate PR #696. ``` WHAT_HAPPENED: Independent review used a fresh detached branches worktree at the exact pinned head. Focused and related suites passed, but three adversarial checks failed. During validation the MCP workflow proof and in-session lease disappeared; safe reload found the durable lease active but session_lease null and classified it foreign_active_current_head with exact next action wait. WHY: The implementation exposes secrets, changes unrelated FastMCP framework behavior, and can misclassify unexpected RuntimeErrors. Native controls also forbid transferring validation or decision state across the lost lease, so no formal review bypass was attempted. RELATED_PRS: PR #701 only. PR #696 was not reviewed, launched, or mutated. BLOCKERS: Code blockers: secret leakage; swallowed URL elicitation; RuntimeError misclassification; generic 403 internal misclassification. Workflow blocker: lease 11131 is active but absent in-session, environment/proposed worktree binding disagrees, mutation_eligibility=prohibited. UNBLOCK CONDITION: controller-authorized lease expiry/reconciliation and matching reviewer worktree binding, author remediation at a new head, then a complete fresh native review. VALIDATION: 39 focused tests passed; 165 related config/MCP/provenance guards passed. Real stdio subprocess failed only after proving auth structured error + subsequent-call survival because URL elicitation became internal_error. Adversarial redaction failed for response-body/Keychain/log secrets. RuntimeError adversarial classification failed. Full suite was not run after the mandatory workflow hard-stop. Worktree and root checkout remained clean; no source edits, commits, pushes, merges, direct APIs, offline helpers, or formal review mutations. LAST_UPDATED_BY: prgs-reviewer / sysadmin
Owner

Canonical Issue State

STATE:
review-blocked; no formal verdict; request-changes-class defects ratified

WHO_IS_NEXT:
author

NEXT_ACTION:
Wait for lease 65664-4f248d213d60 to canonically expire. The human operator will then clear the stale GITEA_ACTIVE_WORKTREE binding. The author must then remediate the ratified defects at a new head.

NEXT_PROMPT:

Role: AUTHOR
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
Issue: #699
PR: #701

1. Wait for lease 65664-4f248d213d60 to canonically expire or rely on operator-initiated environment cleanup.
2. Fix the four findings on PR #701: secret redaction, FastMCP URL-elicitation semantics, RuntimeError over-classification, and generic 403 classification.
3. Push fixes and post an author handoff at the new head.

WHAT_HAPPENED:
Controller ratified the four findings from the aborted review session. No formal verdict was submitted because the native reviewer lease state was lost due to an unhandled exception crashing the daemon. A durable issue (#702) was filed to track the lease/workspace-binding defect.

WHY:
The implementation exposes secrets, changes unrelated FastMCP framework behavior, and misclassifies unexpected RuntimeErrors. These are controller-ratified blockers.

RELATED_PRS:
PR #701

BLOCKERS:
Author remediation is required for the four findings. The reviewer namespace environment variable GITEA_ACTIVE_WORKTREE must be manually cleared by the operator before the next independent review.

VALIDATION:

  • Verified no formal review exists at head b4d0cb22e452a07c8e816745c704ddb0f43edf0b.
  • Lease disposition: wait.
  • Reviewer binding recovery: operator environment intervention required.
  • Durable tooling issue created: #702.

LAST_UPDATED_BY:
controller

## Canonical Issue State STATE: review-blocked; no formal verdict; request-changes-class defects ratified WHO_IS_NEXT: author NEXT_ACTION: Wait for lease 65664-4f248d213d60 to canonically expire. The human operator will then clear the stale `GITEA_ACTIVE_WORKTREE` binding. The author must then remediate the ratified defects at a new head. NEXT_PROMPT: ```text Role: AUTHOR Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools Issue: #699 PR: #701 1. Wait for lease 65664-4f248d213d60 to canonically expire or rely on operator-initiated environment cleanup. 2. Fix the four findings on PR #701: secret redaction, FastMCP URL-elicitation semantics, RuntimeError over-classification, and generic 403 classification. 3. Push fixes and post an author handoff at the new head. ``` WHAT_HAPPENED: Controller ratified the four findings from the aborted review session. No formal verdict was submitted because the native reviewer lease state was lost due to an unhandled exception crashing the daemon. A durable issue (#702) was filed to track the lease/workspace-binding defect. WHY: The implementation exposes secrets, changes unrelated FastMCP framework behavior, and misclassifies unexpected RuntimeErrors. These are controller-ratified blockers. RELATED_PRS: PR #701 BLOCKERS: Author remediation is required for the four findings. The reviewer namespace environment variable `GITEA_ACTIVE_WORKTREE` must be manually cleared by the operator before the next independent review. VALIDATION: - Verified no formal review exists at head `b4d0cb22e452a07c8e816745c704ddb0f43edf0b`. - Lease disposition: wait. - Reviewer binding recovery: operator environment intervention required. - Durable tooling issue created: #702. LAST_UPDATED_BY: controller
Author
Owner

CTH: Author Handoff

Status: remediation_pushed_awaiting_fresh_independent_review
Next owner: reviewer
Current blocker: none (code blockers from 11133/11136 addressed at new head)
Decision: Remediated all four controller-ratified findings on PR #701. Pushed head 6b675f5c83. Author will not self-review, approve, or merge. Do not launch PR #696 reviewer. Lease/binding work remains #702 only.
Proof: see VALIDATION; prior reviewed candidate was b4d0cb22e4
Next action: Completely fresh independent reviewer (not jcwalker3) at the new pinned head.
Ready-to-paste prompt: see NEXT_PROMPT.

Canonical Issue State

STATE:
pr-open; remediation at new head; ready for fresh independent review

WHO_IS_NEXT:
reviewer

NEXT_ACTION:
Fresh independent prgs-reviewer session reviews PR #701 at head 6b675f5c83 against the four findings and full #699 AC

NEXT_PROMPT:

Role: REVIEWER (prgs-reviewer / independent identity — not jcwalker3)
Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools
PR: #701
Issue: #699
Pinned head: 6b675f5c834b41f9d74e8a54294ff44dddf28ae4
Prior (superseded) candidate: b4d0cb22e452a07c8e816745c704ddb0f43edf0b

1. gitea_whoami + gitea_resolve_task_capability(review_pr) on prgs-reviewer.
2. Ensure GITEA_ACTIVE_WORKTREE is not a stale foreign binding; use a fresh review worktree under branches/ for this head only.
3. Re-verify the four prior findings are fixed:
   - no response-body / Keychain / daemon-log secret leakage (fixed messages only)
   - UrlElicitationRequiredError re-raised; narrow boundary; idempotent install
   - no RuntimeError substring auth heuristics; unexpected RuntimeError is internal_error
   - every HTTP 403 is typed GiteaAuthzError (authorization)
4. Run focused + related + full suite and the real stdio auth→second-call survival test.
5. Submit exactly one formal verdict at the live head; post CTH: Reviewer Handoff.
6. Do not review or mutate PR #696. Do not absorb #685/#695/#697/#698/#702.

WHAT_HAPPENED:
Author resumed existing worktree branches/fix-issue-699-structured-auth-mcp-errors. Fixed secret exposure (fixed messages + typed metadata; fail-closed sanitize), framework semantics (wrap original Tool.run; re-raise UrlElicitationRequiredError; idempotent install), RuntimeError over-classification (typed-only), and HTTP 403 mapping (central classify_http_status; all 403 → GiteaAuthzError). Expanded regressions. Pushed to PR #701.

WHY:
Controller ratified the four findings from the aborted review (comments 11133/11136/11144). Remediation required before a fresh independent formal review at a new head.

RELATED_PRS:
PR #701 (Closes #699). Cross-links only: #685 #695 #697 #698 PR #696. Lease/binding tooling tracked separately as #702 (not absorbed).

BLOCKERS:
none for independent review of the new head; operator may still clear stale GITEA_ACTIVE_WORKTREE for the reviewer namespace if needed (#702)

VALIDATION:

  • identity jcwalker3 / prgs-author
  • worktree branches/fix-issue-699-structured-auth-mcp-errors on fix/issue-699-structured-auth-mcp-errors
  • pytest tests/test_structured_auth_mcp_errors.py tests/test_api_reliability.py tests/test_retry_backoff.py → 66 passed
  • related config/MCP set → 148 passed (earlier related batch)
  • full suite → 2661 passed, 6 skipped, 161 subtests passed
  • head 6b675f5c83 pushed to prgs

LAST_UPDATED_BY:
author (jcwalker3 / prgs-author)

## CTH: Author Handoff Status: remediation_pushed_awaiting_fresh_independent_review Next owner: reviewer Current blocker: none (code blockers from 11133/11136 addressed at new head) Decision: Remediated all four controller-ratified findings on PR #701. Pushed head 6b675f5c834b41f9d74e8a54294ff44dddf28ae4. Author will not self-review, approve, or merge. Do not launch PR #696 reviewer. Lease/binding work remains #702 only. Proof: see VALIDATION; prior reviewed candidate was b4d0cb22e452a07c8e816745c704ddb0f43edf0b Next action: Completely fresh independent reviewer (not jcwalker3) at the new pinned head. Ready-to-paste prompt: see NEXT_PROMPT. ## Canonical Issue State STATE: pr-open; remediation at new head; ready for fresh independent review WHO_IS_NEXT: reviewer NEXT_ACTION: Fresh independent prgs-reviewer session reviews PR #701 at head 6b675f5c834b41f9d74e8a54294ff44dddf28ae4 against the four findings and full #699 AC NEXT_PROMPT: ```text Role: REVIEWER (prgs-reviewer / independent identity — not jcwalker3) Repo: prgs / Scaled-Tech-Consulting / Gitea-Tools PR: #701 Issue: #699 Pinned head: 6b675f5c834b41f9d74e8a54294ff44dddf28ae4 Prior (superseded) candidate: b4d0cb22e452a07c8e816745c704ddb0f43edf0b 1. gitea_whoami + gitea_resolve_task_capability(review_pr) on prgs-reviewer. 2. Ensure GITEA_ACTIVE_WORKTREE is not a stale foreign binding; use a fresh review worktree under branches/ for this head only. 3. Re-verify the four prior findings are fixed: - no response-body / Keychain / daemon-log secret leakage (fixed messages only) - UrlElicitationRequiredError re-raised; narrow boundary; idempotent install - no RuntimeError substring auth heuristics; unexpected RuntimeError is internal_error - every HTTP 403 is typed GiteaAuthzError (authorization) 4. Run focused + related + full suite and the real stdio auth→second-call survival test. 5. Submit exactly one formal verdict at the live head; post CTH: Reviewer Handoff. 6. Do not review or mutate PR #696. Do not absorb #685/#695/#697/#698/#702. ``` WHAT_HAPPENED: Author resumed existing worktree branches/fix-issue-699-structured-auth-mcp-errors. Fixed secret exposure (fixed messages + typed metadata; fail-closed sanitize), framework semantics (wrap original Tool.run; re-raise UrlElicitationRequiredError; idempotent install), RuntimeError over-classification (typed-only), and HTTP 403 mapping (central classify_http_status; all 403 → GiteaAuthzError). Expanded regressions. Pushed to PR #701. WHY: Controller ratified the four findings from the aborted review (comments 11133/11136/11144). Remediation required before a fresh independent formal review at a new head. RELATED_PRS: PR #701 (Closes #699). Cross-links only: #685 #695 #697 #698 PR #696. Lease/binding tooling tracked separately as #702 (not absorbed). BLOCKERS: none for independent review of the new head; operator may still clear stale GITEA_ACTIVE_WORKTREE for the reviewer namespace if needed (#702) VALIDATION: - identity jcwalker3 / prgs-author - worktree branches/fix-issue-699-structured-auth-mcp-errors on fix/issue-699-structured-auth-mcp-errors - pytest tests/test_structured_auth_mcp_errors.py tests/test_api_reliability.py tests/test_retry_backoff.py → 66 passed - related config/MCP set → 148 passed (earlier related batch) - full suite → 2661 passed, 6 skipped, 161 subtests passed - head 6b675f5c834b41f9d74e8a54294ff44dddf28ae4 pushed to prgs LAST_UPDATED_BY: author (jcwalker3 / prgs-author)
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

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