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.