Skip to content
Registry StackDocsDevelopment (unreleased)

How Registry Coordinator works

For the operator

View as Markdown

You have followed one application through review to a notice. Here is what each part of that run was, and what changes when a wait times out, a product refuses, or a service restarts.

A Registry Coordinator project defines one workflow. workflow.yaml names the operations the workflow may call, the typed input it accepts, and the steps from start to every finish. Each operation alias binds one exact versioned host operation, such as casework.submit-review-request/v1, to a logical connection name. There are five step types:

  • call runs one operation with a typed mapping of input, earlier step output, and literals.
  • choose routes on a pure Function written in bounded Rhai. A Function has no clock, file, network, database, or credentials, and cannot add steps.
  • wait-until waits for an instant.
  • wait-for waits for a named completion that an earlier accepted call exposes, such as the result of a submitted review request.
  • finish ends the run with a declared outcome and the output the workflow chooses to publish.

In reviewed-notice, every refusal and timeout has its own named finish, so each way the run can end is visible before it starts.

coordinatorctl check compiles the project offline. It proves that every mapping reads data that exists on every route that reaches it, and computes a workflow revision from what changes execution; titles, descriptions, and project.version do not change it. coordinatorctl package freezes the project into an immutable package whose digest the deployment pins.

What you do not define is equally deliberate: no SQL steps, no dynamic fan-out, no arbitrary HTTP method or destination, and no automatic compensation or rollback.

A run is one admitted execution of the active workflow revision. It is admitted in one of two ways: an authorized caller posts to POST /v1/runs with the expected revision, its input, and an idempotency key, or an authored event trigger accepts a signed product event at POST /v1/events/{workflow}/{trigger}. The same key with the same revision and input returns the same run; a different revision or input gets 409 idempotency.key-reused. Coordinator is not a review provider: when a workflow needs a human decision, it submits its own request to Casework, as reviewed-notice does.

Admission, the run, and its first job commit together in PostgreSQL, and the run’s definition, input, and prepared commands are sealed with AES-256-GCM under the deployment’s payload state key. A later package activation leaves an admitted run on the definition it started with.

A wait is durable state, not a sleeping process. A wait-for has a required timeoutSeconds shorter than the run deadline, and an optional onTimeout and onCancel route. While waiting, Coordinator observes the source at most every 30 seconds, a floor the deployment can raise. A Casework pending result is read every 900 seconds by default. A Casework completion event at POST /v1/review-completions only brings the next read forward; it carries no result and starts no run.

A timeout means the workflow stopped waiting, not that the review stopped, so reviewed-notice withdraws its request and reads whether a decision arrived anyway.

Each product a run calls owns the effect and decides whether to allow it. Coordinator keeps the progress, the prepared commands, the waits, and its own audit journal.

Every connection in runtime.yaml carries its own service identity, with a fresh credential for each attempt, and starting a workflow grants no downstream authority. In reviewed-notice, Base Registry Engine (BReg) decided what the workflow could read, Casework who could review, and Messaging whether the notice could be sent. A wait, retry, or restart never renews an approval or widens its scope.

Coordinator does not apply a BReg Proposal: check refuses a Proposal Action with coordinator.operation.proposal-action. The applicant drives the Proposal in BReg, and a workflow follows it through a product event or a later record read.

A product refusal is a fact about the product’s policy. An immediate Action call may route an owner-declared no-effect refusal through onDeclaredRefusal as {refusalCode}; any other refusal fails the run with product-refused.

coordinatorctl status and coordinatorctl inspect show a run’s state: running, attention, cancel-requested, finished, failed, cancelled, cancelled-after-effect, or expired. Inspection adds each step, every effect as accepted or unknown, and the timing and observation count of a wait. Inputs, product responses, and prepared requests stay protected; a finished run publishes only the output its finish step declares.

When a call might have reached the product but no answer came back, the effect is uncertain, and Coordinator does not guess. A definite retryable response resends the same saved command within the original deadline. Messaging and Scheduling expose a receipt for the original idempotency key, so coordinatorctl reconcile can settle an uncertain send against it. BReg Action and Casework mutations have no such receipt, so a record read or an operator’s word does not settle them. A decision-evaluation call (evaluation.evaluate/v1) that may have been sent is never repeated.

coordinatorctl retry-same resends the original command, and coordinatorctl cancel stops future calls where it can. Cancellation never reverses an accepted effect or withdraws a downstream request on its own; a workflow that wants a withdrawal says so in its onCancel path, as reviewed-notice does.

A restored database must never be handed to an ordinary worker first, because a backup can predate effects that products already accepted, and the worker would resend prepared commands to products whose state has moved on. The operator starts coordinator --recovery-only, which admits and dispatches nothing, and places a restore hold with coordinatorctl restore-hold. Each unfinished run then waits for review, and work resumes only after the operator releases the hold.

Author a Coordinator workflow builds, checks, and packages a workflow of your own.