Problem. RFC-019 selects law versions against a single global
calculation_date. That answers “is this law in force today?”, but Dutch law routinely requires
resolving a referenced law as it stood on a different date, and that date must propagate to
everything resolved beneath the reference:
The event dates already exist: RFC-008 (“the lifecycle is law”) carries
aanvraag_datum, besluit_datum, bekendmaking_datum as stage inputs. What is missing is a way
for a reference to be resolved at one of those dates instead of the global calculation_date.
Add an optional as_of to a cross-law reference / open-term resolution: the referenced law
(and everything beneath it) is resolved at that date, using RFC-019’s
valid_from/valid_to selection.
| Source | Vindplaats | Role in this RFC |
|---|---|---|
| Awb art. 7:11 (heroverweging) | BWBR0005537 | lid 1: “Indien het bezwaar ontvankelijk is, vindt op grondslag daarvan een heroverweging van het bestreden besluit plaats.” (example A) |
| Awb art. 5:46 lid 4 + art. 1 lid 2 Sr | BWBR0005537 · BWBR0001854 | lex mitior codified: “Artikel 1, tweede lid, van het Wetboek van Strafrecht is van overeenkomstige toepassing.” (§4, example C) |
| Ex-nunc jurisprudence | ABRvS Greenpeace 28-10-2020 (ECLI:NL:RVS:2020:2571, standard arrest, r.o. 6.2.3-6.2.9) · Steenwijkerland 21-12-2016 (ECLI:NL:RVS:2016:3388) · Berg en Dal 21-02-2018 (ECLI:NL:RVS:2018:610, exception-side anchor) | the ex-nunc default is jurisprudential, not statutory (§3) |
| Lex-mitior jurisprudence | ABRvS 21-05-2025 (ECLI:NL:RVS:2025:2223) · ABRvS 30-08-2023 (ECLI:NL:RVS:2023:3291) · CBb 06-07-2021 (ECLI:NL:CBB:2021:700) | mandatory favourable-provision duty confirmed through beroep (§4) |
| Aanwijzingen 3.47 / 5.60 / 5.61 / 5.64 | BWBR0005730, deep links via kcbr.nl | drafting conventions: statische/dynamische verwijzing, plaats overgangsrecht, onmiddellijke werking, eerbiedigende werking (besluit van de Minister-President, not substantive law) |
| Wet IB 2001 art. 10bis.1 | BWBR0011353 | the “zoals dat luidde op |
| Awb bezwaartermijn chain | corpus/.../algemene_wet_bestuursrecht/1994-01-01.yaml, features/bezwaartermijn.feature | existing modeled lifecycle this RFC builds on |
Conflating these is the root confusion:
| Axis | Question | Where it lives |
|---|---|---|
| Instrument validity | When is this text in force? | valid_from / valid_to (RFC-019) |
| Substantive scope | Which period/facts does the norm govern? | the rule’s conditions + temporal metadata (RFC-001 §8) |
| Applicable-date selection | Which version-date do we evaluate a reference against? | this RFC, computed by law, carried per reference |
as_of on a reference, propagating down the subtreeas_of): follows the global calculation_date, the hoofdregel
(Aanwijzing 3.47) and current behaviour.as_of: <date | $param>: a literal date models a statische verwijzing; a parameter (e.g.
$besluit_datum) models ex tunc / eerbiedigende werking.as_of.
Event dates and date arithmetic exist (RFC-008, RFC-007 §3).as_of. This refines RFC-008’s ex-nunc default; it does not contradict it.Art. 5:46 lid 4 Awb makes the lex-mitior principle (art. 1 lid 2 Sr) van overeenkomstige toepassing
on bestuurlijke boetes, so one besluit op bezwaar can be ex nunc on the merits while the boete
compares two dates. This proves as_of must be per-reference, not one global date.
Four boundaries keep it faithful and out of the engine:
as_of + an operation;
which is favourable is domain knowledge in the rule (fixed fine → MIN; conduct no longer
punishable → IF). The engine never “tries all dates and optimizes”.Hook and override candidates are already filtered by valid_from (RFC-007);
RFC-019’s valid_to and this RFC’s as_of apply identically: an ended candidate
drops out, as_of selects the applicable version. A conformance case (RFC-014)
locks this in.
The IoC pattern (open_terms/implements, RFC-003) follows the same
propagation rule: when a reference carries as_of, implementing regulations for the referenced
subtree are selected at the propagated date, not at calculation_date. A statische verwijzing to
an older version of a law therefore uses the implementing regulations that were in force on that
date, the legally correct reading, and the only one consistent with “inherited down the subtree”.
Selecting implementations at calculation_date would be an undocumented exception to that rule.
Whether the heroverweging applies the law of the beslissing op bezwaar moment (ex nunc) or of the
original besluit moment (ex tunc) is selected by which event date is passed as as_of:
(Illustrative: the corpus vreemdelingenwet_2000 does not yet expose
verblijfsvergunning_verleend, and Awb 7:11 is not yet in the corpus Awb; the modeled chain today
is the bezwaartermijn. The example shows the mechanism; modeling the heroverweging is
implementation work.)
Two inputs resolve the same output at the two legally relevant moments; the selector (MIN, since
for a fixed fine the lower amount is favourable) lives in the law. Stays within the existing
operation grammar: only as_of is new.
($besluit_datum is the existing RFC-008 BEHANDELING stage input.
$overtreding_datum is not: a boete procedure needs its own lifecycle that adds it as a stage
input; that lifecycle is future RFC-008 extension work, alongside modeling this pattern.)
MIN/IF-over-two-as_of per boete-law.valid_to
static and defers a “terminates” mechanism that derives a law’s end from the terminating
instrument. That is the same cross-law, date-aware territory as as_of and belongs alongside
this model.calculation_date inside an inherited as_of context: propagation (§2) is
“inherited down the subtree, innermost wins”, and calculation_date is an engine-level value
that is not addressable as a $-parameter in law YAML, so a referenced law cannot declare
“always resolve my sub-references at the current date” (e.g. a dynamic rate table). This is a
deliberate constraint for temporal consistency. An explicit escape would need an engine
change (injecting calculation_date as a reserved parameter, with name-collision and
nested-subtree semantics to settle), not just a schema addition, so it stays out of scope until
a real corpus case demands it.as_of: $param with the parameter absent at runtime: silently falling back to
calculation_date would hide a caller error and contradict RFC-015’s
zero-domain-knowledge policy, because the engine cannot know whether the date was optional. The
expected resolution is a strict resolution error (mirroring how missing required inputs already
fail), but this must be settled in the implementation.Extends the cucumber-rs harness (features/bezwaartermijn.feature, features/einddatum.feature):
as_of: $besluit_datum vs the default, with two versions of the target loaded.as_of resolves correctly when calculation_date is past
the target’s valid_to but as_of is within the validity window (interaction with
RFC-019).as_of dates yields the favourable (lower) result.as_of inherits the outer one; an inner as_of
overrides for its subtree.as_of past the target’s valid_to (e.g. as_of: '2027-01-01' on a law
with valid_to: '2026-12-31') yields a RFC-019 §3 SelectionReason error
(EndedOn) reported against the resolved date, never a silent miss.as_of before the target’s valid_from (law not yet in force,
e.g. an overtreding_datum predating the law) yields the corresponding SelectionReason
error (NotYetInForce).as_of, implementing regulations (open_terms/implements,
RFC-003) are selected at the propagated date, not at calculation_date,
the §5 rule, with two versions of an implementing regulation loaded.Plus as_of cases in the Temporal conformance level (RFC-014).
as_of can resolve an earlier version even
after the target’s valid_to; an ended reference at the default date still fails honestly
(RFC-019 §3, stated relative to the resolved date).as_of and its
propagation are new.as_of must thread through cross-law resolution, the reference
subtree, cycle detection and the memoization cache (the key must include the resolution date,
or example C’s two lookups of the same output would collide).as_of on source (literal date or $-parameter), encoded as the
existing union pattern oneOf: [variableReference, {type: string, format: date}] so malformed
dates and unprefixed parameter names fail validation. as_of is only meaningful when
regulation is present (there is no law to version-select otherwise); the schema must make
that conditional (e.g. if: {required: [regulation]}), not silently ignore it. source is
additionalProperties: false, so this needs a new minor schema version (additive, non-breaking).as_of (default calculation_date) through the cross-law resolution path;
inherit down the subtree, innermost wins; reuse RFC-019’s selection at the
resolved date; include the resolved date in memoization and cycle-detection keys; report
selection failures (RFC-019 §3 SelectionReason) relative to the resolved date.
Date-keyed cycle detection catches same-date self-reference; a regressive chain (A at D
referencing A at D−1, and so on) has a unique key per step and is backstopped by the engine’s
existing cross-law depth limit (MAX_CROSS_LAW_DEPTH), a deliberate constraint, since static
corpus YAML cannot generate ever-older as_of values itself.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