Unreleased documentation. These pages follow the main branch and can change before the next release. For supported guidance, use v0.26.1.
Registry Casework serves one HTTP surface for source-backed work and for the hosted work it owns. Every call presents a bearer token and the Casework profile selected for that call, and the presence of a source profile decides which kind of work a shared route addresses. The contract is current and carries no frozen compatibility promise.
Open the Registry Casework API operations for every route, parameter, schema, and reachable problem code. This page holds the authentication, selection, revision, and recovery rules those operations assume.
Contract boundary
Section titled “Contract boundary”Every request presents Authorization: Bearer <token> and Registry-Casework-Profile, naming the one
profile the caller selected for that call. A profile name is bounded to 128 bytes. Liveness and
readiness are the only routes that take neither header, and a source-delivered event authenticates with
the configured webhook signature and timestamp headers instead.
Registry-Source-Profile names the separate source authority the caller selected. On a work-item route
that serves both kinds of work, presenting the source profile addresses source-backed work under that
authority, and omitting it addresses hosted work. A route that reads or acts on source-owned state
requires the source profile, and a hosted-only or directory-only route refuses a request that carries
one. The two paths stay separate even when one client instance drives both.
A revisioned mutation carries the item or directory revision the caller displayed in If-Match. A
retriable create or mutation carries an Idempotency-Key the caller chooses, bounded to 128 bytes, and
Casework never retries one on the caller’s behalf. After a lost response, the attempt recovery routes
return the original attempt under the same key, so recovery does not depend on the attempt identifier
reaching the caller.
A refusal answers application/problem+json with type, title, status, detail, code, and
traceId. The type is the code with each dot replaced by a slash under
https://id.registrystack.org/problems/registry-casework/, and detail is the fixed sentence that
belongs to the code. No field repeats a submitted value. A refused hosted submission adds
Registry-Casework-Validation-Path, a bounded JSON path, and Registry-Casework-Validation-Reason, one
value from a closed set, so a caller can point at the offending field without the service echoing it. A
refusal that holds a durable attempt adds Registry-Casework-Attempt.
Problem codes
Section titled “Problem codes”Every Casework problem response carries one code from this closed catalogue, always answered with the
HTTP status listed beside it.
For a source-backed decision, request.source-rejected means you must fix the promoted action body,
source.record-missing means the bound record is no longer at its registered location, and
source.reviewer-not-authorized means you must check the selected source profile and credential.
Only work-item.not-offered tells you to refresh the item because the action is stale.
| Code | Status | When |
|---|---|---|
absence.cover-cycle | 422 | A cover assignment would return to an earlier person during a shared period. |
absence.invalid-period | 422 | An absence period does not end after it starts. |
absence.overlap | 422 | The period overlaps another absence already recorded for that person. |
absence.self-cover | 422 | An absence names its own person as cover. |
authentication.refused | 401 | The bearer credential is missing, invalid, or expired. |
clock.recompute-preview-expired | 410 | A clock recompute preview was applied after it expired. Create a new preview and review it before applying. |
cursor.expired | 410 | A page cursor has expired. Start again without a cursor and deduplicate entries by eventId. |
cursor.invalid | 400 | A page cursor is malformed or was issued for a different request. |
idempotency.expired | 410 | The stored response for the idempotency key has expired. Reconcile the original operation before choosing a new key. |
idempotency.key-reused | 409 | An idempotency key was presented for a different request. |
operation.not-authorized | 403 | The caller's Casework authority does not allow this operation. |
precondition.failed | 412 | If-Match did not match the current revision of the item or directory. |
precondition.required | 428 | A mutation that requires the revision the caller loaded was called without it. |
profile.not-authorized | 403 | The selected Casework profile does not authorize the request. |
profile.not-human | 403 | An action reserved for a human session was called under another session. |
request.body-too-large | 413 | The request body exceeds the one MiB limit. |
request.invalid | 400 | The path, query, or headers did not match the Casework contract. |
request.method-not-allowed | 405 | The route does not accept that HTTP method. |
request.not-found | 404 | The requested Casework route does not exist. |
request.reason-unsupported | 422 | The reason field was sent with approve or apply, which do not accept it on the BReg source. |
request.source-rejected | 422 | The source refused the promoted action body. Fix the decision request before trying again. |
request.unprocessable | 422 | The request body does not match the Casework contract. validation names the member and the closed reason. |
request.unsupported-media-type | 415 | A body without Content-Type: application/json. |
runtime.failure | 500 | Casework could not complete the request. |
service.unavailable | 503 | Casework storage is unavailable. Retry after the service recovers. |
source-profile.not-applicable | 400 | The route does not use source authority. Omit the Registry-Source-Profile header. |
source-profile.required | 400 | The route needs an explicit Registry-Source-Profile header to select source authority. |
source.bad-gateway | 502 | The source returned a response that does not match its registered contract. |
source.not-found | 404 | The named source is not registered. |
source.record-missing | 404 | The bound source record is no longer at the registered location. |
source.reviewer-not-authorized | 403 | The source refused the selected reviewer profile or credential. |
source.signature-invalid | 400 | A source event's signature did not verify. |
work-item.already-claimed | 409 | Another person claimed the item first. |
work-item.not-holder | 409 | The caller does not hold the item. Claim it first, or ask a supervisor. |
work-item.not-offered | 409 | The source did not offer that action to this caller. |
work-item.not-visible | 404 | The source did not show this request to the caller, so Casework shows no item. The caller cannot tell this from an item that does not exist. |
work-item.proposal-changed | 409 | The proposal changed since the caller read it. The private draft is retained. |
work-item.recovery-pending | 409 | The result of the caller's last action is unconfirmed. Recover the original attempt; do not decide again. |
work-item.source-unavailable | 503 | The source is not answering, so Casework cannot confirm the current item or its actions. The private draft is retained. |
work-item.superseded | 409 | A revised proposal replaced this item. Open the current one. |
Route families
Section titled “Route families”The served routes group into these families. Authority is checked per route and per item, so membership in a family grants nothing on its own.
| Family | Base paths | Callers |
|---|---|---|
| Service description | /v1/casework | Any authenticated profile |
| Work items and holdings | /v1/work-items, /v1/holdings | Staff and Supervisor |
| Hosted items | /v1/hosted-items | Requester |
| Hosted accountability | /v1/hosted-accountability/{eventId} | Supervisor |
| Directory and absences | /v1/directory, /v1/directory/absences | Administrator, with own or supervised absences for Staff and Supervisor |
| Caseload movement | /v1/directory/caseload | Supervisor |
| Clocks and holidays | /v1/directory/clocks, /v1/directory/holidays | Administrator |
| Source events | /events/sources/{sourceId} | The configured source, by signature |
| Liveness and readiness | /health, /ready | Any caller, without a token |
Work item history
Section titled “Work item history”Two history reads sit under the same work item and answer different questions.
GET /v1/work-items/{itemId}/hosted-history is the staff read of hosted lifecycle history, open to a
human Staff or Supervisor profile under current deciding-profile and served-queue authority, and it
returns source-profile.not-applicable when a request carries Registry-Source-Profile.
GET /v1/work-items/{itemId}/history is the source-scoped variant and requires
Registry-Source-Profile, returning source-profile.required when it is absent and entries under
the caller’s current source visibility when it is present. Both order entries by occurredAt and
eventId and page with an opaque cursor.
Profiles and disclosure
Section titled “Profiles and disclosure”- Staff works eligible items and may delegate an item it holds.
- Supervisor controls assignment and caseload for currently led teams, reads holdings, and resolves retained hosted accountability for served queues.
- Administrator manages directory teams, holiday revisions, and clock recomputation without gaining item payload access.
- Requester creates and follows only hosted items bound to the same service principal and selected Requester profile, and cannot claim or decide work.
Hosted terminal feeds expose stable event identifiers and opaque actor references. The separate accountability read returns raw issuer-qualified actor identity and staff reason only to an authorized Supervisor, records that read in the audit journal, and stops returning the record after accountability expiry.
Source of truth
Section titled “Source of truth”The implementation is the source of truth, and the generated document is the published form of it. The
product generator builds the OpenAPI document from Rust-owned DTOs, problem codes, route inventory,
extraction rules, and operation contracts, and declares the API version v1alpha1. The product check
regenerates the document and refuses byte drift. A running Casework process serves the routes in that
document, and does not serve the document itself.
The problem code table is generated from maintained data checked against the runtime catalogue by the product test suite. The route families table, the header rules, and the profile list are maintained by hand against the cited source.
- Author a Casework policy for policy, profiles, and authority.
- Operate Registry Casework for runtime settings and readiness.
- Client API reference for the Rust, Node.js, and Python clients over these routes.
- How Registry Casework works for the model behind claims, drafts, and attempts.