Unreleased documentation. These pages follow the main branch and can change before the next release. For supported guidance, use v0.43.0.
Run one Registry Coordinator workflow, reviewed-notice, from an application
in Base Registry Engine (BReg), through your decision as reviewer in Registry Casework, to an
approval email from Registry Messaging. Coordinator does the rest, even across a restart.
Build the local tools
Section titled “Build the local tools”From the source checkout, build the four products, their tools, and the example’s input helper. On macOS, the sourced function also tells your shell where the binaries’ FIPS library lives:
. scripts/cargo-runtime-library-path.shregistry_cargo_build "$PWD" --locked \ -p registry-coordinator --example reviewed-notice-input \ -p registry-breg --features registry-breg/runtime \ -p registry-bregctl -p registry-casework -p registry-caseworkctl \ -p registry-messaging -p registry-messagingctl --binsexport PATH="$PWD/target/debug:$PATH"Keep this terminal open.
Read the workflow
Section titled “Read the workflow”A workflow is a finite list of named steps. Ask coordinatorctl to explain this one:
coordinatorctl explain --project products/coordinator/examples/reviewed-noticeThe output ends with the steps from start, among them:
verify-review-subject: choose by review-subject-route(): changed -> changed-before-review, current -> submit-review changed-before-review: finish application-changed submit-review: call review review-submit-review-request (casework mutation, recovery same-command) with review-request(), then await-review await-review: wait for the result of submit-review, at most 1209600 seconds, then decide; on timeout withdraw-timeout; on cancel withdraw-operatorEach line is one step. A call reaches a product through a named connection, here review for
Casework; a choose picks the next step; a finish ends with an outcome.
await-review is a wait: it holds up to fourteen days for the review result. Later steps read
the application again before calling Messaging.
Start the products and the run
Section titled “Start the products and the run”The session script starts the four products from target/debug, with their databases and the
Mailpit mail sink in Docker. It seeds one application for Amina Example and starts one
run of the workflow for it with POST /v1/runs: one admitted
execution that Coordinator keeps in its database. The registry project, review policy, and
notice template it uses are in products/coordinator/scripts/real_service_fixtures.py. Every
service listens on loopback HTTP (tlsTermination: development-loopback), and Coordinator applies
its schema as the database superuser and serves as a separate runtime role: a local setup only.
mkdir -p tutorial-workpython3 products/coordinator/examples/reviewed-notice/session.py start \ --session-dir tutorial-work/reviewed-notice > tutorial-work/session.jsonjq '{status, workflow}' tutorial-work/session.json{ "status": "ready", "workflow": "reviewed-notice"}session.json holds service addresses and owner-only token file paths. Keep them in variables,
and copy the Coordinator token out of its header file for coordinatorctl:
session=tutorial-work/session.jsonrun_id="$(jq -r .runId "$session")"coordinator_url="$(jq -r .coordinatorApi "$session")"casework_url="$(jq -r .caseworkApi "$session")"mailpit_url="$(jq -r .mailpit "$session")"staff_headers="$(jq -r .staffHeaderFile "$session")"(umask 077 && sed -n 's/^Authorization: Bearer //p' \ "$(jq -r .coordinatorHeaderFile "$session")" > tutorial-work/coordinator.token)Inspect the waiting run
Section titled “Inspect the waiting run”coordinatorctl inspect --run "$run_id" \ --url "$coordinator_url" --token-file tutorial-work/coordinator.tokenThe run is at await-review, after Casework accepted the review request:
state: running step: await-reviewwaits:- acceptedStep: submit-review completion: resultNothing has gone to Messaging. Inspection never shows the application data or the commands sent.
Claim and approve the review task
Section titled “Claim and approve the review task”As staff, find the open task in the applications queue and read the facts you decide on. The
applicant’s email address stays in BReg.
curl -fsS --header @"$staff_headers" --header 'Registry-Casework-Profile: staff' \ "$casework_url/v1/review-tasks?queue=applications" > tutorial-work/tasks.jsontask_id="$(jq -r '.items[] | select(.state == "open") | .taskId' tutorial-work/tasks.json)"curl -fsS --header @"$staff_headers" --header 'Registry-Casework-Profile: staff' \ "$casework_url/v1/review-tasks/$task_id/context" | jq .context.snapshot{ "applicantName": "Amina Example", "benefitProgram": "housing-support", "requestedAmount": 1200}Claim the task at the revision you read. Casework answers 200:
revision="$(jq -r '.items[] | select(.state == "open") | .revision' tutorial-work/tasks.json)"curl -sS --output /dev/null --write-out '%{http_code}\n' -X POST \ --header @"$staff_headers" --header 'Registry-Casework-Profile: staff' \ --header "If-Match: \"$revision\"" --header "Idempotency-Key: $(openssl rand -hex 16)" \ "$casework_url/v1/review-tasks/$task_id/claim"200Before you decide, restart Coordinator. The run is durable state, not a running process:
python3 products/coordinator/examples/reviewed-notice/session.py restart-coordinator \ --session-dir tutorial-work/reviewed-notice > "$session"coordinator_url="$(jq -r .coordinatorApi "$session")"jq .coordinatorRestarts "$session"1Now approve at the task’s current revision, with the policy’s approved outcome. Casework answers
204:
revision="$(curl -fsS --header @"$staff_headers" --header 'Registry-Casework-Profile: staff' \ "$casework_url/v1/review-tasks/$task_id" | jq -r .revision)"curl -sS --output /dev/null --write-out '%{http_code}\n' -X POST \ --header @"$staff_headers" --header 'Registry-Casework-Profile: staff' \ --header 'Content-Type: application/json' \ --header "If-Match: \"$revision\"" --header "Idempotency-Key: $(openssl rand -hex 16)" \ --data '{"decision":{"type":"approve","outcome":"approved"}}' \ "$casework_url/v1/review-tasks/$task_id/decisions"204If a request answers 401, the local token expired. Refresh the staff token, and the Coordinator
token for coordinatorctl, then repeat:
owner="$(jq -r .ownerProject "$session")"bregctl dev token staff "$owner"bregctl dev token coordinator-producer "$owner"(umask 077 && sed -n 's/^Authorization: Bearer //p' \ "$(jq -r .coordinatorHeaderFile "$session")" > tutorial-work/coordinator.token)See the run finish
Section titled “See the run finish”Casework tells the restarted Coordinator a result is ready. The workflow reads the application again, checks it is unchanged and still allows a notice, and asks Messaging to send to the address on that record. Check the run:
coordinatorctl status --run "$run_id" \ --url "$coordinator_url" --token-file tutorial-work/coordinator.tokenoutcome: notice-acceptedoutput: messageId: <message-id> resultId: <result-id>state: finishedIf it is still running, repeat it after a few seconds. Then look at the local mail server:
curl -fsS "$mailpit_url/api/v1/messages" \ | jq '{count: (.messages | length), to: .messages[0].To[0].Address, subject: .messages[0].Subject}'{ "count": 1, "to": "amina@example.invalid", "subject": "Application approved"}One email reached Amina’s address on record. A changed application, a withdrawn noticeAllowed,
or a rejection would each have finished without calling Messaging.
Stop the session
Section titled “Stop the session”The script removes only the containers and sessions it created:
python3 products/coordinator/examples/reviewed-notice/session.py stop \ --session-dir tutorial-work/reviewed-noticeHow Registry Coordinator works explains the run, its wait, who owned each effect, and how an operator recovers a run.