41 · Rules without Colang: the rule sheet¶
A rule sheet states the rules over your tools as YAML a person can read aloud: a refund over 200 needs a supervisor's approval; closing an account waits for the customer to confirm; nobody deletes a customer. It compiles to the same rulebook a Colang policy becomes, so every check that reads a rulebook reads a sheet exactly as it reads Colang. This chapter is the sheet, construct by construct, and what happens when a sheet says something the compiler cannot state exactly.
A sheet¶
# The shop's rules, as a sheet a person can read aloud.
rules:
- action: refund_card
requires: [supervisor_approved]
when: { amount_over: 200 }
- action: charge_card
requires_confirmation: true
- action: send_receipt
after: [charge_card]
at_most: 1
One rule per action. Each rule names its action, a tool of your catalogue, and says one or more of:
| Key | What it says | The Colang it equals |
|---|---|---|
requires: [a, b] |
the action runs only where every named context holds | a deny-by-default flow for the action, guarded on $a and $b |
when: {amount_over: 200} |
when the requirements apply, as conditions on the call's own arguments: <argument>_over, _under, _at_least, _at_most or _is |
the guard holds only where the condition does; the condition becomes a context the tool check computes from the checked call's arguments, so the host cannot set it |
never: true |
the action never runs | a flow that refuses it unconditionally |
requires_confirmation: true |
a person confirms each call | not in the rulebook: a confirmation the catalogue declares, which the tool check enforces |
confirmation: "…" |
the same, with the words the person is asked | as above, with the wording |
after: [tool] |
the action runs only after each named tool, in the same session | the catalogue's order rule, enforced by the tool check |
not_after: [tool] |
the action never runs after a named tool | as above |
at_most: 3 |
the action runs at most that many times in a session | as above |
A sheet's confirmations and order rules are not in the rulebook, because the rulebook decides whether an action may happen at all, and those decide when and how. They are returned as an overlay on your catalogue, and the tool check enforces them like any declaration (chapter 32).
Compiling and saving¶
$ stalwart rules compile rules.yaml # compiled and linted; nothing is kept
$ stalwart rules compile rules.yaml --save # registered on your newest catalogue
The service compiles the sheet into the Colang policy it equals, and the Colang front end every policy
goes through emits the rulebook from that. A sheet and the Colang it equals are therefore one gate, and
every verdict over one is a verdict over the other. --out-dir writes what the compiler made:
rule_sheet.co, the Colang; rulebook.ir.json, the rulebook; and catalogue_overlay.json, the
confirmations and order the sheet sets.
--save keeps the sheet and registers a new catalogue version: your newest catalogue's tools, with the
sheet's confirmations and order laid over them, and the sheet's rulebook as its rules. Every tool check
enforces it from then on. A rulebook and a rule sheet are one record on a catalogue: an agent that
declares a Colang rulebook: registers it again at its next start, in place of a sheet saved since
(chapter 45).
The console's Rules page is a form over the same sheet: it compiles and lints on the page, and saves
as --save does (chapter 5).
The lints¶
The sheet is checked against your newest catalogue, and each problem is a lint, not a failure:
rule_action_unknown: the sheet has a rule for an action the catalogue does not hold;write_ungoverned: a write the catalogue holds that the sheet never names, so a new write is never left ungoverned by omission.
What every mode reads¶
The rulebook a sheet compiles to is what the tool check enforces at run time, what stalwart verify and
the bug hunter scan, and what a guardrail job verifies when you send the compiled rulebook as
rulebook_ir. Each answers over it exactly as over a rulebook from Colang.
Refused, never approximated: rule_sheet_unsupported¶
A sheet the compiler cannot state exactly is refused, naming its line and the reason, and nothing is written. The reasons are concrete:
- a key that is not one of the nine above;
- a second rule for the same action: how two rules would combine is never guessed;
neverwith anything beside it: an action that never runs has no other condition;whenon a rule that requires nothing: the conditions say when the requirements apply;- a condition with no comparison the compiler can state, or a number compared with something that is not one;
- YAML outside the sheet's subset: tabs, a block list, a value on the line below its key, a second document.
$ stalwart rules compile unsupported.yaml
unsupported.yaml:4: rule_sheet_unsupported: line 4: `refund_card` has a rule already: one rule per action, so how two would combine is never guessed. The sheet was not compiled; nothing was changed.
$ echo $?
1
A sheet is refused rather than approximated because an approximation would be a rule you did not write,
enforced as though you had. stalwart rules compile exits 1 on a refusal, 0 on a sheet that
compiled, 2 where the file could not be read and 3 where the service could not be reached.
From a drafted rule to a sheet¶
A rule Guardrail Writing drafted and verified is Colang. Where its rule is one of the shapes above, it can be restated as a sheet a reviewer reads more easily, and the two compile to one gate: compile both and compare the rulebooks, or verify the same obligation over each.
The limits¶
- A sheet states what its constructs express and no more. A rule that needs a construct the sheet does not have is written in Colang.
- The contexts a sheet
requiresare set by your systems at run time; the sheet proves the action waits for them, not that they are set truthfully. - Lints are advice. A sheet with lints still compiles; reading them is how a new write is not left without a rule.