Unreleased documentation. These pages follow the main branch and can change before the next release. For supported guidance, use v0.43.0.
If your Base Registry Engine (BReg) registry needs changes beyond field-by-field edits, declare them as Actions. Here you see what an Action declares, when it applies at once and when it becomes a reviewed Proposal, and how a Plan computes its effects. Change a registry with an Action runs both.
Start from the facility template
Section titled “Start from the facility template”bregctl init --template facility-registry facilitybregctl check facilityThe template declares three Actions: register-facility, correct-address, and
deactivate-facility; bregctl explain actions facility shows each one compiled.
What an Action declares
Section titled “What an Action declares”An Action has typed inputs, an execution mode, a plan
of effects, and optional commitGuards. deactivate-facility holds all four:
- id: deactivate-facility display: label: Deactivate facility description: Submit a durable deactivation that requires no external review. execution: mode: proposal proposal: review: {type: none} application: {mode: manual} retention: {mode: retain} commitGuards: targets: - {input: facility, revision: unchanged} - {input: facility, field: status, equals: active} inputs: - {id: facility, apiName: facilityId, type: reference, target: facility, required: true, classification: internal} plan: type: fixed effects: - id: facility-status target: {fromInput: facility} operation: patch set: status: {value: inactive}Commit guards are checked when the change commits: here, the facility must be unchanged since the Proposal froze it, and still active. The caller never chooses the execution mode.
Who may run an Action is an access-profile grant, invoke for an immediate Action and start
for a Proposal:
actions: - action: correct-address operations: [start]Other Proposal operations, such as submit, cancel, or apply, are granted separately under
permissions.proposals, so whoever drafts a change need not apply it.
Immediate Actions return an ActionReceipt
Section titled “Immediate Actions return an ActionReceipt”register-facility declares execution: {mode: immediate}. One request checks the guards,
writes every effect, and commits the new revisions, the receipt, the audit entry, and any outbox
events together, or none of them. The answer is an
ActionReceipt naming each changed Record and its new revision.
A Record type can require a Proposal for an operation:
mutationPolicy: patch: proposal-requiredWith this on facility, neither a direct patch nor an immediate Action may patch a facility; only
a Proposal can. register-facility still creates facilities at once.
Proposals
Section titled “Proposals”An Action in proposal mode creates a Proposal instead.
correct-address requires review:
execution: mode: proposal proposal: review: type: required authority: casework source: facility-registryA Proposal starts as a draft its author can edit. Submitting it freezes the inputs, the
computed effects and their digest, the target revisions, and the Action revision; review and
application work on that frozen submission, so a later change to the Plan or policy cannot
reinterpret it. Revise or Rebase returns it to a new draft, which must be submitted, and
reviewed, again.
A Proposal ends in one of three states:
applied: the registry wrote the frozen effects, under the commit guards as they stand at that moment. With no review it follows submission; with required review it needs current approval of that exact submission.rejected: the review authority rejected the submission. This is final. A reviewer who wants another attempt returns it with changes requested instead, which keeps itsubmittedand offers Revise.cancelled: a caller with thecancelgrant withdrew it before it applied.
Application is automatic, under a restricted system grant for that one submission, unless the
Action declares application: {mode: manual}, as deactivate-facility does; then a caller with
the apply grant applies it. The Proposal’s applicationStatus reports progress: awaiting-review, pending,
applying while a worker is writing it, then applied, or blocked with a reason and a
recovery hint.
Review authorities, declared twice
Section titled “Review authorities, declared twice”The project names each review authority it relies on:
reviewAuthorities: - id: casework protocol: id.registrystack.org/protocols/review/v1 display: label: Casework review authority description: Logical authenticated review authority resolved by deployment configuration.The deployment binds that id to a running service. For local development, the template’s
README gives the dev-clients.yaml binding:
reviewAuthorities: casework: endpoint: http://127.0.0.1:8100/ profile: requester producerId: facility-registry recoveryDays: 30 client: requesterIn production the same map sits in the runtime configuration (runtime.yaml), with a tokenRef
or privateKeyJwt credential instead of client. A missing binding disables only the operations
that need it. An unreachable authority never counts as approval.
Registry Casework is one such authority. The registry sends it the frozen submission and applies only the correlated result; Review a Proposal in Casework pairs the two.
Plans and Evidence
Section titled “Plans and Evidence”A Plan is fixed, like deactivate-facility’s, or computed
by a Rhai Function. correct-address names its Function and bounds what it may write:
plan: type: function function: correct-address-plan inputs: [facility, address-line, city, postal-code] writes: - id: facility-address target: {fromInput: facility} operation: patch fields: [address-line, city, postal-code] refusals: - {code: invalid-postal-code, label: Postal code is invalid}The project’s functions entry names its script:
fn plan(ctx) { let postal_code = ctx.inputs["postal-code"]; postal_code.trim(); if postal_code == "" { return #{ refusal: #{ code: "invalid-postal-code", field: "postal-code" } }; }The planner receives ctx.inputs, holding only the inputs the Plan lists. It returns either a
refusal, whose code the Action declares, or effects: a list of maps, each with the id of a
declared write and its set or clear fields. The declaration fixes each write’s target and
operation, so the script cannot redirect one. Omitting a write skips it; the caller still needs
authority over its target.
Effects apply in authored order. A value fromEffect must name an earlier create, as
register-facility’s assignment names its new facility. Two effects that land on the same Record
are written together as one revision; two effects that write the same field fail bregctl check.
An Action with a Rhai Plan may also declare evidence: at most two capabilities, each naming an
Evidence provider the project declares, a requirement, its subjects, and the outputs it may read.
The script calls evidence::resolve("<capability id>", subjects) once per capability and
receives only those outputs; a failed call refuses the operation. commitGuards.evidence
instead checks a requirement at commit and never changes the effects. The provider’s endpoint and
credentials belong to the runtime configuration; BReg inherits no Evidence authorization.