Operator Actions — Append-Only Audit

Every mutating endpoint in jobcache-ops-api writes a row to operator_actions before dispatching the actual upstream call. The MCP wraps the same endpoints, so MCP-driven recovery is just as auditable as UI-driven recovery.

The table lives in CockroachDB. Schema in jobcache/migrations/add-operator-actions.sql. Writer helper in jobcache/ops/api/src/lib/audit.ts.

Canonical action enum

The cockpit emits exactly these action values today:

action target_type Meaning
rerun_scrape scrape_run Re-execute the last failed scrape for a source
pause_source source Soft-disable a source so the scheduler skips it
resume_source source Clear the pause flag
reset_schema_drift source Clear the drift flag after operator investigation
pin_source_note source Attach or replace the operator note on the source matrix row
state_badge_override source Manual yellow/red pin; auto-expires after 4h

The column itself is unconstrained STRING, so adding a new action means a new row here in the doc and a new code path. There is no schema bump.

Three indexes for three queries

  • idx_operator_actions_ts — recency (the audit log panel)
  • idx_operator_actions_target — per-target history (source detail drill-down)
  • idx_operator_actions_action — per-action filter (e.g. "show me every pause_source this week")

Append-only on purpose

There is no UPDATE and no DELETE path exposed from the cockpit. If a row is mistaken, the response is another row (e.g. resume_source after a wrong pause_source), not an edit. The forensic trail must survive operator error.

No automatic purge today. When log volume becomes a concern, a separate retention job becomes its own change — explicitly out of scope for this table.

Why this pairs with scrape_events

scrape_events records what the system did. operator_actions records what the operator did. Together they answer: "what was the source's state, who acted on it, when, and what happened next?" The cockpit's source-detail drill-down stitches the two tables in the UI; the API exposes them as separate routes (/audit and /changes/stream).

See also

  • jobcache/migrations/add-operator-actions.sql — schema.
  • jobcache/ops/api/src/lib/audit.ts — writer.
  • jobcache/ops/api/src/routers/recovery.ts — mutating routes that emit audit rows.
  • scrape-event-log.md — sibling table for scrape attempts.
  • wiki/content/studies/cockpit-vision/jobcache-cockpit.md — UI surface for the audit log.
Source: jobcache/wiki/content/architecture/operator-actions.md