RFC-022: Chronolexogram types in the schema and the cell model

DraftNot implemented
Depends on
RFC-002 (Bevoegdheid (Authority) in Machine-Readable Law), RFC-003 (Inversion of Control for Delegated Legislation), RFC-007 (Cross-Law Execution Model), RFC-008 (Awb Administrative Procedures), RFC-009 (Multi-Organization Execution), RFC-010 (Federated Corpus), RFC-013 (Execution Provenance)

Context

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):

  1. No fitting decision_type exists, so the domain cannot be expressed.
  2. There is no place to record factual events (payments received, kwijtscheldingen, deurwaardertrajecten); these are not regulation outputs and do not belong in produces.
  3. There is no clean separation between normative content (regulations) and registration specifications (which facts a deployment records), so integrations either invent a local format or push the recording into a regulation YAML.

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:

  1. The three chronolexogram types as first-class concepts in the schema and repository layout.
  2. The cell as a containment and autonomy domain, with legal competence (competent_authority) and the security context (keys, transport, authorisation) kept as separate axes (§2).
  3. Two cross-cutting fields on chronolexograms: modality and extensions.
  4. Cross-cell queries by reusing the existing 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).

Design principles

  1. The corpus is the lexogram store. Only normative content lives in corpus/regulation/.
  2. The chronicle store is separate. Registration specifications live in chronicles/; a registration-spec is not a regulation.
  3. A decretogram is an engine output with legal_character: BESCHIKKING. New decision_type values cover financial enforcement.
  4. An executogram is not a regulation output. It is declared in a chronicle-stream file, not in produces.
  5. A cell is a containment and autonomy domain (§2). Legal competence and the security context are separate axes; the engine is one component that can run against a cell.
  6. Integration configuration is a security-context concern, not a property of the law. Where it must touch a regulation, it is namespaced under extensions.
  7. Rechtsbescherming is derived from the producing procedure (RFC-008), not declared on the rule, and is not always Awb bezwaar (§3.3).
  8. Citizen-side aggregation is preserved. The runtime picks Blauwe Knop or FSC per security context; the schema does not centralise data.

Terminology

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.

Decision

1. Chronolexogram types

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).

1.1. Lexograms: already exist

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.

1.2. Decretograms: decision_type as an open vocabulary

A 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 bestuursorgaan
  • STRAFBESCHIKKING: criminal-law settlement under Sv art. 257a
  • BESTUURLIJKE_BOETE: sectoral administrative fine

To 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).

1.3. Executograms: chronicles/ directory

An 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:

$id: payments_received recording_actor: <organisation-id> # the actor (cell operator); NOT competent_authority chronicle: cjib_main_chronicle # which chronicle these events join events: - name: payment_received intake: external_intake # where the event enters the cell grondslag: <wettelijke-grondslag># on which legal ground this fact is recorded fields: case_reference: $external.case_reference amount_cents: $external.amount_cents received_at: $external.received_at # at which moment the fact occurred

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.)

2. The cell, the competent_authority, and the security context

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:

  • The cell holds chronicles, records chronolexograms, and runs reductions over its own facts. That is its whole job. One actor may keep several cells.
  • The 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.
  • The security context carries the signing keys (RFC-009 §5), the trust material, and the authorisation under which a cross-cell query is answered. The paper has no security model at all; these live off the cell. A deployment binds a security context to a cell (many-to-one in principle: a production and a sandbox context over comparable cells).

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.

ChronolexografieRegelRechtRFC
chronolexocellcontainment domain: chronicles + autonomy over own vastlegging (not keys, not competence)this RFC §2
chronolexokronieka time-ordered grouping of the cell’s chronolexograms, realised via chronicle-streams§1.3
chronolexogramone decretogram (engine output) or one executogram (chronicle-stream event); each elementary§1.2, §1.3
chronolexoreductiethe within-cell filter/aggregate over the cell’s own chronicles, producing a lexostatus§4
lexostatusthe result of a reductie: the rechtstoestand from a requested perspective, on facts known in that cell§4
chronolexosynthesethe cross-cell activity: combining and judging lexostatussen from several cells§4
chronolexospherethe set of all cells; transport over it is a security-context concernRFC-009
(no paper term)competent_authority: legal competence for the besluitRFC-002
(no paper term)security context: signing keys, trust material, transport selection, query authorisationRFC-009

3. Two cross-cutting fields, plus rechtsbescherming via RFC-008

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).

RFC-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:

produces: legal_character: BESCHIKKING decision_type: BETALINGSVERPLICHTING modality: is_intrekking_van: "<beschikking-id>" # optional backlink, per RFC-008 is_wijziging_van: "<beschikking-id>" # optional backlink, per RFC-008

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.

3.2. extensions: namespaced integration hooks

Integrations 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:

# on a decretogram produces: legal_character: BESCHIKKING decision_type: BETALINGSVERPLICHTING extensions: blauwe_knop: payload: fcid # for now always fcid; future-proof category: ALGEMEEN visible_from_stage: BEKENDMAKING # optional; defaults per integration # on an event in the payments_received chronicle-stream (§1.3) events: - name: payment_received extensions: blauwe_knop: { payload: fcid, event_type: BetalingVerwerkt, category: ALGEMEEN }

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.

  • Activation lives in the security context, not in the law. Whether a deployment serves a Blauwe-Knop-source is a security-context decision (§2). A gemeente running the same Wahv as CJIB but no source simply omits the 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.
  • Stage-aware visibility, not emission. Blauwe Knop is pull-based (a citizen-client authenticates and pulls on demand), so the RFC-008 binding is visibility, not emission: a verplichting becomes visible from 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.

3.3. Rechtsbescherming: derived from the procedure (RFC-008), not a field, and not always bezwaar

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:

  1. Awb-bezwaar route. For an ordinary Awb-beschikking (Awb titel 4.4 geldschulden, many bestuurlijke boetes): a 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.
  2. Lex-specialis own-regime route. The Wahv (Wet Mulder) replaces the Awb route with its own regime rather than offering Awb bezwaar: its remedy is administratief beroep before the officier van justitie (Wahv art. 6), then beroep before the kantonrechter (Wahv art. 9). The engine emits a beroep_route (not a bezwaar_route), selected from the procedure_id, never hard-coded per cell.
  3. Direct-beroep / no-route / verzet families. UOV procedures get 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.

  • For executograms. A feit carries no route by default. A specific executogram may, because it implicitly references a nested besluit: a 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.
  • Surface and propagation. A lexostatus includes the route per chronolexogram; the trace records the computed einddatum at the BEKENDMAKING node (RFC-008’s AWB-6:8 hook). When cell A accepts a decretogram from cell B over FSC (§4.3), the route travels with it, so cell A’s reduction surfaces the original objection route downstream.

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.

4. Cross-cell queries: lexostatus, reuse source, runtime chooses the transport

4.1 Lexostatus, chronolexoreductie, and chronolexosynthese

The 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):

# cells/cjib/capabilities.yaml (sketch; full cell-config format is a future RFC) lexostatus_definitions: - name: openstaande_vorderingen # all open obligations for a BSN, inputs: [{ name: bsn, type: string }] # filtered on stage, net of withdrawals reduction: # over cjib_main_chronicle (§1.3): keep # BETALINGSVERPLICHTING from BEKENDMAKING onward, drop withdrawn ones, # group_by zaakkenmerk, order_by bekendmaking_datum

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.

4.2 Source resolution

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.

input: - name: openstaande_vorderingen source: regulation: cjib # the cjib cell-id, resolved by the runtime output: openstaande_vorderingen # the lexostatus from §4.1 parameters: bsn: $bsn

Resolution order (canonical, normative). source.regulation resolves in this fixed order:

  1. Data-source tier. The engine short-circuits against the DataSourceRegistry (keyed on input.name) first. Unchanged by this RFC; named so the documented order matches the engine.
  2. Loaded-regulation tier (RFC-007). If the value matches a regulation $id in the loaded corpus, evaluate it as today.
  3. Cell tier (this RFC). Only when no loaded regulation matches: a cross-cell query for the named lexostatus.
  4. When none match, error.

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.

4.3 Transport selection

What changes is how the query travels. Two transports, chosen by the context the engine runs in:

  • Citizen-client context (Blauwe Knop). When the engine runs inside a citizen-client (RegelRecht-WASM, a mobile app), the query resolves via Blauwe Knop Connect: the citizen has a DigiD session, the engine pulls the cell’s source-endpoint, verifies the signed FCID-response against the App Manager’s trust material, and returns the result. No server-side aggregation; data stays on-device.
  • Authorised-server context (FSC). When the engine runs on a server of a bevoegde instantie with a statutory ground (or explicit citizen mandate), the query resolves via FSC along the RFC-009 ACCEPT path: the receiving cell’s security context verifies the signed call and asserted ground (§2), then answers from its own reductie.

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.

5. Out of scope

  • Specific outbound serialisation formats, and specific integration partners (integration/casus documents).
  • The AWB lifecycle and bezwaar mechanics (RFC-008), trust and signing (RFC-009 §5), provenance (RFC-013), federation transport (RFC-009), federated corpus distribution (RFC-010).
  • The full cell-config format (a future RFC); this RFC introduces only chronicles/ and the extension-activation site.
  • The legal basis for inter-organisation data exchange (per-case, not engine-level), and the governance of which facts are vastlegbaar (a policy matter; this RFC fixes only the mechanism).
  • A statutory Wet gegevensboekhouding (Nieuwland §7.3.2): a legislative artefact, not an engineering one.

Open Questions

  1. Cell roles along the production-mode axis. §1 names a difference between the compile-time, generic lexogram and the operational, individual decretograms and executograms. This may mean publishing and executing are different roles a cell plays, possibly different kinds of cell. A follow-up should decide whether a cell role becomes a first-class declaration and how it interacts with the chronicles/ layout.
  2. Security-context binding. §2 separates the security context from the cell but does not specify how it is declared, how it binds, or how it relates to the FSC and Blauwe-Knop trust models. The full format is for a follow-up.
  3. Update cadence as a designed property. There is a ladder of update mechanisms at increasing cost: editing a vocabulary file (§1.2), publishing a schema version, rolling out an engine version. The first two are addressed; whether engine-version rollout needs a standard mechanism warrants its own RFC.
  4. One mechanism, two peers, vs. two transports. §4.3 describes two transports; a reading worth testing is that these are one query mechanism over a cell’s chronicles with two kinds of peer (a person vs. an organisation). Tracked for a later revision of §4.

Why

Benefits

  • Lexogram, decretogram and executogram are explicit and separately located. A reader sees the type from the path alone.
  • The cell is a containment domain, not a binary, and not the legal authority (§2): keys and competence are separate axes rather than bolted onto the cell.
  • The financial-enforcement domain becomes expressible without mixing types and modalities.
  • The decretogram typology stays open. 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.
  • Activation lives in the security context. A gemeente runs the same Wahv lexogram as CJIB without forking it just because it does not emit FCID.
  • Cross-cell queries are first-class, with no fake-regulation adapters, and rechtsbescherming reuses RFC-008 with no parallel mechanism.
  • Chronicle-streams are reproducible via RFC-013 Execution Receipts.

Tradeoffs

  • Opening 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.
  • An FCID-aware regulation YAML can be loaded by a deployment that does not activate the source, without effect. Acceptable: presence is a hint, activation is a security-context decision.
  • Integrations must understand RFC-008 stages to decide visibility at the right moment (a constraint on integration authors; the CJIB pilot proposal demonstrates the pattern).
  • The proposed schema bump (v0.5.x → v0.6.0) is close to purely additive: opening 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.

Alternatives Considered

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.

References

RegelRecht

An exploration by Bureau Architectuur of the Dutch Ministry of the Interior into the possibilities of transparent, executable legislation.

Links

GitHub repository
How it works
Stay informed
Documentation

Contact

regelrecht@minbzk.nl

Part of

Bureau Architectuur
Ministry of the Interior and Kingdom Relations