RegelRecht turns Dutch law into executable specifications. Earlier RFCs built up the vocabulary: how a beschikking is modeled and who is competent to issue it (RFC-002, RFC-007), how delegated legislation plugs in (RFC-003), how the AWB lifecycle structures application-to-objection (RFC-008), how organisations execute side by side and federate corpora (RFC-009, RFC-010), and how each execution leaves an auditable trace (RFC-013).
Three gaps block a concrete next step, the financial-enforcement domain (Wahv, OM-strafbeschikking, sectoral bestuurlijke boetes):
decision_type exists, so the domain cannot be expressed.produces.In december 2025 the Denktank Achterkant van de Overheid published Nieuwland and the Chronolexografie position paper, which offer a coherent vocabulary for digitally recording the rechtstoestand: three types of recording (lexogram, decretogram, executogram), held by a containment and autonomy domain called a chronolexocel. That vocabulary matches the architecture RegelRecht is already building.
This RFC introduces:
competent_authority) and the security context (keys, transport, authorisation) kept as separate axes (§2).modality and extensions.source block, with the runtime selecting the transport per context (Blauwe Knop for citizen-clients, FSC for authorised servers).The RFC is neutral about any specific external standard at the schema level. The first integration it anticipates is the Blauwe Knop Connect standard behind Mijn Betaaloverzicht; concrete integration shape lives in the CJIB pilot proposal. This RFC reuses three existing mechanisms (the RFC-007 source.regulation resolver, the RFC-013 Execution Receipt, and RFC-009 signing) in ways that ask for a small follow-up amendment to each; until those land, the resolver, signing, and provenance decisions in §4, §3.2 and §1.3 are accepted pragmatically. The RFC-007 and RFC-013 amendments are additive; the RFC-009 one carries a genuine open security question (whether the cell’s FSC key may also sign Blauwe-Knop responses), so the pilot uses a dedicated JWS signing key and treats key-reuse as a later optimisation, not a blocker.
This RFC does not introduce a bezwaarbaar field; RFC-008 already models the AWB lifecycle a per-rule field would duplicate (Alternative 7). The route from a chronolexogram back to its objection stage is derived through RFC-008 (§3.3).
corpus/regulation/.chronicles/; a registration-spec is not a regulation.legal_character: BESCHIKKING. New decision_type values cover financial enforcement.produces.extensions.This RFC adopts the Chronolexografie position paper vocabulary (lexogram, decretogram, executogram, chronicle, reduction, lexostatus), introduced in context where first needed; glossary entries land with the follow-up implementation work.
Each chronolexogram records a process-relative fact, not a free-standing truth: not “Lotje woont op Lindelaan 5” but “op moment T heeft actor X vastgesteld dat …”. The engine’s reductie therefore reasons over vaststellingen at moments, not over current-world state.
Three concepts are kept apart as independent axes (worked out in §2): the cell (a containment and autonomy domain, the paper’s only meaning), the competent_authority (RFC-002: who is legally empowered to take a besluit), and the security context (keys, trust material, query authorisation; a RegelRecht concern the paper does not address). A RegelRecht engine is a computational component that can run inside a cell; the cell is not the engine.
Chronolexografie names three types of vastlegging (lexogram, decretogram, executogram) as an explicit first enumeration, not a closed set. RegelRecht maps each to a place in the repository layout and chooses representations that do not assume the set is closed: where it touches the schema it uses open vocabularies (an open decision_type string, the extensions namespace), never a closed enum that would have to be reopened per new type.
The three also differ in production mode, a distinction the Chronolexografie typology does not itself draw (in its framing all three are chronolexograms, and that unification is real). A lexogram is prepared ahead of execution and is generic, one current version per regulation per moment (compile-time). A decretogram and an executogram arise during execution and are individual, produced per subject per case at runtime (operational). What this implies for cell roles is left open (Open Question 1).
A lexogram is the recording of a (possible, future) wijziging in wet- of regelgeving. A YAML file under corpus/regulation/<jurisdiction>/<type>/<name>/<valid_from>.yaml is a lexogram; the sequence of valid_from versions is its lexogram-chronicle. No new schema; the contribution is documentational.
decision_type as an open vocabularyA decretogram is an engine output with produces.legal_character: BESCHIKKING. The decretogram is the primary artefact; the RFC-013 execution trace is its body; the RFC-009 §5 signature (made with the security context’s signing key, §2) is its signature. Wire-formats (an FCID-record, an FSC-payload) are serialisations, not separate artefacts.
A decretogram is lifecycle-aware through RFC-008. The procedure_id on produces selects the AWB procedure. The lifecycle is not one accumulating decretogram: the position paper makes each chronolexogram elementary (“in exact één chronolexogram”). The paper pairs this with a transactional-consistency rule that the elementarity citation alone does not carry: what arises together is recorded together in one chronolexogram (“wat tegelijkertijd ontstaat wordt samen vastgelegd”, which “voorkomt multirealiteit”). Stage-splitting therefore applies to successive events in a besluit’s lifecycle, not to facts that arise simultaneously: a single decretogram that imposes a hoofdsom plus an opslag plus rente records those co-arising elements as one elementary artefact, not three. Each RFC-008 stage (BESLUIT, BEKENDMAKING, BEZWAAR, …) is its own elementary stage-decretogram; the stages of one besluit are grouped, in time order, in a kroniek sharing a zaakkenmerk. “The besluit” is that kroniek; “the current stage” is its latest stage-decretogram.
The existing produces.decision_type is a closed enum of nine values (TOEKENNING, AFWIJZING, GOEDKEURING, GEEN_BESLUIT, ALGEMEEN_VERBINDEND_VOORSCHRIFT, BELEIDSREGEL, VOORBEREIDINGSBESLUIT, ANDERE_HANDELING, AANSLAG). None covers financial enforcement, and modeling an open, growing typology as a closed enum guarantees a breaking schema bump per future type. This RFC therefore opens decision_type to a type: string, moving the recommended (non-exclusive) vocabulary into a schema-independent file. This reuses the exact pattern of the RFC-018 Decision 9 ambiguity-tag vocabulary (corpus/annotations/_vocabulary/ambiguity.yaml): values live beside the schema, feed both the editor picker and the validator from one file, and an out-of-vocabulary value warns rather than fails (mirroring validate-annotations). The schema-version contract stays stable; the vocabulary moves at its own cadence.
The nine historical values seed the recommended set. This RFC adds three for the financial-enforcement domain, as examples (the next type is a one-line edit, not a schema reopening):
BETALINGSVERPLICHTING: generic financial obligation imposed by a bestuursorgaanSTRAFBESCHIKKING: criminal-law settlement under Sv art. 257aBESTUURLIJKE_BOETE: sectoral administrative fineTo anchor these in recognisable cases: a Wahv parking or speeding fine (Wet Mulder) is a BETALINGSVERPLICHTING, with the Wahv’s own beroep-route (§3.3); an OM settlement for the same speeding offence routed criminally is a STRAFBESCHIKKING, with verzet before the strafrechter; an AP or ACM fine is a BESTUURLIJKE_BOETE, with the ordinary Awb-bezwaar-route. The same financial fact can thus carry a different decretype and a different rechtsbescherming-route depending on the procedure that produced it.
Opening a closed enum to a string is backward-compatible for producers (every existing value still validates) and does not break consumers that exhaustively match (an unrecognised value was already unrepresentable). Consumers that switch on the value still need a default branch, as they always should have.
STRAFBESCHIKKING is not an Awb decision. Its remedy is verzet before the strafrechter (Sv 257e), not Awb bezwaar/beroep; the RFC-008 procedure machinery and the §3.3 route derivation do not apply. The slot exists so the financial fact can be modeled, but a deployment issuing a STRAFBESCHIKKING must derive its route from the criminal-procedure model. Until that model lands a STRAFBESCHIKKING carries a geen_rechtsbescherming_reden placeholder rather than a computed route. (The UOV procedure, Awb afdeling 3.4, never applies to a strafbeschikking.)
Scope: administrative and OM-issued besluiten only. The model does not cover court-imposed financial measures (a schadevergoedingsmaatregel, Sr 36f, or ontnemingsmaatregel, Sr 36e), which are rechterlijke measures from a vonnis/arrest with a different remedy. The boundary is the issuer, not the money: an OM-issued financial component (including a schadevergoeding the OM may attach to a strafbeschikking under the Wet OM-afdoening) is in scope as a STRAFBESCHIKKING, while the same measure imposed by a court is out. A cell that collects a court measure still records the collection as an ordinary executogram; only the underlying court decision falls outside the model.
Two earlier candidates are excluded: INCASSO_BESCHIKKING conflated an executoriale titel (the dwangbevel, Awb 4:115/4:116) with a primary besluit; INTREKKING_BESCHIKKING treated a modality as a type (an intrekking is a nested besluit per RFC-008 Open Question 5, referenced via modality.is_intrekking_van, §3.1).
chronicles/ directoryAn executogram is the recording of feitelijke levering of afhandeling (a payment received, a kwijtschelding granted, a service delivered). It is not a regulation output and belongs in no produces block; like a decretogram it is its own primary artefact, with FCID and other wire-formats as serialisations.
Executogram-stream definitions live in a new top-level directory chronicles/, parallel to corpus/. A chronicle-stream declares which facts a cell records, which actor records them (the cell operator, not competent_authority, since an executogram is a feit, not a besluit), and the fields each carries:
A separate JSON schema for chronicle-stream files lives at schema/v0.6.0/chronicle.json. The relocation matters: a regulation is normative content, a chronicle-stream is a registration spec, and putting them in the same tree invites tooling to treat one as the other. The name chronicles/ reflects “which events does the cell’s chronicle accept”; a broader cell-config/ is left to a future RFC.
The four elements a future Wet gegevensboekhouding (Nieuwland §7.3.2) would ask for are already present per entry, what (name/fields), by whom (recording_actor), on which grondslag (grondslag), at which moment (the timestamp field); intake names through which channel the fact enters the cell, completing the record. This is a convention today, not a claim the law will be enacted; the norm-vs-registration separation stands on its own regardless.
Chronicle-streams participate in the federated-corpus mechanism (RFC-010) and in the RFC-013 Execution Receipt: when one contributes to an execution, its content-hash and version are recorded so the execution can be reproduced. (RFC-013’s loaded_regulations array is generalised to all loaded artefacts, a small follow-up amendment to RFC-013.)
The position paper’s chronolexocell is a containment and autonomy domain, and nothing more: chronolexograms are created and stored in it, cannot be edited outside it, and reduction “vindt altijd plaats ín de cel waar de betreffende chronolexogrammen zijn vastgelegd”. Its governing property is autonomy (“elke actor houdt eigen feiten bij in een eigen cel”). The paper attaches no signing keys, no transport, no authorisation, and no legal competence to the cell.
This RFC keeps the cell as the paper defines it and pulls two other concerns into their own axes:
competent_authority (RFC-002) is the legal competence to take the besluit a decretogram records. RegelRecht needs it because a decretogram is a besluit; it is a juridical fact, not a property of the storage domain.These vary independently, which is what makes the sandbox case and the key/transport questions tractable. A RegelRecht engine is one component that can run against a cell, alongside others (a legacy system, a payment-intake system); RFC-009’s one-engine / several-engines / mixed-component choices are unchanged.
| Chronolexografie | RegelRecht | RFC |
|---|---|---|
| chronolexocell | containment domain: chronicles + autonomy over own vastlegging (not keys, not competence) | this RFC §2 |
| chronolexokroniek | a time-ordered grouping of the cell’s chronolexograms, realised via chronicle-streams | §1.3 |
| chronolexogram | one decretogram (engine output) or one executogram (chronicle-stream event); each elementary | §1.2, §1.3 |
| chronolexoreductie | the within-cell filter/aggregate over the cell’s own chronicles, producing a lexostatus | §4 |
| lexostatus | the result of a reductie: the rechtstoestand from a requested perspective, on facts known in that cell | §4 |
| chronolexosynthese | the cross-cell activity: combining and judging lexostatussen from several cells | §4 |
| chronolexosphere | the set of all cells; transport over it is a security-context concern | RFC-009 |
| (no paper term) | competent_authority: legal competence for the besluit | RFC-002 |
| (no paper term) | security context: signing keys, trust material, transport selection, query authorisation | RFC-009 |
Two optional fields apply to chronolexograms regardless of type: modality (§3.1) and extensions (§3.2). The third concern, rechtsbescherming, is a derivation through RFC-008, not a field (§3.3).
modality: a backlink within RFC-008’s nested-procedure modelRFC-008 already settled intrekking and wijziging (Open Question 5: an intrekking is a state transition effected by a nested besluit with its own bekendmaking and bezwaar; a wijziging pending bezwaar is governed by Awb 6:19). This RFC adds no new semantics, only a backlink field so a downstream consumer can find the original besluit a new BESCHIKKING modifies without reconstructing it from procedure-state:
This avoids inventing INTREKKING_BESCHIKKING as a decision_type. The modality block is for one BESCHIKKING that modifies another; an executogram that effectively intrekt an earlier vordering uses the separate references_decision field (§3.3) instead.
extensions: namespaced integration hooksIntegrations attach configuration to chronolexograms without baking domain assumptions into the base schema. extensions is a namespaced map: each integration owns one namespace key, and the integration document for that namespace owns the shape and semantics inside its block. A reader of the schema sees that there is extension-driven behaviour, and which integration drives it, without the base schema having to know what category: ALGEMEEN means.
The first integration is blauwe_knop: a hint that a deployment may surface this rule’s decretograms (or this chronicle-stream’s events) in a Blauwe Knop source-endpoint.
The same namespaced block hangs off a decretogram (on produces) or a chronicle-stream event:
Two properties of the blauwe_knop block matter at the architecture level; the full stage-binding and validation mechanics live in the CJIB pilot proposal.
blauwe_knop_source feature-block; the same lexogram works either way. The presence of an extensions.blauwe_knop block is a hint for deployments that do activate the source.BEKENDMAKING onward, because before notification it has no juridical existence to display. visible_from_stage carries a legal consequence (a route-bearing decretype’s einddatum, in a bezwaar_route, beroep_route or verzet_route, is only populated from the route-populating stage), so it is a runtime-validated field with a per-integration default rather than a free-form one, and a route-bearing decretype must not be made visible before that stage. Enforcing that constraint (a route-aware guard, checked against the producing procedure) is a requirement on whichever deployment activates the source; until a deployment can enforce it, the blauwe_knop extension is experimental and a production security context must not activate the source for any route-bearing decretype. The CJIB pilot runs in a sandboxed context, which is what lets it exercise the Wahv source meanwhile.The rechtsbescherming-route is derived from the procedure_id that produced the chronolexogram, not declared on the rule. A static termijn_dagen: 42 or via: cell.cjib.bezwaar would duplicate what the procedure computes at the right stage. The route is whatever the decretype’s procedure prescribes, in at least three families:
bezwaar_route whose duration is the AWB-6:7 termijn (six weeks) but whose einddatum the AWB-6:8 hook fixes at BEKENDMAKING (the termijn cannot start before notification), complete only from BEKENDMAKING onward.beroep_route (not a bezwaar_route), selected from the procedure_id, never hard-coded per cell.beroep_route per Awb-7:1 lid 1 sub d (RFC-008 §A.8); a STRAFBESCHIKKING gets verzet (Sv 257e) from the criminal-procedure model, not RFC-008 (§1.2).In all families the route is computed by the engine and carries an actual einddatum, not a duration; what differs is the procedure, the field name (bezwaar_route vs beroep_route vs verzet_route), and the grondslag.
kwijtschelding_verleend event, in a sibling chronicle-stream joining the same cjib_main_chronicle (§1.3), declares references_decision (an optional event field holding the $id of the BESCHIKKING it executes), and the engine derives the route from that decision’s RFC-008 procedure-state. It is distinct from the §3.1 modality.is_intrekking_van backlink, which lives on a besluit.This RFC’s contribution to rechtsbescherming is not a new field but the requirement that integrations carry the route in their payloads, derived from the producing procedure.
source, runtime chooses the transportThe paper draws a two-level distinction this RFC adopts. Chronolexoreductie is the within-cell activity: each queried cell filters and aggregates its own facts into a lexostatus. Chronolexosynthese is the cross-cell activity: a consumer (or, in the citizen context, the citizen-client aggregating on-device) “combineert, vergelijkt en beoordeelt” lexostatussen from several cells. The cell never does cross-cell work; it only reduces its own chronicles.
A lexostatus is the canonical answer-shape a cell offers: the result of a reductie over one or more of its chronicles, expressing the rechtstoestand from a requested perspective on the facts known there. It is a cell-level capability, not the output of a single regulation execution. Each cell declares which lexostatussen it exposes and how each is reduced (provisional shape; full cell-config format is a future RFC):
The reduction orders across the cell’s own zaak-kronieken (not across cells, which is synthese, §4.1) on a common axis the reduction makes explicit: the made-it-fact timestamp every chronolexogram carries. The runtime ships the result in the transport-specific format (FCID over Blauwe Knop, ACCEPT-payload over FSC); same reduction, different serialisations. A consumer cannot inject a custom reduction, it can only ask for a published lexostatus and supply documented parameters, which keeps the reduction logic with the cell that holds the chronicles.
A regulation needing data from another cell uses the existing source block from RFC-007. No new fields, no kind discriminator: it names the producing cell and the lexostatus it wants.
Resolution order (canonical, normative). source.regulation resolves in this fixed order:
DataSourceRegistry (keyed on input.name) first. Unchanged by this RFC; named so the documented order matches the engine.$id in the loaded corpus, evaluate it as today.Name-collision handling. Because the value space is shared, a cell-id could equal a loaded regulation $id. This RFC introduces a new load-time error: a cell-id that shadows a loaded regulation $id fails at load time and never reaches query-time resolution. This is stricter than RFC-010’s regulation-vs-regulation collision (resolved by priority, since shadowing is intended there); a cell-vs-regulation shadow has no legitimate use and its consequence (a citizen-facing query silently rerouted to an unrelated regulation) is severe, so this errors unconditionally. This extends RFC-007’s resolver.
What changes is how the query travels. Two transports, chosen by the context the engine runs in:
The selection is a property of the security context (§2), not the regulation: a blauwe_knop_client block resolves via Blauwe Knop, an fsc_client block via FSC, and a context with both selects on the present authorisation. The same regulation YAML works unchanged in a citizen-application, a gemeente-systeem, or a research environment that mocks both. Blauwe Knop and FSC are not alternatives; they cover different juridical contexts (citizen-to-source under the data-at-source principle, organisation-to-organisation under a ground or mandate), and a source organisation typically binds two security contexts to one cell, both serving the same underlying lexostatus.
chronicles/ and the extension-activation site.chronicles/ layout.decision_type is an open string with a recommended vocabulary; a future type is a one-line vocabulary edit, not a breaking schema reopening. The same instinct drives the extensions namespace.decision_type trades static exhaustiveness for extensibility. A typo validates against the bare type: string; mitigation is the vocabulary file plus a warn-not-fail validator (MAY warn, MUST NOT reject). RegelRecht already pays this cost for RFC-018 ambiguity tags; the alternative (a closed enum) forces a breaking bump per future type.chronicles/ adds a second top-level directory tooling must learn about (one-time cost).extensions blocks are uninterpreted at the schema level, so a reader needs an integration document to know what a block means. The gain is that the schema is honest about this.decision_type breaks no consumers, the new modality/extensions blocks and the chronicle schema are additive, and cross-cell queries need no schema change. The minor-digit bump signals a meaningful contract change, not a break.Alternative 1: Put executogram-streams under corpus/. Rejected: conflates norm and registration. A registration-spec is not a regulation, and the Chronolexografie registreren-vs-interpreteren distinction collapses at the file-system level.
Alternative 2: Treat the engine itself as the cell. Rejected: ties the cell-concept to one binary. A cell must be able to hold multiple components or none; it is a containment domain (§2).
Alternative 3: Two anonymous outbound_emit / outbound_category fields on produces. Rejected: anonymous fields hide which integration drives them. A namespaced extensions.<integration> block makes the dependency explicit.
Alternative 4: Put activation in the regulation (fcid_emit: true). Rejected: makes integration-participation a property of the law, forcing a gemeente to fork the regulation. Activation belongs in the security context (§3.2).
Alternative 5: Keep the wrapper-regulation pattern (procedureregeling_vorderingenoverzicht_rijk). Rejected: misusing a juridical genre name for an adapter invites confusion. The reused-source approach (§4) is the right answer.
Alternative 6: A single source.kind: lexostatus_query discriminator with fresh cell:/lexostatus: fields. Rejected: invents schema for what source.regulation/source.output already express (§4.2).
Alternative 7: A per-rule bezwaarbaar block on produces. Rejected: RFC-008 already models bezwaar correctly, including that the termijn starts at BEKENDMAKING. A static termijn_dagen: 42 cannot reflect a computed einddatum. This RFC’s contribution is to require integrations to carry the route (§3.3), not redeclare it.
Alternative 8: Treat every cross-cell query as a server-to-server FSC call. Rejected: right for the bevoegde-instantie context, wrong for citizen-facing tools, where it would centralise data Blauwe Knop deliberately keeps decentralised. The runtime-selects-transport pattern (§4.3) keeps both contexts first-class.
Alternative 9: Treat the Blauwe-Knop-source as a push-emit (emit_at_stage). Rejected: Blauwe Knop is pull-based with no central destination. The stage-binding that matters is visibility at pull-time (§3.2); a genuinely push-based integration can define its own field in its own extensions namespace.
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