Schema Reference

The JSON schema every law YAML file must conform to: its fields, operations and vocabulary, and how versioned schema URLs work.

The law format is defined by a JSON Schema. All law YAML files in the corpus must conform to this schema.

Everything below the version history is generated from the released schema itself, so this page and the contract cannot disagree. Where a field has a concept page, the table links to it.

Current Version

The current schema version is v0.7.0.

Schema URLs use immutable git tags to guarantee reproducibility. The format is:

https://raw.githubusercontent.com/MinBZK/regelrecht/refs/tags/schema-v0.7.0/schema/v0.7.0/schema.json

The tag schema-vX.Y.Z is created when a schema version is released. Using tags instead of refs/heads/main ensures that the schema a law file references can never change underneath it. See RFC-013 for the rationale.

Version History

This table is the single source of truth for which schema version introduced which construct. RFCs that add a construct reference this table rather than asserting a version independently.

VersionIntroducesRFC
v0.7.0placement on articles: the chapter, title, division and paragraph that enclose it, with their headings. markings replaces untranslatables (a flag on an article that is otherwise worked out, with resolution, resolved_by and target), declares records a document property an article establishes, and enables is removed. open_terms gains expected_source, decided_per_case_by and a closed delegation_type. An override can state voids: true with a legal_text_excerpt. Operations DATE_PART and START_OF. Not additive: a file carrying untranslatables or enables does not validate under v0.7.0 and goes through law-migrateRFC-031, RFC-032, RFC-027
v0.6.0No new constructs. Fills in the description of every field that lacked one, rewrites 39 that were already there, and adds examples, so the schema documents itself and this page can render it. Both keywords are annotation-only, so a file valid under v0.5.9 is valid under v0.6.0 unchangedRFC-040
v0.5.9RECHTSPOSITIE added to produces.legal_character and to the hooks.applies_to filter: a legal position of a person that arises by operation of law, without a besluit and without an aanvraagRFC-038
v0.5.8nullable on parameters, inputs and outputs: whether null (absence) is a legitimate value of the field; defaults to false, and the validator and the engine hold a law to it. Also corrects the description of required on execution parameters: it defaults to true, and an omitted required: false parameter is an unknown value, not an errorRFC-036
v0.5.7FOREACH operation (iteration over a variable-length collection)RFC-016
v0.5.6Quantity unit labels (euro, ratio, percentage) and structured definitions constants carrying type/type_specRFC-023
v0.5.5ROUND, CEIL, FLOOR rounding operations (explicit statutory rounding)RFC-024
v0.5.4DATE_DIFF operation; date operands for the comparison operatorsRFC-021
v0.5.3valid_to (law end date)RFC-019
v0.5.2annotation-schema.json for stand-off notesRFC-005, RFC-018
v0.5.1Tag-based immutable schema URLs; refinements within the v0.5.x lineRFC-013
v0.5.0hooks, overrides (reactive execution); procedure, procedure_id (Awb lifecycle); Woo supportRFC-007, RFC-008
v0.4.0open_terms, implements (IoC); legal_character; date and array value typesRFC-003
v0.3.2SUBTRACT_DATE split into its own date operation with a unit (days, months, years)
v0.3.1Structured references on articles (bwb_id, artikel, lid, onderdeel, …) for runtime cross-reference resolution
v0.3.0Typed operation definitions (arithmetic, logical, comparison, conditional, switch) with semantic operands and legal_basis, replacing the single untyped operationRFC-004
v0.2.0Initial public schema: regulatory_layer, competent_authority, execution.produces, cross-law references (source)RFC-001, RFC-002

Multi-organization execution (RFC-009) reuses competent_authority (v0.2.0) and adds no schema construct of its own. Absent and unknown values (RFC-036) add one construct, the nullable flag of v0.5.8, and otherwise fix what the engine does with existing constructs over a missing value; v0.5.8 also corrects the wording of required, whose text said “defaults to false” while the engine has always read an absent flag as required.

The annotation schema (annotation-schema.json) versions independently of the law schema: it is republished only when it changes. It was introduced at schema/v0.5.2/ and last republished at schema/v0.5.3/, which is the version the validators embed.

Validation

Validate law files against the schema:

just validate # All files just validate corpus/regulation/nl/wet/wet_op_de_zorgtoeslag/2025-01-01.yaml # Specific file

For a guided walkthrough of how a law is written, rather than a field list, see Law Format.

The law file

A law file is one regulation at one point in time. These 21 keys sit at the top level; articles carries the text and, where a provision has been translated, its machine_readable section.

FieldTypeDescriptionnamestringstringName of the law/regulation (can be plain text or internal reference like '#wet_naam').publication_datestringstringDate when the law/regulation was officially published (publicatiedatum). Must match ^[0-9]{4}-[0-9]{2}-[0-9]{2}$. valid_fromstringstringDate when the law/regulation becomes effective (inwerkingtredingsdatum), or an internal reference starting with #. Must match ^([0-9]{4}-[0-9]{2}-[0-9]{2}|#.+)$. '2025-01-01'Temporal Validityvalid_tostringstringLast calendar day on which the law/regulation is in force, inclusive (einddatum). Set ONLY when the law is terminated - it vervalt or wordt ingetrokken (a horizonbepaling/vervalbepaling, or repeal by another instrument); omit when a newer version of the same law simply takes over. A statutory 'vervalt met ingang van D' maps to valid_to = D minus one day. Must be a literal date (no internal references): the engine reads it as static version-selection metadata; end dates derived from another instrument or an executed article output are future work. See RFC-019. Must match ^[0-9]{4}-[0-9]{2}-[0-9]{2}$. '2024-12-31'Temporal Validityregulatory_layerstringstringType of legal instrument (regelgevingslaag). It fixes which identifier the file must carry, and it ranks candidates when several regulations implement the same open term. Which layer may implement a term is set by that term's delegation_type, not by this field alone.WETGEMEENTELIJKE_VERORDENINGurlstringstringOfficial URL of the law text this file was written from, at the version stated in valid_from.https://wetten.overheid.nl/BWBR0018451/2025-01-01bwb_idstringstringBWB identification number (for Dutch national laws). Must match ^BWBR[0-9]{7}$. BWBR0018451celex_nummerstringstringCELEX number (for EU regulations and directives).32013R1303elistringstringEuropean Legislation Identifier (for EU laws).tractatenblad_idstringstringTractatenblad identification (for international treaties).unts_nummerstringstringUN Treaty Series number (for international treaties).gemeente_codestringstringCBS municipality code (for municipal regulations). Must match ^GM[0-9]{4}$. GM0363provincie_codestringstringCBS province code (for provincial regulations). Must match ^PV[0-9]{2}$. waterschap_codestringstringCBS water board code (for water board regulations). Must match ^WS[0-9]{4}$. officiele_titelstringstringOfficial full title (for decentralized regulations).stcrt_idstringstringStaatscourant identification number.organisationstringstringOrganization responsible (for implementation policies without official IDs).legal_basisarray of objectarray of objectArticles of higher law that authorize this regulation: the grondslag. Not the same shape as the legal_basis a field or action carries, which cites a provision far more precisely.preambleobjectobjectThe aanhef, the passage before Article 1 that names the authority the regulation is made under. It carries no operative norm of its own, so it rarely computes anything.articlesarray of objectarray of objectThe articles of this regulation, in the order they appear in the law. An article is carried as text whether or not it has been translated; machine_readable is what makes one executable.Law Formatprocedurearray of objectarray of objectAWB-defined procedure lifecycles for administrative decisions (RFC-008).Administrative procedure stages

Identifiers per regulatory layer

Which identifier a file must carry depends on what kind of instrument it is. A national law is identified by its BWB number, an EU regulation by its CELEX number, a municipal ordinance by the CBS municipality code plus its official title. The schema states this as conditional requirements:

Regulatory layerRequired
legal_basis[]

The articles of higher law that authorize this regulation. Not the same shape as the legal basis a field or action carries: this one names a law by law_id and nothing finer than an article.

FieldTypeDescriptionlaw_idstringstringIdentifier of the law that provides authority.articlestringstringArticle number that authorizes this regulation.descriptionstringstringOptional explanation of the legal relationship.

preamble

preamble

The aanhef, the passage before Article 1 that names the authority the regulation is made under. It carries no operative norm of its own, so it rarely computes anything.

FieldTypeDescriptiontextstringstringPreamble text in markdown format, preserving original formatting from official publication.urlstringstringURL to the preamble in the official publication (if available).machine_readableMachine readable sectionMachine readable sectionMachine-readable interpretation of the preamble, in the same shape as an article's. The Rust law-model carries no preamble at all, so this is read by nothing today.

procedure

procedure[]

AWB-defined procedure lifecycles for administrative decisions (RFC-008).

FieldTypeDescriptionidstringstringUnique identifier for this procedure (e.g., 'beschikking', 'beschikking_uov').defaultbooleanbooleanWhether this is the default procedure for its legal_character.applies_toobjectobjectWhich decisions this procedure governs, matched on the legal character an article declares in produces.stagesarray of objectarray of objectThe lifecycle stages in order, from the application to the final decision. Each names itself and what it needs before it can complete.

stages

procedure[].stages[]

The lifecycle stages in order, from the application to the final decision. Each names itself and what it needs before it can complete.

FieldTypeDescriptionnamestringstringStage name (e.g., AANVRAAG, BESLUIT, BEKENDMAKING).descriptionstringstringHuman-readable description.requiresarray of objectarray of objectExternal inputs required to enter this stage.

Articles

Each entry of articles is one provision: its number, its verbatim text, and the URL it was taken from. machine_readable is present only where the provision has been translated, which for most of the corpus is not yet the case. An article without it is carried as text and nothing more.

FieldTypeDescriptionnumberstringstringArticle number as it appears in the law.textstringstringArticle text in markdown format, preserving original formatting from official publication (numbered lists, links, paragraph structure).urlstringstringURL to this specific article.machine_readableMachine readable sectionMachine readable sectionMachine-readable interpretation of this article. Absent when the article has not been translated, which is the normal state for most of the corpus: an article without this key is carried as text only.referencesarray of objectarray of objectStructured references to other laws and articles. Accepted by the schema, but the Rust law-model has no field for it and drops it on load, so nothing resolves these at runtime today.placementobjectobjectWhere this article sits in the document: the containers that enclose it, each with its number and its opschrift. The opschrift is condensed legal classification written by the legislator, and it decides questions the article text alone cannot answer. Awb 3:9 only makes sense once you can see it sits in 'Afdeling 3.3 Advisering', because the adviseur definition of 3:5 lid 1 is scoped to that division. Absent for an article that no container encloses, which is normal in a short law.

references

articles[].references[]

Structured references to other laws and articles. Accepted by the schema, but the Rust law-model has no field for it and drops it on load, so nothing resolves these at runtime today.

FieldTypeDescriptionidstringstringReference ID used in markdown links (e.g., 'ref1').bwb_idstringstringBWB identifier of referenced law. Must match ^BWBR[0-9]{7}$. artikelstringstringArticle number in referenced law.lidstringstringLid (paragraph) number.onderdeelstringstringOnderdeel (sub-item) letter/number.hoofdstukstringstringChapter number.paragraafstringstringParagraph number.afdelingstringstringSection number.

placement

articles[].placement

Where this article sits in the document: the containers that enclose it, each with its number and its opschrift. The opschrift is condensed legal classification written by the legislator, and it decides questions the article text alone cannot answer. Awb 3:9 only makes sense once you can see it sits in 'Afdeling 3.3 Advisering', because the adviseur definition of 3:5 lid 1 is scoped to that division. Absent for an article that no container encloses, which is normal in a short law.

FieldTypeDescriptionboekobjectobjectdeelobjectobjecthoofdstukobjectobjecttiteldeelobjectobjectafdelingobjectobjectparagraafobjectobject

The machine_readable section

An article carries this when it has been translated. It holds the executable part (execution) and the annotations around it: what the article delegates, what it implements, which authority decides, and what could not be translated.

FieldTypeDescriptionendpointstringstringNamed endpoint for this article. Accepted by the schema, but the Rust law-model has no field for it and drops it on load; a law calls another law by output name, not by endpoint.competent_authoritystring or objectstring or objectBevoegd gezag: the authority whose execution of this article produces a binding decision. Another body may run the same calculation and get the same number, but its result carries no legal force (RFC-009). Annotation only: the engine computes the same either way.Competent Authorityrequiresarray of objectarray of objectOther provisions this article depends on. The schema and the Rust law-model disagree on the shape here: the model expects a list of names, so a law written to the structure below fails to load.open_termsarray of objectarray of objectAbstract values that this article leaves open and that an implementing regulation or implementing policy fills at a lower level. Any regulatory layer can declare open_terms; a law typically has required: true (no default), lower layers often provide defaults that can be refined further down. This is the single place for an open norm, whether the article names who fills it ('bij ministeriele regeling') or leaves that open ('redelijkerwijs'); in the second case delegated_to and delegation_type are simply absent and any competent authority may fill it through implementing policy. Whether the filling regulation is currently in the corpus is a state of the corpus and not a property of the law, so it is not recorded here.- id: standaardpremie type: amount required: trueInversion of Controlimplementsarray of objectarray of objectDeclares that this article fills open terms from a higher-level law. Maps to the 'Gelet op' clause in Dutch legislation. One article can implement multiple open terms from different laws.- law: wet_op_de_zorgtoeslag article: '4' open_term: standaardpremie gelet_op: Gelet op artikel 4 van de Wet op de zorgtoeslagInversion of ControldefinitionsobjectobjectDefinitions and constants. Each entry is either a bare value (naam: 123) or the optionally-structured form carrying a type and type_spec so the constant can declare its quantity-kind (RFC-023): naam: {value: 123, type: amount, type_spec: {unit: eurocent}}.DefinitionsexecutionobjectobjectThe executable logic of this article: what it needs, what it computes and what it yields.hooksarray of objectarray of objectHook declarations: this article fires when matching lifecycle events occur (RFC-007).Hooksoverridesarray of objectarray of objectOverride declarations: this article replaces another article's output (RFC-007, lex specialis).- law: algemene_wet_bestuursrecht article: '6:7' output: bezwaartermijn_wekenOverrides (lex specialis)markingsarray of objectarray of objectConstructs in this article that the format itself cannot express. A marking is a flag on an article that is otherwise worked out: it names the one thing that does not fit and leaves everything that does fit standing. A marking that empties an article is a defect, not a translation. Keep it strictly apart from open_terms, which say the opposite: the language can express this fine, the content is filled elsewhere. Replaces untranslatables and norm_gaps from earlier schema versions.Markingsdeclaresarray of objectarray of objectDocument properties this article establishes. A citation title, a commencement date or a scope in time is not a calculation, and it is not nothing either: it fixes a value the rest of the corpus and every trace depend on. Article 51 of the Awir says what that law is called, and a trace that names the law is quoting that article. Recording it here makes the article accounted for and lets a check hold the document header against the provision that decides it.

requires

machine_readable.requires[]

Other provisions this article depends on. The schema and the Rust law-model disagree on the shape here: the model expects a list of names, so a law written to the structure below fails to load.

FieldTypeDescriptionarticlestringstringArticle number within this law.lawstringstringName of external law.regelingstringstringName of ministerial regulation.koninklijk_besluitstringstringName of royal decree.valuesarray of stringarray of stringThe outputs this article needs from the dependency, named so the dependency is checkable rather than implied.

open_terms

machine_readable.open_terms[]

Abstract values that this article leaves open and that an implementing regulation or implementing policy fills at a lower level. Any regulatory layer can declare open_terms; a law typically has required: true (no default), lower layers often provide defaults that can be refined further down. This is the single place for an open norm, whether the article names who fills it ('bij ministeriele regeling') or leaves that open ('redelijkerwijs'); in the second case delegated_to and delegation_type are simply absent and any competent authority may fill it through implementing policy. Whether the filling regulation is currently in the corpus is a state of the corpus and not a property of the law, so it is not recorded here.

FieldTypeDescriptionidstringstringIdentifier for this open term (e.g., 'standaardpremie').descriptionstringstringHuman-readable description of what this term represents.typestringstringData type of the expected value.requiredbooleanbooleanWhether an implementation is mandatory (true) or optional with possible default (false). Defaults to true. delegated_tostringstringWho the article authorises to fill this term (e.g. 'Onze Minister', 'gemeenteraad'). Absent when the article names nobody, which leaves the term to whichever authority is competent in the individual case.delegation_typestringstringThe regulatory layer the article requires of the implementation. An implementation at another layer does not fill this term: delegation is a question of competence, and a regulation that takes on what the law did not delegate to it has nothing to give. Closed here rather than free text, so a misspelling is caught when the file is written instead of years later when the filling regulation is finally harvested.legal_basisstringstringThe provision that delegates this term, as it reads in the law (e.g. 'artikel 4 Wet op de zorgtoeslag').defaultobjectobjectDefault execution logic, making the article executable standalone while still allowing refinement through implements. It applies in two cases: no implementing regulation was found, and an implementation ran but returned null for this case.expected_sourcestringstringThe regulation the article itself names as the one that fills this term (e.g. 'Regeling zorgverzekering'), a BWB id when the text carries one. Which regulation is meant is a property of the law, so it belongs here, next to delegated_to and delegation_type. Whether that regulation is currently in the corpus is not: that changes without the law changing, and it belongs to the resolve step.decided_per_case_bystringstringThe authority that fills this norm in the individual case while no general specification exists, with the article that makes it competent. Which authority may decide is a property of the law, so it belongs here. Its answer needs a motivation (Awb 3:46) and is part of the besluit rather than a ground for it, which is what separates a discretionary power from a value that is merely missing.

implements

machine_readable.implements[]

Declares that this article fills open terms from a higher-level law. Maps to the 'Gelet op' clause in Dutch legislation. One article can implement multiple open terms from different laws.

FieldTypeDescriptionlawstringstringThe $id of the higher-level law being implemented (e.g., 'wet_op_de_zorgtoeslag').articlestringstringArticle number in the higher law that declares the open_term (e.g., '4').open_termstringstringThe open_term id being filled (e.g., 'standaardpremie').gelet_opstringstringLegal reference text (e.g., 'Gelet op artikel 4 van de Wet op de zorgtoeslag').

hooks

machine_readable.hooks[]

Hook declarations: this article fires when matching lifecycle events occur (RFC-007).

FieldTypeDescriptionhook_pointstringstringWhere in the lifecycle of another article's decision this one runs: before its actions or after them.applies_toobjectobjectWhich decisions of other articles this hook fires on. legal_character is required; adding decision_type or stage narrows it further.

overrides

machine_readable.overrides[]

Override declarations: this article replaces another article's output (RFC-007, lex specialis).

FieldTypeDescriptionlawstringstringThe $id of the law whose output is being replaced: lex specialis written down. An override from another law fires only when that law is the one being executed, so with no such context it does not apply (RFC-007). An override on an output of its own law applies whatever the contextual law is, because an exclusion in the same law is not a claim about the asking law (RFC-041). The engine does not check that the override is legally valid.articlestringstringThe article number being overridden.outputstringstringThe specific output being replaced.voidsbooleanbooleanThe overridden output does not arise at all, rather than being replaced by another value. "Bestaat geen aanspraak" is not an entitlement of zero: with an entitlement of zero there is a decision carrying legal remedies and a ground for recovery, and with no entitlement there is neither. An engine reads this flag and nothing else; it needs no knowledge of administrative law to act on it.legal_text_excerptstringstringThe words of this article that establish the override, quoted verbatim, as markings already do. A closed vocabulary was considered and rejected: it would make the agent translate the statute into a category, which is the interpretive step this format exists to avoid. A quotation only has to be copied, and a check can hold it against the article's own text.

markings

machine_readable.markings[]

Constructs in this article that the format itself cannot express. A marking is a flag on an article that is otherwise worked out: it names the one thing that does not fit and leaves everything that does fit standing. A marking that empties an article is a defect, not a translation. Keep it strictly apart from open_terms, which say the opposite: the language can express this fine, the content is filled elsewhere. Replaces untranslatables and norm_gaps from earlier schema versions.

FieldTypeDescriptionaboutstringstringThe construct that cannot be expressed, in the words the article uses (e.g. 'het kalenderjaar waarop de tegemoetkoming betrekking heeft')reasonstringstringWhy this construct does not fit the format, in terms of what the format does have. This is the diagnosis, and it is the field a reviewer needs to tell a well-examined gap from a wish: resolved_by follows from it, and not the other way round. Round 4 showed the asymmetry: 'voor zover limits application per provision of this law rather than the law as a whole, and the model only knows applicability of a whole law' yields the change that would close it, while the change on its own recovers none of the reading behind it.resolutionstringstringWhat has to change before this article can be translated in full. operation: the operation does not exist and must be built (statutory rounding, extracting the year from a date). Adding one reaches further than the engine: schema, model, evaluation, the BDD grammar and the frontend all carry it, so the value names the thing to be built rather than the place it happens to run. model: the operation set is not the problem; the format has no shape for this construct (quantification over persons, a rule about a set rather than a value, a legal fiction). Nothing else belongs here: a norm whose content is filled by another regulation is an open_term, and a value produced by another law is an input with a source.resolved_bystringstringThe change that would resolve it, named concretely enough to become work (e.g. 'Een YEAR-bewerking die het jaardeel van een datum oplevert', or the shape the format lacks). Required, and it is the field that keeps resolution: model from becoming the bin everything awkward falls into: a marking that cannot say what would fix it has not been diagnosed. Grouping markings by this field is how the backlog is read off the corpus.targetarray of stringarray of stringThe values in this article that cannot be produced because of this marking: outputs, inputs or parameters by name. Every name listed here must be absent from the article's actions, which the enrichment checks hold the file to: computing a value you declared blocked is a contradiction, and it is caught when the file is written rather than when someone is waiting on an answer. An empty list is a statement and not an omission: it says the marking is a flag on an article that is otherwise worked out, and that only the explanation is incomplete. It does not change execution. What the engine does with a marked article is decided by accepted and the untranslatable modes of RFC-012, which do not read this field; whether a marking should ever block only the values it names is an open question in RFC-031.legal_text_excerptstringstringThe words from this article's own legal text that the marking hangs on. Required: a marking that cannot quote the text it is about is about something else.acceptedbooleanbooleanWhether a human has reviewed and acknowledged this gap. Accepted markings are allowed in error mode. Defaults to false.

declares

machine_readable.declares[]

Document properties this article establishes. A citation title, a commencement date or a scope in time is not a calculation, and it is not nothing either: it fixes a value the rest of the corpus and every trace depend on. Article 51 of the Awir says what that law is called, and a trace that names the law is quoting that article. Recording it here makes the article accounted for and lets a check hold the document header against the provision that decides it.

FieldTypeDescriptionpropertystringstringThe top-level document property this article fixes.valueanyanyThe value the article gives it, verbatim from the text.applies_fromstringstringWhere the article limits the property in time beyond the value itself, e.g. Awir article 50, which commences on 1 September 2005 but applies to berekeningsjaren from 1 January 2006.

applies_to

hooks[].applies_to

Which decisions of other articles this hook fires on. legal_character is required; adding decision_type or stage narrows it further.

FieldTypeDescriptionlegal_characterstringstringMatch articles that produce this legal character.decision_typestringstringOptionally narrow to a specific decision type.stagestringstringLifecycle stage at which this hook fires (e.g., BESLUIT, BEKENDMAKING). Defaults to BESLUIT.

execution

The executable core. Values come in as parameters andinput, actions compute, and outputdeclares what the article yields.

FieldTypeDescriptionproducesobjectobjectWhat executing this article yields in legal terms: its legal character, the kind of decision it is, and the procedure that governs it. Not merely annotation: legal_character and decision_type select which hooks fire, and legal_character with procedure_id selects the Awb procedure, so an article's outputs and how it runs both depend on what is declared here.The produces annotationparametersarray of Parameter fieldarray of Parameter fieldValues the caller passes in, such as a bsn or a peildatum.inputarray of Input fieldarray of Input fieldValues this article reads from elsewhere: another law's output, or a fact from a register. Each declares a source.outputarray of Output fieldarray of Output fieldValues this article yields. Each is callable from another law by name.actionsarray of Actionarray of ActionThe steps that compute the outputs, each assigning one output either a literal or the result of an operation.Operations

produces

execution.produces

What executing this article yields in legal terms: its legal character, the kind of decision it is, and the procedure that governs it. Not merely annotation: legal_character and decision_type select which hooks fire, and legal_character with procedure_id selects the Awb procedure, so an article's outputs and how it runs both depend on what is declared here.

FieldTypeDescriptionlegal_characterstringstringLegal character of the output. BESCHIKKING: a besluit not of general scope (Awb art. 1:3 lid 2). RECHTSPOSITIE: a legal position of a person that arises by operation of law, without a besluit and without an aanvraag (voting rights, majority, nationality).decision_typestringstringThe kind of decision this output is, within its legal character. GEEN_BESLUIT is the value for an article that establishes a fact rather than deciding anything.procedure_idstringstringSelects a specific AWB procedure variant. When absent, the default procedure for the legal_character is used.

Action

One assignment to one output. It either states a literal valueor computes one with an operation, never both.

FieldTypeDescriptionoutputstringstringName of the output field this action computes.valueOperation valueOperation valueA literal value for this output, used where the law states an amount or a term outright. When the action also carries an operation, that operation wins and this field is read as one of its operands.operationOperation typeOperation typeThe operation computing this action's value. When the action also carries value, this wins and that field is read as an operand.valuesarray of Operation valuearray of Operation valueOperands for the operation.precisionintegerintegerDecimal places for an inline rounding operation (ROUND/CEIL/FLOOR; RFC-024), in the value's own unit. 0 = whole units; negative rounds to tens/hundreds.resolveobjectobjectLook up the value in whichever regulation implements it. Accepted by the schema, but the Rust law-model has no field for it and drops it on load; no law in the corpus uses it.legal_basisLegal basisLegal basisThe provision this action rests on. Accepted by the schema, but the Rust law-model has no field for it and drops it on load, so it does not reach a trace today.

resolve

action.resolve

Look up the value in whichever regulation implements it. Accepted by the schema, but the Rust law-model has no field for it and drops it on load; no law in the corpus uses it.

FieldTypeDescriptiontypestringstringRegulatory layer to search for implementation.outputstringstringOutput field to retrieve.matchobjectobjectMatching criteria for selecting the right implementation.

Fields

Parameters, inputs and outputs share one shape and add to it. Note the singular spelling: the keys are input and output, not their plurals.

Common to every field

Every parameter, input and output carries these. The three kinds below repeat them, so each section is the complete list for that kind.

FieldTypeDescriptionnamestringstringField name, referenced elsewhere as $name. This is the name another law asks for when it reads this value through source, so renaming an output is a change other laws can see.descriptionstringstringHuman-readable description.typestringstringValue type. What an amount is counted in is declared separately, in type_spec.unit; units are opt-in per law, and an un-annotated value has unit unknown and is never checked (RFC-023).nullablebooleanbooleanWhether null (absence: the register or the law says there is none) is a legitimate value of this field. Defaults to false: a non-nullable input may never receive null from a data source, another law or a caller, a non-nullable output may never evaluate to null, and a non-nullable parameter may never be passed null. On a required parameter the flag means the same at the top level and across laws: a nullable one is run with the null and decides on it, a non-nullable one is a caller error at the top level and skips the call across laws. Unknown (a value nobody has) is not governed by this flag. RFC-036.Absent and Unknown Valuestype_specobjectobjectAdditional type specifications for numeric and temporal values.unit: eurocentunit: ratio precision: 4Type SpecificationstemporalobjectobjectHow the value relates to time: whether it is measured at a moment or over a period, and which date it is anchored to (RFC-001). Declared in the schema but not yet read by the engine, and unused in the corpus.legal_basisLegal basisLegal basisThe provision this field rests on. On an output it is the article granting the entitlement; on an input, the provision that makes the value relevant.

type_spec

field.type_spec

Additional type specifications for numeric and temporal values.

FieldTypeDescriptionunitstringstringUnit of measurement for the value (RFC-023). A label, never a computational constraint: tagging a value never changes it. ratio (0-1) and percentage (0-100) are distinct labels; any division by 100 is an explicit value operation, never implied by the label.precisionintegerintegerNumber of decimal places for numeric values. Parsed as metadata and not yet enforced by the engine.minnumbernumberMinimum allowed value. Parsed as metadata and not yet enforced by the engine.maxnumbernumberMaximum allowed value. Parsed as metadata and not yet enforced by the engine.

temporal

field.temporal

How the value relates to time: whether it is measured at a moment or over a period, and which date it is anchored to (RFC-001). Declared in the schema but not yet read by the engine, and unused in the corpus.

FieldTypeDescriptiontypestringstringWhether the value represents a period or point in time.period_typestringstringGranularity of the period (for period type).referencestring or Variable referencestring or Variable referenceReference date for point-in-time values.

Parameter

A value the caller passes in, rather than one the law looks up or derives. Adds required, which defaults to true; an omitted required: false parameter resolves to an unknown value rather than an error (RFC-036).

FieldTypeDescriptionnamestringstringField name, referenced elsewhere as $name. This is the name another law asks for when it reads this value through source, so renaming an output is a change other laws can see.descriptionstringstringHuman-readable description.typestringstringValue type. What an amount is counted in is declared separately, in type_spec.unit; units are opt-in per law, and an un-annotated value has unit unknown and is never checked (RFC-023).nullablebooleanbooleanWhether null (absence: the register or the law says there is none) is a legitimate value of this field. Defaults to false: a non-nullable input may never receive null from a data source, another law or a caller, a non-nullable output may never evaluate to null, and a non-nullable parameter may never be passed null. On a required parameter the flag means the same at the top level and across laws: a nullable one is run with the null and decides on it, a non-nullable one is a caller error at the top level and skips the call across laws. Unknown (a value nobody has) is not governed by this flag. RFC-036.Absent and Unknown Valuestype_specobjectobjectAdditional type specifications for numeric and temporal values.unit: eurocentunit: ratio precision: 4Type SpecificationstemporalobjectobjectHow the value relates to time: whether it is measured at a moment or over a period, and which date it is anchored to (RFC-001). Declared in the schema but not yet read by the engine, and unused in the corpus.legal_basisLegal basisLegal basisThe provision this field rests on. On an output it is the article granting the entitlement; on an input, the provision that makes the value relevant.requiredbooleanbooleanWhether the caller must pass this parameter. Defaults to true: an omitted required parameter is an error. A parameter declared required: false that the caller omits resolves to an unknown value that names the parameter (RFC-036), so a law can declare application-form fields another law never passes.

Input

A value the law looks up elsewhere: another law's output, or a fact from a register. Adds source, which is required and says where the value comes from (RFC-007).

FieldTypeDescriptionnamestringstringField name, referenced elsewhere as $name. This is the name another law asks for when it reads this value through source, so renaming an output is a change other laws can see.descriptionstringstringHuman-readable description.typestringstringValue type. What an amount is counted in is declared separately, in type_spec.unit; units are opt-in per law, and an un-annotated value has unit unknown and is never checked (RFC-023).nullablebooleanbooleanWhether null (absence: the register or the law says there is none) is a legitimate value of this field. Defaults to false: a non-nullable input may never receive null from a data source, another law or a caller, a non-nullable output may never evaluate to null, and a non-nullable parameter may never be passed null. On a required parameter the flag means the same at the top level and across laws: a nullable one is run with the null and decides on it, a non-nullable one is a caller error at the top level and skips the call across laws. Unknown (a value nobody has) is not governed by this flag. RFC-036.Absent and Unknown Valuestype_specobjectobjectAdditional type specifications for numeric and temporal values.unit: eurocentunit: ratio precision: 4Type SpecificationstemporalobjectobjectHow the value relates to time: whether it is measured at a moment or over a period, and which date it is anchored to (RFC-001). Declared in the schema but not yet read by the engine, and unused in the corpus.legal_basisLegal basisLegal basisThe provision this field rests on. On an output it is the article granting the entitlement; on an input, the provision that makes the value relevant.sourceobjectobjectReference to where this input comes from.regulation: wet_op_de_zorgtoeslag output: standaardpremie parameters: bsn: $bsnCross-Law References

source

input[].source

Reference to where this input comes from.

FieldTypeDescriptionregulationstringstringName of external law/regulation. Omit for external data sources that must be resolved outside the YAML.outputstringstringOutput name to retrieve from the source.parametersobjectobjectParameters passed when calling the source regulation. A map from the parameter name the source expects to the value passed for it, usually a $-reference to a value in scope, as in bsn: $bsn.descriptionstringstringHuman-readable description or legal reference for this data source.endpointstringstringEndpoint to call on the delegated regulation.

Output

A value the article yields. Adds nothing to the common fields, and that is the point: every output is callable from another law through source, which asks for it by name (RFC-007). Callable is not the same as presentable, and what a portal offers a citizen is derived from produces, not from a flag on the output (RFC-038).

FieldTypeDescriptionnamestringstringField name, referenced elsewhere as $name. This is the name another law asks for when it reads this value through source, so renaming an output is a change other laws can see.descriptionstringstringHuman-readable description.typestringstringValue type. What an amount is counted in is declared separately, in type_spec.unit; units are opt-in per law, and an un-annotated value has unit unknown and is never checked (RFC-023).nullablebooleanbooleanWhether null (absence: the register or the law says there is none) is a legitimate value of this field. Defaults to false: a non-nullable input may never receive null from a data source, another law or a caller, a non-nullable output may never evaluate to null, and a non-nullable parameter may never be passed null. On a required parameter the flag means the same at the top level and across laws: a nullable one is run with the null and decides on it, a non-nullable one is a caller error at the top level and skips the call across laws. Unknown (a value nobody has) is not governed by this flag. RFC-036.Absent and Unknown Valuestype_specobjectobjectAdditional type specifications for numeric and temporal values.unit: eurocentunit: ratio precision: 4Type SpecificationstemporalobjectobjectHow the value relates to time: whether it is measured at a moment or over a period, and which date it is anchored to (RFC-001). Declared in the schema but not yet read by the engine, and unused in the corpus.legal_basisLegal basisLegal basisThe provision this field rests on. On an output it is the article granting the entitlement; on an input, the provision that makes the value relevant.

A citation back to the provision a value or a step rests on. Any field, any action and any operation may carry one; it is what lets an execution trace name the article behind each number rather than only the number.

FieldTypeDescriptionlawstringstringName of the law.bwb_idstringstringBWB identification number. Must match ^BWBR[0-9]{7}$. articlestringstringArticle number.paragraphstringstringParagraph/lid number.sentencestringstringSentence number for fine-grained reference.urlstringstringURL to wetten.overheid.nl.juriconnectstringstringJuriconnect BWB 1.3 reference. Optionally pinned to a date with the z=/g= parameters; most references in the corpus carry them, and the pattern does not require them. Must match ^jci1\.3:c:BWBR[0-9]{7}(&[a-zA-Z_]+=.+)*$. explanationstringstringDutch explanation of how this element relates to the law text.

Operations

An action either states a literal value or computes one with anoperation. There are 16 forms. Each is a closed object: the operation key picks the form and the schema rejects any other combination of keys, so a malformed action fails validation rather than executing as something unintended.

Operand value

Wherever an operation below takes a value, three things may stand there:

  • A variable reference. A name beginning with $, resolved from the parameters, inputs, outputs and definitions in scope, such as $inkomen.
  • A literal. A number, a boolean, null, or a string that does not begin with $.
  • Another operation. Any of the forms below, nested. This is what lets one action express a whole calculation rather than a single step.

Arithmetic

Arithmetic operations that compute numeric values.

operation: DIVIDE values: - $inkomen - $maanden_per_jaaroperation: MIN values: - operation: ADD values: - $woonperiodes - $werkzame_verzekerde_jaren - $jaren_voor_volledig_pensioenFieldTypeDescriptionvaluesarray of Operation valuearray of Operation valueOperands for the operation.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Rounding

Rounding operations (RFC-024). Round the single operand to precision decimal places, in the value's own unit (RFC-023). Rounding is never implicit - a law that rounds must say so here. ROUND is half-up (rekenkundig, the Hoge Raad default); CEIL rounds up (naar boven); FLOOR rounds down (naar beneden / afkapping).

operation: ROUND precision: 0 value: operation: DIVIDE values: - $pensioen_uitkering_bruto - $maanden_per_jaaroperation: FLOOR precision: 1 value: $alcoholpercentageFieldTypeDescriptionvalueOperation valueOperation valueOperand to round.precisionintegerintegerNumber of decimal places to round to, in the value's own unit. 0 = whole units; 2 = two decimals; a negative value rounds to tens/hundreds (e.g. -2 rounds a eurocent value to whole euros).legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Rounding and Precision

Logical

Logical operations that combine boolean conditions.

operation: OR conditions: - operation: NOT value: operation: EQUALS subject: $type_bedrijf value: $type_horecabedrijf - operation: GREATER_THAN_OR_EQUAL subject: $vloeroppervlakte value: $minimale_vloeroppervlakte_horecaFieldTypeDescriptionconditionsarray of Operation valuearray of Operation valueConditions to combine - each item can be an operation, variable reference, or boolean literal.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Comparison

Comparison operations that compare values. Operands may be numbers or ISO 8601 dates (YYYY-MM-DD); when both operands are dates they are compared chronologically (RFC-021). value is required: all five of these compare two operands, and a comparison with only a subject compares against nothing. It was optional, and the Rust model's untagged fallback turned such an operation into a literal object without an error, a warning or a line in the trace, so the execution carried on and produced an answer that looked complete.

operation: GREATER_THAN_OR_EQUAL subject: $leeftijd value: 18FieldTypeDescriptionsubjectOperation valueOperation valueThe value being compared, on the left of the comparison.valueOperation valueOperation valueThe value compared against, on the right of the comparison.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

NOT

Logical NOT - negates a boolean value.

operation: NOT value: operation: EQUALS subject: $type_bedrijf value: $type_horecabedrijfFieldTypeDescriptionvalueOperation valueOperation valueValue to negate.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

IF

Conditional operation with multiple cases evaluated in order.

operation: IF cases: - when: operation: EQUALS subject: $type_beplanting value: heg_of_heester then: 50 default: 0FieldTypeDescriptioncasesarray of objectarray of objectCases evaluated in order; the first whose when holds decides the value. Order is significant, so a narrower case belongs before a broader one.defaultOperation valueOperation valueValue when no case matches. Without it, an IF whose cases all fail evaluates to null (absence, RFC-036), so the validator refuses a defaultless IF on an output that is not nullable. A case whose condition is unknown takes neither its branch nor the default.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

cases

IF.cases[]

Cases evaluated in order; the first whose when holds decides the value. Order is significant, so a narrower case belongs before a broader one.

FieldTypeDescriptionwhenOperation valueOperation valueCondition to evaluate.thenOperation valueOperation valueValue if condition is true.

IN

Membership test - checks if subject is in a list.

operation: IN subject: $partnerschap_type value: $geldige_partnertypenFieldTypeDescriptionsubjectOperation valueOperation valueValue to check.valueOperation valueOperation valueA single value or a reference to a list to test against. Use values instead to write the list inline.valuesarray of Operation valuearray of Operation valueInline list to check against.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Collections

LIST

Construct an array from items.

operation: LIST items: - $huurFieldTypeDescriptionitemsarray of Operation valuearray of Operation valueItems in the list.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Collections

FOREACH

Iterate over a collection, evaluating an expression per element (RFC-016).

operation: FOREACH collection: $medebewoners as: medebewoner body: 1 combine: ADDFieldTypeDescriptioncollectionOperation valueOperation valueExpression evaluating to the array to iterate over. A non-array iterates as a single element; null is an empty collection.asstringstringName of the local variable bound to the current element. Defaults to 'item'. Must match ^[a-z_][a-z0-9_]*$. filterOperation valueOperation valueEvaluated per element in the child scope; elements for which it is false are skipped.bodyOperation valueOperation valueEvaluated once per surviving element, in the child scope where 'as' is bound.combinestringstringAggregation over the collected results. Omitted, the results are returned as an array.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Collections

AGE

Calculate age in complete years between two dates.

operation: AGE date_of_birth: $geboortedatum reference_date: $peildatumFieldTypeDescriptiondate_of_birthOperation valueOperation valueDate of birth.reference_dateOperation valueOperation valueReference date to calculate age at.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Dates

DATE_ADD

Add years, months, weeks, and/or days to a date. Applied coarsest-to-finest: years → months → weeks → days. Month/year additions use the Dutch legal 'corresponding numbered day' rule: the day is clamped to the last day of the target month (e.g., Jan 31 + 1 month = Feb 28).

operation: DATE_ADD date: $bekendmaking_datum days: 1FieldTypeDescriptiondateOperation valueOperation valueBase date.yearsOperation valueOperation valueNumber of years to add (clamped to last day of target month).monthsOperation valueOperation valueNumber of months to add (clamped to last day of target month).weeksOperation valueOperation valueNumber of weeks to add.daysOperation valueOperation valueNumber of days to add.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Dates

DATE

Construct a date from year, month, day components.

operation: DATE year: $jaar month: 1 day: 1FieldTypeDescriptionyearOperation valueOperation valueYear.monthOperation valueOperation valueMonth (1-12).dayOperation valueOperation valueDay (1-31).legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Dates

DAY_OF_WEEK

Get the day of the week (0=Monday, 6=Sunday).

operation: DAY_OF_WEEK date: $activiteitsdatumFieldTypeDescriptiondateOperation valueOperation valueDate to check.legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Dates

DATE_DIFF

Signed difference between two dates, expressed in a chosen unit. Positive when 'to' is on or after 'from'. Months and years count complete calendar units (RFC-021).

operation: DATE_DIFF from: $datum_aanmaning_opheffing to: $datum_ontstaan_schade in: daysFieldTypeDescriptionfromOperation valueOperation valueStart date (ISO 8601 YYYY-MM-DD).toOperation valueOperation valueEnd date (ISO 8601 YYYY-MM-DD).instring or Variable referencestring or Variable referenceUnit the difference is expressed in: 'days', 'months', or 'years' (or a variable resolving to one of these).legal_basisLegal basisLegal basisThe article this particular step rests on. Set it where one action combines rules from several provisions and the operands come from different articles, so a trace can name the provision behind each step.

Dates

DATE_PART

Read one calendar component out of a date. The inverse of DATE, so 'in' ranges over exactly the components DATE takes. Returns an integer: the year number, the month number (1-12) or the day of the month (1-31). A month number is only meaningful within one year — comparing two month numbers across a year boundary is almost always wrong. For the weekday, use DAY_OF_WEEK.

FieldTypeDescriptiondateOperation valueOperation valueDate to read a component from (ISO 8601 YYYY-MM-DD)instringstringCalendar component to read: 'year', 'month' or 'day' (singular, because the operation selects a component rather than counting units the way DATE_DIFF does)legal_basisLegal basisLegal basis

START_OF

Truncate a date down to the start of the calendar unit it falls in: 1 January of its year, or the first day of its month. Returns a date (ISO 8601 YYYY-MM-DD). For 'the first day of the month following', truncate first and add afterwards — DATE_ADD over START_OF — so the day-clamping of DATE_ADD never comes into play and the first of the month yields the next first.

FieldTypeDescriptiondateOperation valueOperation valueDate to truncate (ISO 8601 YYYY-MM-DD)instringstringCalendar unit to truncate to: 'year' or 'month'. 'day' is the identity and 'week' would need a convention no legal text imposes.legal_basisLegal basisLegal basis

Vocabulary

The closed value sets a law picks from. These are the terms the rest of the documentation uses, so each one links to where it is explained.

Regulatory layer

regulatory_layer

Type of legal instrument (regelgevingslaag). It fixes which identifier the file must carry, and it ranks candidates when several regulations implement the same open term. Which layer may implement a term is set by that term's delegation_type, not by this field alone.

Glossary: Legal Hierarchy
machine_readable.execution.produces.legal_character

Legal character of the output. BESCHIKKING: a besluit not of general scope (Awb art. 1:3 lid 2). RECHTSPOSITIE: a legal position of a person that arises by operation of law, without a besluit and without an aanvraag (voting rights, majority, nationality).

Glossary: Legal Character

Decision type

machine_readable.execution.produces.decision_type

The kind of decision this output is, within its legal character. GEEN_BESLUIT is the value for an article that establishes a fact rather than deciding anything.

Glossary: Decision Type

Value types and units

type / type_spec.unit

Value type. What an amount is counted in is declared separately, in type_spec.unit; units are opt-in per law, and an un-annotated value has unit unknown and is never checked (RFC-023).

Units

type_spec.unit

Unit of measurement for the value (RFC-023). A label, never a computational constraint: tagging a value never changes it. ratio (0-1) and percentage (0-100) are distinct labels; any division by 100 is an explicit value operation, never implied by the label.

About this reference

The sections above are generated from the released schema at build time, so this page cannot describe a schema other than the released one. That guard is about the version, not the wording: a description that has fallen behind what the engine does is still a description this page will render faithfully. RFC-040 sets out why the schema carries its own documentation and how the generated page is held to it.

The version history is not generated: it records what a version introduced and why, which is a judgement no schema can state about itself.

The schema is JSON Schema draft-07. It uses none of the constructs that changed in later drafts, so it would migrate to 2020-12 mechanically; the one keyword that would be worth having is deprecated, which arrived in 2019-09. That is a decision for its own RFC, since the schema is a contract other engines read (RFC-013) and draft-07 is the most widely implemented dialect.

One consequence of draft-07 shows up here. Where a field is a $ref to another definition, a description written next to that $ref is formally ignored: draft-07 says a $ref replaces its siblings. This page reads those descriptions anyway, falling back to the target’s, so nothing is lost in what you see. An editor that follows the specification strictly will not show them.

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