Bind mutation/credential paths to a process-local native MCP runtime so env spoofing, direct imports, and offline helpers cannot reconstruct session gates after native transport failure. Quarantine contaminated formal reviews under controller authority and honor quarantine in review feedback, merge eligibility, merge mutation, and canonical handoff validation. Add regression coverage for the second (PR #694 / review 427) incident class.
78 lines
3.0 KiB
Markdown
78 lines
3.0 KiB
Markdown
# MCP daemon import and native-transport guard (#558 / #695)
|
|
|
|
## Problem
|
|
|
|
During deadlock debugging and the PR #694 incident (#695), agents imported
|
|
`gitea_mcp_server` or ran credential helpers from a raw shell / offline helper,
|
|
bypassing native MCP transport, preflight purity, and role gates. Contaminated
|
|
formal reviews then looked identical to native approvals.
|
|
|
|
## Rule
|
|
|
|
Mutation auth, keychain fill, and controller quarantine require a **native MCP
|
|
transport runtime** established only by the official entrypoint.
|
|
|
|
| Context | Allowed |
|
|
|---------|---------|
|
|
| Official MCP entrypoint (`mcp_server.py` / `gitea_mcp_server` `__main__`) calls `mark_sanctioned_daemon()` and holds a process-local runtime token | yes |
|
|
| pytest (hermetic unit tests) | yes |
|
|
| `GITEA_MCP_SANCTIONED_DAEMON=1` alone (no process-local native runtime) | **no** (#695) |
|
|
| `GITEA_ALLOW_DIRECT_MCP_IMPORT=1` in LLM sessions | **no** — never set in agent sessions |
|
|
| `GITEA_ALLOW_KEYCHAIN_CLI=1` in LLM sessions | **no** — human operator only |
|
|
| bare `python -c 'import gitea_mcp_server; …'` or offline runners | **no** |
|
|
| keychain fill outside native/pytest | **no** |
|
|
|
|
Native runtime is **process-local**: a random token bound to the daemon PID.
|
|
It is never reconstructed from environment variables, session-state files, or
|
|
importing internals in a fresh Python process.
|
|
|
|
## Contaminated review quarantine (#695 AC8)
|
|
|
|
Controller/reconciler/merger profiles may call
|
|
`gitea_quarantine_contaminated_review` with explicit confirmation:
|
|
|
|
```text
|
|
QUARANTINE CONTAMINATED REVIEW <review_id> PR <pr_number>
|
|
```
|
|
|
|
Quarantine records are durable under the MCP session-state root and are
|
|
**honored** by:
|
|
|
|
- `gitea_get_pr_review_feedback` (quarantined approvals do not authorize merge)
|
|
- `gitea_check_pr_eligibility` action=`merge`
|
|
- `gitea_merge_pr` (mutation)
|
|
- merger lease adoption paths that read `approval_at_current_head`
|
|
|
|
Forensic Gitea reviews and historical comments are **never deleted**.
|
|
|
|
## STOP after native MCP failure (AC10)
|
|
|
|
If the native MCP namespace dies (EOF, capability disconnect, session death):
|
|
|
|
1. **STOP.** State BLOCKED + DIAGNOSE.
|
|
2. Do **not** import `gitea_mcp_server` from a standalone process.
|
|
3. Do **not** run `offline_mcp_helper.py`, `offline_mcp_runner.py`,
|
|
`run_quarantine.py`, or any offline mutation helper.
|
|
4. Do **not** set direct-import, keychain-bypass, or raw-token environment
|
|
variables.
|
|
5. Reconnect / restart the official MCP daemon; resume only via native tools.
|
|
|
|
Any further native MCP failure is a hard stop. Do not construct another fallback.
|
|
|
|
## Canonical approval claims (AC7)
|
|
|
|
Comments that claim `approved` / `ready-to-merge` / `WHO_IS_NEXT: merger` /
|
|
`MERGE_READY: true` must include:
|
|
|
|
```text
|
|
NATIVE_REVIEW_PROOF: transport=native_mcp; …
|
|
```
|
|
|
|
Claims that cite offline/import helpers are rejected even if a proof line is
|
|
present.
|
|
|
|
## Operator note
|
|
|
|
LLM sessions must never set allow-direct-import, allow-keychain-cli, or raw
|
|
token overrides. Those are human-only escape hatches outside agent workflows.
|