Operator API
The unmerged parity Worker's route-specific auth, response envelopes, reports and mutation contracts.
Branch boundary
This reference describes son-of-anton-operator-parity/cloudflare/ on unmerged feat/greptile-operator-parity. It is not the public API of the deployed-engine lineage, son-of-anton-review on feat/cloudflare-native. Native ingress serves health and GitHub webhooks, not these operator routes.
The engine's separate Node dashboard exposes GET-only snapshot, PR and trace routes. Its /operator/api/trace?id=... and /operator/api/trace-stats are not parity Worker routes. See Dashboard for the Node surface.
Sources: parity cloudflare/src/worker.js:93-157; engine cloudflare-native/src/ingress.js:264-273, src/operator-dashboard.js:639-687.
Authentication
Send Authorization: Bearer <token>. The parity Worker's token resolver prefers SON_OF_ANTON_<NAME> over legacy GILF_<NAME>, using nullish fallback. An empty canonical value does not fall through to the legacy value. This is not a general ANTON_ alias for engine settings.
| Legacy variable | Accepted route class |
|---|---|
GILF_OPERATOR_READ_TOKEN | Ordinary operator GET routes, except /operator/api/keys and descendants |
GILF_OPERATOR_ADMIN_TOKEN | Key management including GET; POST queue repair; PATCH repo config; non-GET memory/settings/SCM |
GILF_OPERATOR_COMMAND_TOKEN | POST command creation |
GILF_OPERATOR_BRIDGE_TOKEN | PATCH command updates; GET command list/detail |
GILF_QUEUE_ADMIN_TOKEN | /queue/jobs, /queue/stats |
GILF_QUEUE_ENQUEUE_TOKEN | /queue/enqueue |
GILF_QUEUE_WORKER_TOKEN | /queue/claim, /queue/ack, /queue/fail, /queue/renew |
Missing or mismatched static tokens return 401 with ok: false, error: unauthorized. Token classes are not hierarchical: the admin token is not automatically valid for command creation or ordinary reads. Static service calls can set x-operator-actor; the default is service-admin. This is attribution supplied by the service-token holder, not separate human authentication.
Sources: parity cloudflare/src/env.js:1-9; cloudflare/src/worker.js:27-81,115-135,159-167.
Scoped API keys
Admin-only POST /operator/api/keys accepts name and optional scopes. Allowed scopes are read and memory:write; omitted scopes default to read. Creation returns HTTP 201 with ok, key, token and apiBaseUrl. The anton_ token contains 64 hex characters after its prefix and is returned only on creation. Storage keeps its SHA-256 hash and metadata, including a 14-character display prefix.
A dynamic key with read may GET the snapshot, PR, repos, traces, reports, memory, SCM and Test Lab route families, plus exactly /operator/api/settings/usage. It cannot read general settings, commands, analytics, webhook history or key management through that scope. A memory:write key may make memory mutations except source-integration preview. Scope permission does not create nonexistent routes.
GET /operator/api/keys?q=... lists metadata. POST /operator/api/keys/:id/revoke revokes a key. A revoked or invalid key fails authentication; an authenticated key used outside its route scope receives 403.
Sources: parity src/operator-api-keys.js:31-45,65-112; cloudflare/src/operator-api-keys-api.js:49-75; cloudflare/src/worker.js:117-127.
Read routes and envelopes
There is no universal ok envelope. Snapshot, PR detail and reports have their own schema envelopes; ZIP export is binary. JSON helpers generally set cache-control: no-store.
| Route | Parameters | Success shape |
|---|---|---|
GET /health | None; unauthenticated | ok, service: gilf-pr-review-queue |
GET /operator/api/snapshot | view, q, repo, status | schema: son-of-anton.operator.v1, generatedAt, ttlSeconds: 15, view, data |
GET /operator/api/pr | repo, number | schema, generatedAt, data containing runs, findings, events and publication ledger |
GET /operator/api/repos | None | ok, repos |
GET /operator/api/webhooks | status, limit | ok, deliveries |
GET /operator/api/webhooks/:deliveryId | Encoded ID | ok, delivery |
GET /operator/api/analytics | None required | ok, analytics, including queue projection and at most 100 failure reasons |
GET /operator/api/traces | repo, prNumber or pr, reviewKey, runId, status, limit | ok, traces |
GET /operator/api/traces/:traceId | Encoded ID | ok, trace, spans as siblings |
GET /operator/api/commands | status, limit | ok, commands |
GET /operator/api/commands/:id | Encoded ID | ok, command |
Snapshot views are pull-requests (fallback), analytics, memory and settings. Pull-request snapshot items are capped at 100. Webhook, trace and command list limits default to 50 and are clamped to 1–100, with noninteger input falling back to 50. Command status filters accept queued, running, succeeded or failed.
Trace summaries expose identity, timing, status and attributes. They do not return top-level cost/token totals or span counts. Those values are available on detail spans, whose fields include spanId, parentSpanId, kind, inputTokens, outputTokens and costUsd. Detail does not expose input/output bodies. Missing trace, webhook or command IDs return 404.
Sources: parity cloudflare/src/review-state-api.js:575-639,641-690,835-923; cloudflare/src/review-trace-queries.js:14-64,73-132; cloudflare/src/worker.js:97-99.
Reports
GET /operator/api/reports accepts each of these parameters at most once. Unknown or duplicate parameters are rejected.
| Parameter | Values/defaults |
|---|---|
repo | owner/name |
author, team, q | Text, at most 300 characters; repo has the same length limit |
from, to | Valid YYYY-MM-DD; inclusive UTC; from must not follow to |
granularity | day (default), week, month |
severity | P0, P1, P2, P3, info, unknown |
status | open, addressed, not_reobserved, unknown |
security | all (default), true, false, unknown |
page | 1–100000, default 1 |
pageSize | 1–100, default 25 |
The response has schema: son-of-anton.reports.v1, filters/options, summary, comparison, series, rankings, coverage, notes and paginated findings, reviewed PRs and comments. A preceding-period comparison is generated only when both date bounds are explicit. Findings return nullable location fields; the API does not invent line numbers when the producer omitted them.
“Addressed” requires a resolution claim plus recorded evidence; a finding disappearing from a later review is not by itself a fix. Preserve the report's notes when interpreting metrics.
Source loading is bounded: 10000 runs, 10000 heads, 2000 configs, 30000 ledger rows, 30000 traces, 30000 findings, 1000 findings per run, 2000 per PR, and 20 MiB input. Exceeding a report bound returns 413 rather than a silently partial source report. Source history is primarily narrowed by repository; a shorter date interval does not necessarily avoid a source-history limit.
GET /operator/api/reports/export uses the report filters and returns a ZIP, with a 20 MiB export bound. Do not parse it as JSON. Report errors use error and code (report_error or report_too_large), not a universal ok: false shape.
Sources: parity cloudflare/src/review-reports-api.js:4-6,42-132,145-179,309-354.
Command creation and updates
The API persists command events; it does not run reviews inside the request handler. A bridge/consumer must process them. A 202 response means queued command, not completed review.
All routes below have prefix /operator/api:
| Route | Accepted body fields |
|---|---|
POST /commands/requeue | Either reviewKey or repo plus number; optional variant, reason, actorId, commandId |
POST /commands/retry-publish | reviewKey, optional reason, actorId, commandId |
POST /commands/replay-webhook | deliveryId, optional force, reason, actorId, commandId |
PATCH /commands/:id | status, optional startedAt, completedAt, error, result |
For a parity Worker URL in BASE and a configured command token:
curl --fail-with-body -sS "$BASE/operator/api/commands/requeue" \
-H "Authorization: Bearer $GILF_OPERATOR_COMMAND_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: operator-review-request-123' \
--data '{"repo":"owner/name","number":123,"reason":"operator_force_review"}'Use a new idempotency key for each intended new command. The header takes precedence over body commandId. The handler validates the request, then returns an existing ID as HTTP 200 with created: false; a new command returns 202 with created: true. It does not compare an existing command's payload with the new payload. Concurrent creation is not implemented as a single upsert.
Transitions allow the same status, queued to running, and running to succeeded or failed; other transitions return 409. A processed/succeeded webhook needs force: true to replay. sync-repositories commands cannot be updated through the generic PATCH route; they are owned by the native live cron bridge.
Sources: parity cloudflare/src/review-state-api.js:328-387,423-445,934-940.
Repository configuration and queue repair
PATCH /operator/api/repos/:encodedRepo accepts enabled, branches, validation, model, alerts and reason. Encode owner/name as one path segment, such as owner%2Fname.
branches:include,excludestring lists.validation:providerinlocal,crabbox,e2b,shadow;codeChangesOnlyboolean. This is the legacy config schema, not the native executor-name list.model:provider,model,fallbackProvider,fallbackModel,reasoningEffort.alerts:telegramboolean andtargetstring.
Unknown fields are rejected. Acceptance into parity storage is not proof that an unmerged native deployment consumes the field.
POST /operator/api/queue/requeue-dead accepts jobKey, resetAttempts, reason, actorId. POST /operator/api/queue/release-lease accepts jobKey or receiptId, force, reason, actorId. These repair the parity Durable Object queue, not native Cloudflare Queue messages. The handler performs repair before recording its audit event; the two are not atomic.
Sources: parity cloudflare/src/review-state-api.js:254-294,525-572; cloudflare/src/queue-do.js:282-318.
Memory, settings, SCM and Test Lab
| Family | Implemented routes under /operator/api |
|---|---|
| Memory | GET /memory/integrations; POST /memory/integrations/preview; GET,POST /memory/contexts; GET,PATCH,DELETE /memory/contexts/:id; GET,POST /memory/clusters; PATCH,DELETE /memory/clusters/:id; GET /memory/knowledge; GET,PUT /memory/knowledge/document |
| Settings | GET,PATCH /settings; GET /settings/audit?q&limit&offset; GET /settings/usage?from&to |
| Keys | GET,POST /keys; POST /keys/:id/revoke |
| SCM | GET /scm; POST /scm/sync; DELETE /scm/alerts/:id |
| Test Lab | GET /test-lab; GET /test-lab/:id |
Memory document GET uses repo and path query parameters; PUT passes its update in JSON. Memory context/cluster deletes and SCM alert dismissal require a body containing revision. SCM sync accepts an empty JSON object and returns 202 with a command. Test Lab details and limits are in Test Lab.
Sources: parity cloudflare/src/review-memory-api.js:48-118; cloudflare/src/review-policy-api.js:48-63; cloudflare/src/operator-api-keys-api.js:49-75; cloudflare/src/scm-api.js:23-41; cloudflare/src/test-lab-api.js:314-342.
The BFF's current command and queue token routing has integration mismatches documented in Dashboard. Use the route-specific backend contract above rather than assuming every UI action is already functional. No live API request was made during this source audit.