Evaluations and watermarks
State machine
pending → processing → complete
↘ error (batch-level failure only)
pending— row created, worker not yet started. Usually milliseconds.processing— worker running.complete— all scenarios finished; per-scenario results populated.error— batch-level failure before any results were produced. Top-levelerrorfield carries the reason.
Per-scenario failures do not flip the batch to error. The batch completes; the failing scenario's entry carries its own error string.
Idempotency
POST /evaluateis not idempotent — each call creates a new evaluation. UseIdempotency-Key? Not currently supported; deduplicate client-side if you need at-most-once submission.GET /evaluations/{id}andGET /scenarios/{id}/resultsare idempotent and cacheable.GET /violations/{id}/remediationis idempotent and cacheable perscenario_id:policy_codeuntil the next re-evaluation.POST /results/fetchis not idempotent — the first successful call consumes the token.
Watermarks
Every authenticated response carries a meta.watermark of the form wm_<8 hex>. The watermark is logged server-side against the calling API key.
"meta": { "watermark": "wm_a1b2c3d4" }
- Watermarks are opaque to clients — do not parse them.
- They are unique per response.
- They are used for leak tracing: if a sanitised result leaks externally, the watermark identifies the calling key and the request that produced it.
- Safe to include in support tickets to speed up correlation.
Anomaly detection
The middleware tracks per-key activity and surfaces internal observability for suspicious patterns (request rate spikes, IP churn, unusual error mix). Today this is platform-internal — partners do not see anomaly events.
Enabling PUBLIC_API_ANOMALY_AUTO_SUSPEND=true causes the platform to auto-suspend keys exceeding configured thresholds. This flag is off by default in production.
Result tokens (single-use JWT)
POST /evaluate returns a result_token JWT alongside the evaluation_id. Properties:
- TTL: 900 seconds (15 minutes).
- Single-use: consumed on the first successful
POST /results/fetch. - Bound to one
evaluation_id. - Sent in the request body, not the URL —
POST /results/fetchwith{"result_token":"..."}— so it never lands in access logs. - Still authenticated: like every endpoint except
/governance/health, the call carries the Bearer key andX-FB-Signature. The token is an additional single-use credential, not a replacement for signing.
If the backing evaluation is not yet complete when the token is presented, the response returns { ok: true, data: { status: "processing", message: "Results not yet available" } } and the token is not consumed. Wait until the evaluation reports complete, then fetch once.