Adds docs/architecture/mcp-restart-governance.md, the restart-governance/v1 ADR defining who may restart the MCP control plane and under what conditions. - Recovery ladder (reconnect -> rebind -> scoped restart -> full restart -> host) with restart stated as the last resort. - Authorization matrix across author/reviewer/merger/reconciler/controller/ operator/admin; no LLM worker role may perform or authorize a full or host restart. - v1 authority decision recorded: controller approval + automated safety gates; quorum deferred to a superseding ADR. - Break-glass path with pre-declared incident and mandatory post-hoc audit. - Ambiguous policy state denies restart. - Stable policy IDs RG-01..RG-08 for later enforcement code to bind to. Cross-links the ADR from docs/safety-model.md and docs/webui-deployment.md, and adds tests/test_mcp_restart_governance_docs.py asserting acceptance criteria 1-5. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
11 KiB
ADR: MCP restart governance and authorization policy
- Status: Accepted (policy effective immediately for LLM and operator sessions; enforcement tooling may lag)
- Date: 2026-07-23
- Tracking issue: #656
- Policy version:
restart-governance/v1 - Related:
- Umbrella: #655 — MCP restart / health hardening umbrella
- Vision: #652 — control-plane restart vision
- Roadmap: #653 — restart hardening roadmap
- Coordinator: #630 — forbids process-kill recovery
- Break-glass / console approval: #642
- Transport recovery: #591, #584 — EOF / transport-flap self-recovery
- Stable-control runtime split:
docs/architecture/mcp-stable-control-runtime-policy-adr.md(#615) - Client-namespace health:
docs/mcp-namespace-health.md(#543) - Reconnect-only EOF recovery:
docs/mcp-namespace-eof-recovery.md
1. Context
The Gitea MCP server is the control plane for real issue and PR mutations
(create, comment, lock, review, merge, reconcile). The same process serves every
role namespace (gitea-author, gitea-reviewer, gitea-merger,
gitea-reconciler, gitea-controller) and holds the in-memory capability-gate
code loaded at startup.
Restarting that process is destructive to concurrent work:
- It resets every session's identity, preflight, and capability-lease binding.
- It can interrupt a mutation mid-critical-section (a lock acquire, a review submit, a merge), leaving durable state half-written.
- Relaunching from the wrong checkout or worktree silently changes which code the control plane runs, defeating master-parity gates (#420 / #615).
Today there is no durable written policy stating who may restart MCP, under what conditions, that restart is a last resort, and how controller approval, automated safety gates, and break-glass interact. Operators and LLM sessions therefore invent restart behavior ad hoc, which makes concurrent multi-role work unsafe. #630 and #642 need this policy as their backbone.
This ADR defines that policy. It does not implement coordinator code or HA multi-instance restart (those are later children of #655).
2. Decision
2.1 v1 decision (recorded)
Restart authority in v1 is controller approval + automated safety gates.
A restart of the stable control runtime is authorized only when both hold:
- A controller role explicitly approves the restart, recording an audit entry (who, why, scope, affected sessions), and
- The automated safety gates pass: a completed drain acknowledgement (no affected session is mid-critical-section) or a declared break-glass incident (§2.5).
Quorum among multiple controllers is not required day-one. It is deferred unless a later investigation (tracked under #653) proves single-controller approval is insufficient. This ADR records the v1 decision so enforcement code (#630) has a fixed target; changing it requires a superseding ADR.
2.2 Restart is a last resort — the recovery ladder
Restart is the last rung. Before any restart, exhaust the narrower recoveries, in order:
- Reconnect the IDE/client MCP namespace (transport EOF,
client is closing: EOF, transient#584flap). No process change. Seedocs/mcp-namespace-eof-recovery.md. - Refresh / rebind the session workspace: re-run
gitea_whoami,gitea_resolve_task_capability, and pass an explicit validatedworktree_path. Fixes stale session context without touching the process. - Scoped restart of a single misbehaving namespace/service (where the deployment supports per-service restart) rather than the whole control plane.
- Full restart of the stable control runtime process — operator-owned, controller-approved, drained.
- Host / infrastructure restart — the broadest action; same authorization as a full restart plus infrastructure ownership.
A session must try rungs 1–2 and record why they were insufficient before requesting a restart at rung 3 or above. Skipping straight to restart is a policy violation.
2.3 Authorization matrix
| Role | Reconnect (1) | Refresh/rebind (2) | Scoped restart (3) | Full restart (4) | Host restart (5) |
|---|---|---|---|---|---|
| author | self | self | request only | forbidden | forbidden |
| reviewer | self | self | request only | forbidden | forbidden |
| merger | self | self | request only | forbidden | forbidden |
| reconciler | self | self | request only | forbidden | forbidden |
| controller | self | self | approve (+gates) | approve (+gates) | request to operator |
| operator | self | self | execute (controller-approved) | execute (controller-approved) | execute (controller-approved) |
| admin | self | self | execute | execute | execute (break-glass) |
Legend: self = may perform for its own client session; request only = may raise a restart request but not authorize or execute it; approve = may authorize under §2.1 gates; execute = may perform the process action after the authorization is recorded.
Key invariants:
- No LLM worker role (author/reviewer/merger/reconciler) may perform or authorize a full or host restart. They may only reconnect/rebind their own client and file a restart request.
- Controller approval authorizes; operator/admin executes. The approving controller and the executing operator may be the same human, but both the approval and the execution are audited.
- Privileged process actions (full restart, host restart) are reserved to operator/admin, never to an automated worker.
2.4 Approved conditions
A restart at rung 3+ is approved only under one of these recorded conditions:
- No affected sessions: the control plane has no live session that would be interrupted (verified, not assumed).
- Full drain acknowledged: every affected session has drained (no open critical section — no held mutation lease mid-write) and the drain is acknowledged in the audit record.
- Controller + gates: controller approval plus passing automated safety gates (§2.1), the standard v1 path.
- Quorum: not required in v1; reserved for a future superseding ADR.
- Break-glass: an incident-backed emergency exception (§2.5).
Restart never bypasses mutation gates mid-critical-section. Drain before restart is mandatory except under break-glass with a declared incident.
2.5 Break-glass
Break-glass is a separate, narrower authorization path for emergencies where the normal drain-and-approve path cannot complete (e.g. the control plane is wedged and cannot drain).
Break-glass conditions:
- A declared incident record exists (id, timestamp, declarer) before the action.
- The action is taken by operator or admin authority only — never by an LLM worker role, and never unilaterally by an operator with active peers when a controller is reachable.
- The scope is the minimum necessary rung of the ladder.
- A mandatory post-hoc audit entry is filed: what was restarted, why the normal path was impossible, which sessions were affected, and the incident id.
Break-glass suspends the drain requirement, not the audit requirement.
2.6 Explicit prohibitions
- A unilateral LLM or operator full restart while active peer sessions exist is forbidden. An LLM worker role must not kill, restart, or relaunch the MCP process; a lone operator must not full-restart over live peer work without controller approval or a break-glass incident.
- Process-kill recovery is forbidden as a routine tool (#630). This ADR does not introduce a kill path.
- Ambiguous policy state denies restart (§4).
3. Security requirements
- Full restart and host restart are privileged; only operator/admin execute them, only after a controller approval or break-glass incident is recorded.
- Break-glass is a distinct authorization path with its own audit mandate; it is never the default and never silent.
- Every approval and every restart action is audited (who approved, who executed, scope, affected sessions, condition, policy version). No restart is authorized without a durable audit entry.
4. Failure behavior
Ambiguous policy → deny restart. If it cannot be established that a restart is authorized under §2 — unknown affected-session state, missing controller approval, absent break-glass incident, or an unclassifiable request — the safe action is to refuse the restart and stop with a recovery report, never to restart on assumption.
5. Policy IDs (for enforcement code)
Enforcement code (#630 coordinator, #642 console approval) binds to these stable policy identifiers rather than to prose:
| Policy ID | Statement |
|---|---|
RG-01 |
Restart is last resort; rungs 1–2 must be tried and recorded first (§2.2). |
RG-02 |
v1 authority = controller approval + automated safety gates (§2.1). |
RG-03 |
No LLM worker role performs or authorizes full/host restart (§2.3). |
RG-04 |
Full/host restart executed by operator/admin only, post approval (§2.3). |
RG-05 |
Drain before restart is mandatory except break-glass with incident (§2.4). |
RG-06 |
Break-glass requires a pre-declared incident and post-hoc audit (§2.5). |
RG-07 |
Unilateral LLM/operator full restart with active peers is forbidden (§2.6). |
RG-08 |
Ambiguous policy state denies restart (§4). |
The restart-governance/v1 policy version field is emitted on future
restart audit events so approvals can be reconciled against the policy revision
in force.
6. Dogfooding
Gitea-Tools governs its own MCP control plane by this policy. Author, reviewer, merger, and reconciler sessions operating on this repository use the recovery ladder (§2.2) — reconnect and rebind, never self-restart — and any real restart of the Gitea-Tools stable control runtime follows the controller-approval + drain path defined here.
7. Acceptance and cross-links
This ADR is the authoritative restart-governance policy. It must stay cross-linked from the safety model and the web-console deployment boundary:
docs/safety-model.md§ Process restart governance references this ADR.docs/webui-deployment.mdreferences this ADR for restart/reload disposition.
It is linked to its issue lineage — umbrella #655, vision #652, roadmap #653, coordinator #630, and break-glass / console approval #642 — in § Related above.
8. Non-goals
- Implementing the restart coordinator or approval state machine (#630, later children of #655).
- Implementing HA multi-instance restart or quorum machinery.
- Introducing any process-kill or auto-restart tool; existing auto-restart behavior must be inventoried before any new restart tool is enabled.