Readiness and operations
The liveness and readiness endpoints with their five checks, the job queue, the outbox and inbox, the daily retention purge, and what an operator does when a check fails.
EvalBook answers two questions on two unauthenticated routes. /health is liveness: is the process up. It touches nothing, so a database that blinks cannot make a restart policy kill a healthy process. /ready is readiness: can this instance do its job. It runs five checks and answers 200 or 503.
An anonymous caller of /ready gets { "ready": true } or { "ready": false } and nothing else: an open endpoint that names the dependency that is down is a map for an attacker. The detail is for a platform admin on Admin → Readiness (platform/api/readiness, run fresh) and for a monitor that sends Authorization: Bearer <EVALBOOK_DIAGNOSTICS_TOKEN> (at least 32 characters). Results are shared for 5 seconds so polling cannot become load; the response carries Cache-Control: no-store.
The five checks
Each check is pass, warn or fail. Only a fail makes /ready answer 503; warnings leave it ready and are named in the reason.
| Check | Passes when | Fails or warns when |
|---|---|---|
database |
every context (authContext, userContext, evalContext) answers SELECT 1 |
fail: any context does not answer |
sso |
SSO accepts this app's token at apps/api/bootstrap (cached 30 s, 4 s timeout) |
fail: SSO_APP_TOKEN is not set, or SSO refuses it; nobody can sign in |
encryption |
EVALBOOK_ENCRYPTION_KEY is set and is 32 bytes |
fail: missing or the wrong length |
peers |
the peer directory has an answer from SSO or from local overrides | warn: the answer is a cached one, or there is no token and no overrides; fail: SSO reports EvalBook as switched off, or SSO is configured and has never answered |
queue |
no due job has waited more than 10 minutes | warn: due jobs are waiting, so no worker is claiming; fail: the job table cannot be read |
The job queue
Every background task is a Job row with its JobAttempt history, claimed by the worker process. The API only enqueues (unless EVALBOOK_INLINE_WORKER=1, for local work). In the container the worker is its own process, and the container exits if it stops. The queues are evaluation, scoring, ingestion, judge, analytics, delivery and maintenance; the registry decides each job type's queue, attempt limit and timeout.
- Claims are atomic and fair: round-robin over the organizations with due work, so one organization cannot starve another.
- Claims are leased for 60 s with a heartbeat every 15 s. Past the lease the job is taken back: requeued, or failed if its attempts are spent.
- Claims are fenced: each claim increments a fencing token, and a completion, failure or heartbeat is accepted only with the current token.
- Failures have classes:
transientretries with backoff;permanentanddeadline_exceededfail now;cancelledis cancelled;outcome_unknownparks the job asawaiting_reconcilefor a reconcile step or a person. Nothing that may already have happened is blindly retried.
The API and the worker execute no customer code. Executable scorers run only in the separately installed, outbound-only runner; see Executable verification.
Outbox and inbox
A fact and the message that announces it to CodeBook or MadeBook commit in one transaction: the message exists if and only if the fact does. The outbox.deliver job sends each message signed and keyed. Backoff is 30 s, 1 m, 2 m, 4 m and so on, capped at 30 m; after 17 attempts (about six hours) the message is failed, stays visible, and a person may send it again. A message goes only to an app the peer directory names, under that app's API base.
Inbound events are deduplicated by (source app, idempotency key) with a payload digest: the same key with the same digest is a duplicate; with a different digest it is a recorded conflict, answered 409, never applied. See Peer links.
The daily purge
retention.purge runs once a day. It applies each project's retention policy per content class (raw_bodies, traces, results, cost_records, audit_metadata), writes a retention receipt shown on Settings → Privacy & retention, and leaves tombstones. See Retention, export and deletion.
When a check fails
| What you see | Where to look |
|---|---|
sso fails |
SSO_ORIGIN and SSO_APP_TOKEN; whether EvalBook is registered and switched on at SSO |
encryption fails |
EVALBOOK_ENCRYPTION_KEY: 32 bytes as 64 hex characters or base64 |
peers fails |
the same SSO registration (it only warns while a cached answer is reused) |
queue warns |
the worker process (in the container it starts once the API answers /health) |
database fails |
EVALBOOK_DB_*; the container refuses to start, naming the first missing variable |
The variables are listed on Deployment; the views are on Platform admin.