Released docs. You are viewing the documentation published with v0.34.0. Development docs are available at Latest.
This journey joins two independent responsibilities. Base Registry Engine (BReg) authors and freezes a proposed registry change. Casework evaluates that proposal under its own policy. BReg applies only an exact approved result, and only through current source authorization and guards.
Create and connect the projects
Section titled “Create and connect the projects”Use the paired starters. Their shared source namespace is professional-licences; Casework
requires its source id to equal BReg’s registry.id so submission and source-context reads address
the same record.
mkdir -p review-workbregctl init review-work/registry --template professional-licencescaseworkctl init review-work/casework --template professional-review
bregctl check review-work/registrybregctl explain change-requests review-work/registrycaseworkctl source add review-work/registry \ --project review-work/casework --source-id professional-licencescaseworkctl source add review-work/registry \ --project review-work/casework --source-id professional-licences --apply
caseworkctl check review-work/caseworkcaseworkctl explain review-work/caseworkcaseworkctl test review-work/caseworkcaseworkctl package review-work/casework --output review-work/casework-packageThe first source add is a preview. It shows the exact BReg authoring changes, the Casework
source description, and a candidate BReg runtime fragment without writing them. The --apply
run checks a staged BReg copy before it writes registry.yaml, dev-clients.yaml, the imported
description, and the runtime fragment. It provisions no secrets and activates neither product.
Review review-work/casework/sources/professional-licences.breg-runtime.yaml, replace its example
endpoints and secret references, and merge it into the launcher-owned BReg runtime file.
For the local evaluation, the applied dev-clients.yaml already binds BReg’s authority client to
Casework’s default loopback port. Start BReg first so Casework can borrow its retained issuer:
bregctl dev start review-work/registrycaseworkctl dev start review-work/casework \ --source-project review-work/registrycurl --fail --silent http://127.0.0.1:8090/readycurl --fail --silent http://127.0.0.1:8092/readyWhen you finish, preserve or remove each product’s owned local database explicitly:
caseworkctl dev stop review-work/caseworkbregctl dev stop review-work/registryThe generated fragment includes both sides of the connection: the lifecycle event destination
and read-only Casework source profile, plus reviewAuthorities.casework. The starter keeps
onApproved.mode: manual, uses result polling, and has no completion destination. These defaults
keep application authority in an explicit BReg operator action.
Author the BReg request
Section titled “Author the BReg request”The request binds to a logical authority and Casework policy. Application remains a separate source choice:
changeRequest: effects: - target: {fromField: record} operation: patch set: licensed-activities: {fromField: licensed-activities} review: authority: casework policyId: scope-correction onApproved: mode: manual retention: mode: operator_eraseThe submitter permission needs only source lifecycle operations. The application permission is ordinary BReg authority:
permissions: - entity: scope-correction operations: [create, get, patch, submit_request, revise_request, cancel_request] readableFields: [record, licensed-activities] writableFields: [record, licensed-activities] requestVisibility: owner rowBoundaries: [] - entity: scope-correction operations: [get, apply_request] readableFields: [record, licensed-activities] readableRequestFields: [review_state] applyTargets: - entity: professional-license rowBoundaries: [] rowBoundaries: []Casework reviewer profiles and stages belong in the Casework project. Do not duplicate them as BReg permissions.
Bind the authority client
Section titled “Bind the authority client”For bregctl dev, source add --apply adds the paired local clients to the BReg project. The
resulting authority binding has this shape:
clients: - id: casework-producer accessProfiles: [] scopes: [casework:reviews:request] claims: {}reviewAuthorities: casework: endpoint: http://127.0.0.1:8092/ profile: integration-requester producerId: registry-breg recoveryDays: 7 client: casework-producerThe local issuer provisions the service client and BReg uses maintained client-assertion token acquisition. If the client has no explicit resource mapping, local development uses the generated BReg audience; otherwise it uses the declared mapped resource. Scopes must belong to that resource. No access token or private key is embedded in generated runtime configuration.
The Casework starter admits the stable subject derived from the professional-licences starter’s
instance id and integration-requester client. Before packaging for a deployment, replace that
local issuer and subject in reviewProducers with the deployed BReg client identity, and replace
the example authority endpoint and secret references in the generated BReg runtime fragment.
In a deployed runtime, reviewAuthorities.<id> keeps endpoint, profile, producerId, and
recoveryDays, and uses either maintained privateKeyJwt settings or an explicitly supported
opaque tokenRef. profile is the Casework requester profile sent on every authority request.
producerId is the independent protocol identity used in the submission digest.
Migrate, serve, and check readiness
Section titled “Migrate, serve, and check readiness”For an operated deployment, migrate both databases through the product commands, start both servers under their service managers, and check setup readiness:
bregctl --format json apply \ --runtime-config /etc/registry-breg/runtime.yaml \ --package /srv/registry/package --initialcasework --runtime-config /etc/registry-casework/runtime.yaml migrate
bregctl doctor --runtime-config /etc/registry-breg/runtime.yamlcaseworkctl doctor --runtime-config /etc/registry-casework/runtime.yamlbreg --config /etc/registry-breg/runtime.yamlcasework --runtime-config /etc/registry-casework/runtime.yaml serve
curl --fail --silent https://registry.example.org/readycurl --fail --silent https://casework.example.org/readydoctor checks configuration, package, database, identity, source connectivity, and directory
setup. It does not report the progress of a submitted review. Use the resources below for that.
Submit and observe the exact binding
Section titled “Submit and observe the exact binding”Create the request as its owner, read its advertised submit_request action, and send the returned
ifMatch with a fresh Idempotency-Key. Submit as a person: the starter’s editor client carries
the human actor marker, because the review stage excludes the request’s initiator and BReg names an
initiator only for a human caller. A service or agent submission is refused with
review.initiator-required when Casework admits it, and the submitter who tries to claim the review
task is refused with review.initiator-excluded.
Submission freezes:
- the request and target facts used by the proposal;
- the proposal version and effect digest;
review.authorityandreview.policyId;- application preconditions and
onApprovedbehavior.
BReg durably records the submission job before contacting Casework. The worker uses one stable idempotency key and expected submission digest until it receives the exact accepted binding. Ambiguous responses are recovered with the same request rather than creating a second review.
A profile with readableRequestFields: [review_state] receives
data.request.review. Its closed sections are submission, result, delivery, application,
and recovery. Optional identifiers and timestamps are omitted until known. These fields report
reconciliation state. They grant neither a Casework decision nor a BReg write.
Follow the submit_request action advertised on the BReg request instead of constructing an
internal route. Keep its ifMatch and use a new Idempotency-Key. Then follow the identifiers the
response and request projection return.
Decide in Casework
Section titled “Decide in Casework”Open the task through the Casework profile authorized by the policy. Casework obtains source context with the caller’s delegated credential and the configured source profile, then enforces its stage, queue, assignment, independence, and decision rules. Complete every stage required by the policy.
The starter’s review stage excludes the submitter, so the person who submitted the request cannot
claim, be assigned, or decide its review. A reviewer either approves or chooses the
changes-requested outcome (“Request changes”) with a reason. A send-back reaches BReg as a
changesRequested review result. The request stays submitted, and BReg now offers its owner only
revise_request, carrying rebase: false, and cancel_request. The submitter follows the
revise_request action with the rebase value it carries, and BReg records the new draft as a
revision. The submitter then patches the draft and submits it again, and Casework opens a fresh
review for the new proposal version.
The terminal result carries the exact review request id, subject binding, full policy binding, and submission digest. BReg accepts it only when every value matches the durable submission. An early or unmatched completion remains in the bounded inbox for reconciliation. Redelivery is idempotent.
Apply at BReg
Section titled “Apply at BReg”For manual application, read the request under the BReg applier profile and follow the advertised
apply_request action. Send its ifMatch, a stable idempotency key, and the displayed proposal
binding:
{ "proposalVersion": 1, "effectDigest": "sha256:<64 lower-case hex digits>"}BReg verifies the exact approved Casework result, then rechecks the current applier grant, target authority, target revisions, and application preconditions. Effects and the source receipt commit atomically. If the HTTP response is lost, replay the exact request with the same idempotency key. BReg returns its stored receipt before any Casework or Evidence network call.
For onApproved.mode: automatic, the reconciliation worker uses a separately configured ordinary
executor credential against this same BReg HTTP action. Revoking that profile blocks the job. It
does not borrow the submitter, reviewer, or completion sender’s authority.
Automatic application is opt-in. Change the authored request to
onApproved: {mode: automatic, executor: registry-automatic}, grant one ordinary BReg
apply_request profile, repeat bregctl check, bregctl explain change-requests, and both
source add runs, then provision the generated reviewExecutors.registry-automatic credential.
The executor still passes the current profile, target authority, revision, and precondition checks
at the time it applies.
Choose result delivery explicitly
Section titled “Choose result delivery explicitly”Polling is the default. BReg polls the Casework result resource and treats 202 as pending, 200
as the retained terminal result, 410 as expired, and an empty 404 as concealed or unknown.
The producer result feed provides the same terminal results in pages with a nextCursor.
Completion delivery is optional. Add a Casework producer completion block and repeat the
authoring loop to generate completionTokenRef and completionRecipient in the BReg authority
binding. The completion receiver acknowledges delivery only with an empty HTTP 204 No Content.
Any other success status, or a 204 carrying response bytes, is not an acknowledgement and
Casework retries the same bounded event. Completion is a wake-up signal; BReg still fetches and
correlates the authoritative retained result before it records approval.
Diagnose one review
Section titled “Diagnose one review”Use each owning resource for its state:
| Question | Owning observation |
|---|---|
| Was the request admitted and which policy is running? | GET /v1/review-requests/{requestId}: lifecycle, policy, active stage, and timestamps. |
| Who can act and what context can they see? | GET /v1/review-tasks, the task resource, and /context: queue, task state, holder, revision, and the current source binding. |
| Is a terminal result retained? | GET /v1/review-requests/{requestId}/result: 202 pending, 200 retained, 410 expired, or empty 404 concealed or unknown. |
| Which terminal results have not been consumed? | GET /v1/review-results?cursor=...&limit=...: bounded items and nextCursor. |
| Has BReg submitted, received, or applied it? | Read data.request.review: submission, result, delivery, application, and recovery, with identifiers and timestamps omitted until known. |
The BReg projection reports the durable state and recovery code. After submission it also reports
the fixed submission.recoveryDeadline. Automatic application jobs report bounded
application.attempts; application.nextAttemptAt appears only while queued or applying and is
omitted after the job is blocked or applied; do not query the database directly or treat doctor
as a workflow console.
Verify the boundary
Section titled “Verify the boundary”After application, check all three observations:
- The target record has the expected new revision and values.
- The source request is
appliedand has the same proposal version and effect digest. - The Casework result remains a review result, not the source application receipt.
Also test a substituted digest, stale target, withdrawn request, and revoked applier. Each must fail without a partial target write. See Base Registry Engine API reference, Declare change requests and actions, and How Casework works for the owning contracts.