Skip to content

feat(agent-actions): the global kill-switch write path has no operable route (setGlobalAgentFrozen is uncalled) #2359

Description

@JSONbored

Parent: #1936

Problem

setGlobalAgentFrozen(env, frozen, updatedBy) (src/db/repositories.ts) — the write side of the DB-backed global agent kill-switch documented as "an operator flips with one row (no redeploy)" — has zero callers anywhere in src/. There is no API route, no MCP tool, and no admin surface that invokes it. The only way to actually flip global_agent_controls.frozen today is a direct SQL statement against the D1 database (e.g. via wrangler d1 execute).

Found while fixing #2125 (the kill-switch's fail-open observability gap): closing the "silent failure" half of that issue doesn't help much if there's no application-level way to set the switch in the first place. The read side (isGlobalAgentFrozen) and the /status health surface (defaultOpsHealthDeps.isFrozen) are both fully wired — only the write path is missing.

Requirements

  • An authenticated, operator-only way to read and flip the global kill-switch without shelling into the database.
  • Must reuse the existing isAuthorizedGitHubSessionLogin/operator-scope model (the same authority tier that already bypasses per-repo scope elsewhere), not a new auth mechanism.
  • Should be reachable from at least one of: a REST route (/v1/app/..., matching the existing operator-only path prefix) or an MCP tool (mirroring gittensory_get_fleet_analytics's requireOperatorAccess pattern).

Deliverables

  • Add a route (or MCP tool) that calls setGlobalAgentFrozen, gated by the same operator-only check used elsewhere (requireOperatorAccess-equivalent).
  • A companion read endpoint/tool surfacing the current frozen state (today only visible indirectly via /status's broader health snapshot).
  • Read-after-write verification: after writing, re-read the row and confirm it reflects the intended value before reporting success, surfacing a clear error if it doesn't (closes the incident-window race where a write could appear to succeed but not actually be confirmed under a degraded D1).
  • Add tests: operator can set/clear the flag and read it back; a non-operator session is denied.

Acceptance criteria

  • An authorized operator can freeze/unfreeze the fleet through the application (API or MCP) without direct database access.
  • A non-operator identity is denied.
  • The write is confirmed via a read-after-write check before the caller is told it succeeded.

Expected outcome

The kill-switch documented as "an operator flips with one row (no redeploy)" is actually operable that way, closing the gap between the read/observability side (already correct) and the write side (currently unreachable except via raw SQL).

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions