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]>
1.7 KiB
1.7 KiB
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
- Allocator (
allocate_next_work): while draining, returnsoutcome=waitwithreason_code=maintenance_drain_assignment_stoppedfor dry-run and apply. - Mutation preflight (
verify_preflight_purity): non-allowlisted mutation tasks raiseMaintenanceDrainErrorwith a typed next action. - 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.