Add durable per-repo drain state, allocator assignment stop, mutation deferral with a safety allowlist, observable status, and capability-gated enter/exit tools. Drain proof/restart gate remain #661. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
46 lines
1.7 KiB
Markdown
46 lines
1.7 KiB
Markdown
# MCP maintenance-drain mode (#659)
|
|
|
|
Graceful **maintenance drain** stops new work assignment and defers non-allowlisted
|
|
mutations so sessions can finish critical handoffs and checkpoint before a
|
|
restart. It is **not** a restart authorization: the drain *proof* and apply gate
|
|
remain #661.
|
|
|
|
## State
|
|
|
|
Per repository scope (`remote`/`org`/`repo`) in the control-plane DB table
|
|
`maintenance_drain` (schema v6):
|
|
|
|
| State | Meaning |
|
|
|-------|---------|
|
|
| `inactive` | Normal operation (also: no row) |
|
|
| `draining` | Assignment stopped; non-allowlisted mutations deferred |
|
|
|
|
Enter/exit transitions are audited as `maintenance_drain_enter` /
|
|
`maintenance_drain_exit` events.
|
|
|
|
## Tools
|
|
|
|
| Tool | Permission | Effect |
|
|
|------|------------|--------|
|
|
| `gitea_maintenance_drain_status` | `gitea.read` | Observe drain (every session) |
|
|
| `gitea_enter_maintenance_drain` | `runtime.maintenance_drain` | Enter drain (capability-gated) |
|
|
| `gitea_exit_maintenance_drain` | `runtime.maintenance_drain` | Exit drain |
|
|
|
|
`runtime.maintenance_drain` is intentionally **not** a `gitea.*` op, so ordinary
|
|
author profiles cannot enter drain by accident.
|
|
|
|
## Enforcement
|
|
|
|
1. **Allocator** (`allocate_next_work`): while draining, returns `outcome=wait`
|
|
with `reason_code=maintenance_drain_assignment_stopped` for dry-run and apply.
|
|
2. **Mutation preflight** (`verify_preflight_purity`): non-allowlisted mutation
|
|
tasks raise `MaintenanceDrainError` with a typed next action.
|
|
3. **Allowlist** (safety only): heartbeats, lease release/abandon, session
|
|
checkpoints, enter/exit drain. Reads always work.
|
|
|
|
## Restart relationship
|
|
|
|
Drain mode prepares the blast radius. Restart apply still requires a clean
|
|
`DrainProof` (#661) or authorized break-glass. Status payloads never claim
|
|
restart permission.
|