The article-based YAML format for machine-readable law, conforming to the official JSON schema.
Laws in RegelRecht are stored as YAML files conforming to the law schema. Each file represents one law at a specific point in time.
| Field | Required | Description |
|---|---|---|
$id | Yes | Machine identifier (snake_case) |
regulatory_layer | Yes | WET, AMVB, MINISTERIELE_REGELING, GEMEENTELIJKE_VERORDENING, etc. |
publication_date | Yes | Official publication date (ISO 8601) |
valid_from | No | Effective date |
bwb_id | Conditional | Required for national laws (format: BWBR + 7 digits) |
gemeente_code | Conditional | Required for municipal ordinances (format: GM + 4 digits) |
Each article mirrors a real article in Dutch law:
Constants used in calculations:
Operations are the building blocks of law logic:
| Category | Operations | Syntax |
|---|---|---|
| Arithmetic | ADD, SUBTRACT, MULTIPLY, DIVIDE | values: [...] |
| Aggregate | MIN, MAX | values: [...] |
| Rounding | ROUND, CEIL, FLOOR | value: + precision: (a single operand, rounded to N decimals; see below) |
| Comparison | EQUALS, GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL | subject:, value: (operands may be numbers or ISO dates, see RFC-021) |
| Logical | AND, OR, NOT | AND/OR: conditions: [...]; NOT: value: (wraps a single operation) |
| Collection | IN, LIST | IN: subject: + value: or values: [...]; LIST: items: [...] |
| Conditional | IF (alias SWITCH) | cases: [{when:, then:}], default: |
| Date | AGE, DATE_ADD, DATE, DAY_OF_WEEK, DATE_DIFF | AGE: date_of_birth:, reference_date:; DATE_ADD: date: + years:/months:/days:; DATE: year:, month:, day:; DAY_OF_WEEK: date:; DATE_DIFF: from:, to:, in: (days/months/years) |
These 25 operations make up the schema. The engine also accepts the compat aliases NOT_EQUALS, IS_NULL, NOT_NULL, and NOT_IN for backward compatibility, but they are outside the schema, so prefer wrapping the positive operation in NOT. See RFC-004: Uniform Operation Syntax for the full specification.
Rounding is an explicit, law-modeled instruction: the engine never rounds a value implicitly (not even money). A law that must round says so with one of three unary operations, each taking a single value: operand and a precision: (the number of decimal places to round to, in the value’s own unit):
| Operation | Direction | Dutch |
|---|---|---|
ROUND | nearest, half-up (ties away from zero) | rekenkundig afronden |
CEIL | up (toward +∞) | naar boven afronden |
FLOOR | down (toward −∞) | naar beneden afronden / afkappen |
precision: 0 rounds to whole units, precision: 2 to two decimals, and a negative precision rounds to tens/hundreds (e.g. -2 rounds a eurocent value to whole euros). Intermediate values keep full precision; rounding only happens where a rounding operation appears.
See RFC-024: Precision and Rounding for the full design and legal grounding (Hoge Raad half-up default; no implicit intermediate rounding).
$variableName - reference inputs, outputs, definitions, or parameters$referencedate.year - dot notation for property access#output_name - internal reference (same law)Laws reference outputs from other laws via source:
See RFC-007: Cross-Law Execution for details.
Higher laws declare open_terms that lower regulations implement:
The engine resolves implementations at runtime using lex superior / lex posterior rules.
See RFC-003: Inversion of Control for the full pattern.
Articles can declare what kind of legal product they produce:
This enables the Awb procedure hooks (RFC-008).
Fields can have detailed type information:
A value’s quantity-kind is declared with type_spec.unit, on inputs, outputs, parameters and definitions constants (RFC-023). The available units are euro, eurocent, ratio (a 0–1 fraction), percentage (0–100), and the durations years, weeks, months, days.
A unit is a label, never a computational constraint: tagging a value never changes it. In particular, a percentage is not silently divided by 100; any … / 100 is an explicit operation written where the value is applied. ratio and percentage are distinct labels for the same dimension; the corpus keeps both so a law that says “1,896” (a ratio) and one that says “30 procent” are both transcribed faithfully.
Constants may use the optionally-structured form to carry a unit (the bare naam: 123 form stays valid):
The engine uses these labels to reject nonsensical combinations (adding a eurocent to a days, or euro to eurocent, is a unit mismatch error), while a dimensionless ratio/percentage multiplied by an amount keeps the amount’s unit. Units are opt-in per law: an un-annotated value has unit unknown and is never checked, so existing laws are unaffected until someone annotates them. just validate reports unit mismatches as failures and flags amount outputs that lack a unit (only for laws that already declare units elsewhere). See RFC-023: Quantities in Law YAML.
The corpus is still small and growing. At the time of writing it spans three regulatory layers:
| Layer | Laws | Examples |
|---|---|---|
| WET | ~15 | Participatiewet, Zorgtoeslag, Zorgverzekeringswet, Awb, BW Boek 5 |
| MINISTERIELE_REGELING | 1 | Regeling standaardpremie (2 versions) |
| GEMEENTELIJKE_VERORDENING | 2 | Amsterdam APV erfgrens, Diemen afstemmingsverordening |
For the authoritative, current set, see corpus/regulation/ in the repository.
An exploration by Bureau Architectuur of the Dutch Ministry of the Interior into the possibilities of transparent, executable legislation.
Bureau Architectuur
Ministry of the Interior and Kingdom Relations