RFC-041: A Void Is Not Scoped Like a Replacement

ProposedImplemented
Depends on

Context

RFC-007 scopes lex specialis to the contextual law: the law that started the execution chain. Only overrides declared in that law apply, and a standalone call applies none at all. The reason is sound and the example in that RFC is the proof of it. A Vreemdelingenwet override on Awb 6:7 shortens the objection period for a vreemdelingenzaak and must not shorten it for a Participatiewet case. How much you get, or how long you have, can differ per the law invoking the general rule, and the invoking law is what says which answer applies.

Schema v0.7.0 added a second kind of override. voids: true says the output does not arise at all (RFC-027): “bestaat geen aanspraak” is not an entitlement of zero, because with zero there is a decision carrying legal remedies and a ground for recovery, and with none there is neither.

That construct inherited the scoping of the one it was built on, and it does not fit. Measured on the shape RFC-027 works out, zorgtoeslag article 3 voiding article 2 of the same law:

How the question is askedBefore
Through the law carrying the exclusionno value, correct
The granting law asked directly€ 1.550,45, provenance Direct
A third law reading that output cross-law€ 1.550,45, provenance Direct

A millionaire received the full amount along two of the three routes, including the most obvious one for a citizen-facing service: ask the law that grants the entitlement.

Decision

An override applies when the overriding law is the target law, whatever the contextual law is. Overrides from another law keep the RFC-007 rule unchanged.

This amends two statements in RFC-007. “When no contextual law is set (standalone API call), no overrides apply” now holds only for overrides from another law. “If multiple found within same contextual law: error” becomes: if more than one override applies to the same output, error, and name the laws they came from.

A consumer asking for a voided output gets a dedicated error carrying the ground, EngineError::OutputVoided with the voiding law, its article and the quoted legal_text_excerpt, rather than OutputNotFound.

Why

An exclusion in the same law is not a claim about the asking law. The contextual-law rule protects one law from another law’s special rule. Where the exclusion and the entitlement sit in the same law there is no other law to be protected from, and the rule only decided something by accident: which route the question took. An article of the zorgtoeslag saying the entitlement does not arise says that about the zorgtoeslag, not about whoever asked.

Scoping a void wrong is worse than scoping a replacement wrong. A replacement scoped too widely gives someone another law’s number, which the next check over the corpus can catch. A void scoped too narrowly hands out money the statute says is not owed, under a run that reports success, and nothing downstream can tell that the entitlement was excluded because the amount looks exactly like an ordinary one.

Why not unscope every void. Making a void from another law apply outside its context is defensible on the same reasoning, and it was considered. It is not decided here, for two reasons. It raises a question this design does not answer: what happens when two laws void the same output, or one voids what another replaces, where the conflict check only ever had to compare overrides from one law. And no law in the corpus uses voids yet, so the case is hypothetical; a rule written for a case nobody has met is a rule nobody can explain later. The narrow change closes every measured route.

Why a separate error. OutputNotFound is the shape of a misspelled output name or a broken binding. An operator reading it goes looking for a modelling defect that is not there, and a citizen is left without the ground for a decision that does exist. The engine already built the record; it was discarded on the way out.

Consequences

An intra-law void now fires on every entry point, traced and untraced alike. The traced path is what the editor’s scenario runner, the demo, the TUI and the BDD harness use, so a void that surfaced only without a trace would have left the silence this change removes exactly where a person looks.

markings[].target is unrelated to this and is corrected in the same schema version: its description claimed an empty list keeps the article executable, which the engine never implemented. What it does enforce, that a named value is absent from the article’s actions, is checked by the enrichment gate when the file is written.

References

  • RFC-007 Cross-Law Execution Model, the contextual-law rule this amends
  • RFC-027 Enrichment a Legal Expert Can Check, where voids and its ground come from
  • RFC-012 Untranslatables, for the marking channel target belongs to

RegelRecht

An exploration by Bureau Architectuur of the Dutch Ministry of Economic Affairs and Climate Policy into the possibilities of transparent, executable legislation.

Links

GitHub repository
How it works
Stay informed
Roadmap (Dutch)
Documentation
Research

Contact

regelrecht@minbzk.nl

Part of

Bureau Architectuur
Ministry of Economic Affairs and Climate Policy