An objection (bezwaar) is a submission, like the application. The decision on it is a beschikking. Awb 7:11 plays the part that art. 13a plays for the application, and holds the procedure in rulework. The cell records and decides an objection like any other submission, and knows no Awb name.
In a procedure, the article that decides gets the earlier steps as context: the submission and the decision it refers to, with their fields and findings. When 7:11 calls that decision anew (source.article: $bestreden_besluit), the call uses the decision’s own fields and findings. New findings come in from the top, and an article in the call must ask for them.
produces lists a BEZWAAR that requests the decision of 7:11 and holds bestreden_besluit, and a BESCHIKKING with the outputs bezwaar_ontvankelijk, heroverweging_geeft_aanleiding, bestreden_besluit_herroepen and nieuw_besluit (RFC-047).nieuw_besluit, and the cell records it in the same append. The revoked one stays in the chronicle as it was. A reduction reads the decisions under 7:11 and leaves out what one of them revoked.BEZWAAR as a kind of submission. Schema v0.8.4 adds what 7:11 needs to call an article named in data: source.article, source.parameters_from, the field type decision and derived on the decision item.The contested decision reaches 7:11 as a decision value:
| Key | What it holds |
|---|---|
grondslag | The article the decision was taken under. |
taken_on | The article of the submission the decision was taken on. The cell derives it from the chronolexogram the decision refers to, and stores nothing new. |
fields | The parameters the article declares. |
findings | What the deciding authority found for the case: the open terms of the article with decided_per_case_by, under their ids. For art. 13a: specifieke_aard_beroep_ouder, verlof_valt_buiten_schoolvakanties and verlof_al_verleend_in_schooljaar. A term that a regulation or the cell filled is left out: the call anew asks it again of the regulation in force that day, or of the cell. |
outputs | Only the outputs of the decision item of the article. |
taken_on tells a decision taken on objection apart. A decision on an application under art. 13a has taken_on: leerplichtwet_1969#13a. The decision on an objection and the new decision it takes both have taken_on: algemene_wet_bestuursrecht#7:11, although the new decision’s grondslag is art. 13a. A value that an article gives through source.article, such as the heroverweging, has no taken_on: the engine builds it from a call, not from a submission.
Schema v0.8.4 describes taken_on as an optional key of a value built from a recorded decision. The engine narrows that for a parameter. A decision given as a parameter at the top of an execution, as bestreden_besluit is in a scenario, holds all five keys and no other, and its grondslag and taken_on are article references. Before the article runs, the engine refuses a value other than null or unknown that is no object, lacks a key, holds another or has no article reference in one of those two. The error names the parameter and the key. Without that rule a hand-written value without taken_on would pass wherever 7:11 does not read the key, and fail without naming the parameter where it does. A taken_on of null would silently make an objection against a decision on objection admissible. An input filled by source.article keeps its shape without taken_on, and one article may pass it to another as a parameter. A taken_on that such a parameter does hold must be an article reference too, at any depth.
7:11 itself uses these names:
| Name | Kind | What it is |
|---|---|---|
bestreden_besluit | parameter, type decision | The contested decision (lid 1 and 2, and Awb 6:5 lid 1 onder c). The objection holds it. |
bezwaarschrift_tijdig_ingediend | parameter | What 6:9 gives on the objection. |
heroverweging | input, type decision, nullable | source.article: $bestreden_besluit: the contested decision called anew, with its own fields and findings. The execution passes what the deciding authority finds anew separately from the parameters (decide(..., findings, ...)); a finding that no article in the call asks, or of the wrong type, is an error that names it. |
bezwaar_ontvankelijk | output | On time, and the contested decision was not taken on an objection: NOT EQUALS($bestreden_besluit.taken_on, "algemene_wet_bestuursrecht#7:11") (Awb 7:1 lid 1 onder a). That covers the decision on an objection and the new decision it took. |
heroverweging_geeft_aanleiding | output, nullable | IF bezwaar_ontvankelijk THEN NOT EQUALS($heroverweging.outputs, $bestreden_besluit.outputs) ELSE null. Every output of the decision item counts, not only the grant: when verlofdagen changes and art. 13a refuses again, the refusal is revoked and another refusal takes its place. |
bestreden_besluit_herroepen | output | Whether the heroverweging gives cause. |
nieuw_besluit | output, type decision, nullable | IF bestreden_besluit_herroepen THEN $heroverweging ELSE null (lid 2, “voor zover nodig een nieuw besluit”). |
The engine reads an input only when an action needs it (RFC-043), and IF reads only the branch it takes. So for an objection that is not admissible the heroverweging does not run, and heroverweging_geeft_aanleiding stays null: there is no heroverweging (lid 1). A test in packages/cel/tests/vakantieverlof.rs checks that through the trace.
Only what the decision item names under outputs counts as the outcome. Data it lists under derived, such as the end of a validity, is recorded with the decision but plays no part in “aanleiding”.
The cell has one record_submission and one decide. It follows six rules. None of them names an Awb article.
| Rule | What the cell does | Why | Example |
|---|---|---|---|
| A reference fills the decision field | record_submission with refers_to: D fills the field of type decision with D. Fields that D already holds are taken from D. | Earlier steps of a procedure are context. | The objection gets bezwaartermijn_einddatum from the decision. |
| Findings come in separately | decide takes the authority’s findings apart from other input. A finding that no article asks for is an error. | A misspelled finding must fail, not vanish. | The head’s new judgement on the profession. |
| A decision output becomes a decision | Each output of type decision that is not null is recorded as its own chronolexogram, with its own period. | Revoking and replacing land together or not at all. | nieuw_besluit from 7:11. |
| A decision is replaced once | A second replacement of the same decision is refused. | Two live replacements would contradict each other. This is our own guard, not an Awb rule. | A second objection against the same refusal. |
| The contested decision does not count against itself | During the reconsideration, reductions read the chronicle without the contested decision. | That decision is the one under review. | Leave granted earlier in the school year. |
| Answers are taken anew | The cell answers the engine for the whole decision, on its day, also in the article called anew; it runs its reduction there on its chronicle. Stage dates are those of the day as well. | The reconsideration looks at the facts of that day. | verlof_al_verleend_in_schooljaar on the day of the decision on the objection. |
The chronolexogram keeps the contested decision by its id, and the head’s findings among the decision’s fields. Which findings the decision used is not stored. A finding that a regulation set aside was not used, even where the regulation gives the same value. The engine reports who filled each term: it lists under open_terms each open term that a finding, a regulation or the cell filled. An entry names the article that declares the term and, for a regulation, the article that implements it; for the cell, the reduction with its version and how far it read the chronicle (RFC-048, §3). The cell gets that report by replaying the decision (Cell::findings, Cell::explain). The replay runs on the decision’s own day, under the law in force then, with the decision’s fields. The cell answers from the chronicle as it stood before the decision, so it gives the same lexostatus as then.
A replay whose outcome differs from the chronolexogram is an error. A cell is always opened with its reductions, because a replay without them would report a reduction’s answer as a finding of the head (RFC-048, §3).
A replay rests on one assumption: every source a decision reads can say what it knew on a given day. The chronicle and the law in force on a day can. A source that cannot, such as an external register without history, would need a facade. The facade records every value fetched with its moment, and a replay reads the recorded value. No such source is in the vakantieverlof case, and the facade is not built.
The school’s reduction reads the decisions under 7:11 as a second input and leaves out the decisions they revoked.
| Case | Art. 13a anew | Result |
|---|---|---|
| Second leave in a school year | Refused again | Ongegrond, the decision stands |
| Profession judged anew on the employer’s statement | Granted | Gegrond, revoked, leave granted |
| Refused anew on another ground | Refused again | Ongegrond: the outcomes do not name the ground |
| Late objection | Not run | Not admissible, the decision stands |
| Objection against the decision on an objection | Not run | Not admissible (Awb 7:1 lid 1 onder a) |
| Objection against the new decision taken on objection | Not run | Not admissible: its taken_on is 7:11 |
| Second objection against a decision already replaced | Would replace it again | The cell refuses the decision |
Not modeled: 6:6 and 6:11, 6:9 lid 2, the hearing (7:2), 7:10 lid 2 to 4, 7:12 lid 2 to 4.
The first version of this RFC put the procedure of Awb 7:11 in the cell (packages/cel/src/objection.rs). That procedure is now in rulework. The table below compares the first version with now. The cell still does two things. During the call, it answers the open term its reduction fills, from the chronicle without the contested decision, where the article called anew reads it (row “Reduction in the nested call”). After the call, it refuses a decision that would replace the contested decision a second time (row “Objection against a revoked decision”).
| First version | Now | |
|---|---|---|
| Recording | record_objection next to record_submission | One record_submission, with refers_to. |
| Deciding | decide_on_objection next to decide | One decide. It runs the deciding article and records what that article produces. |
| Admissibility first | Order in Rust | 7:11 itself: the heroverweging is only read when bezwaar_ontvankelijk holds. |
| Heroverweging | The cell reruns the contested article | 7:11 calls the contested decision anew, with its own fields and findings and what is found anew. |
| ”Aanleiding” | The cell compares outputs | 7:11 compares the outputs of the call with those of the contested decision. |
| Revoke and replace | The cell appends two chronolexograms | 7:11 gives the new decision as an output; the cell records both. |
| Awb names in the cell | bestreden_besluit_herroepen | None. The reduction reads the revocation by that name, in YAML. |
| Reduction in the nested call | The cell ran art. 13a anew with its reductions bound | The reduction names an open term of art. 13a with implements (RFC-048, schema v0.8.5). The engine asks the cell for it during the call, and the trace of the decision on the objection (Cell::explain) shows the answer as one node; the cell’s reasoning comes from Cell::explain_answer. Before 2026-10-16 the cell refreshed the fields of the decision value it passed; from 2026-10-16 to 2026-10-17 the engine ran the reduction itself. |
| A decision taken on objection | Refused by the cell | 7:11 reads taken_on of the contested decision, so it recognizes both the decision on an objection and the new decision it took. |
| Objection against a revoked decision | Refused by the cell | It is recorded and reconsidered. When the heroverweging would replace the decision again, the cell refuses the decision. This is our own guard: under the Awb a second objection has no object left (usually no interest), and art. 6:19 carries a pending objection over to the replacing decision. Open: 7:11 itself declares it not admissible, once the decision value says that the decision was replaced. |
| A finding anew on an objection that is not admissible | Not possible | There is no heroverweging, so no article asks the finding, and the engine refuses it. |
The deciding authority may give a finding for an article that the decision calls anew. That finding is recorded among the fields of the decision on the objection. When that decision is called anew in turn, it does not pass the finding on: the article it calls anew takes the finding of the contested decision again. Beroep is not modeled, so nothing calls a decision on an objection anew yet.
The call has two more limits. A decision value holds a decision among its fields as an id. A call that merges those fields therefore passes an id where the article expects a decision. The call also passes only the parameters the article itself declares and its findings per case. A value that only a hook on the decision or a stage of its procedure asks for does not reach it.
$bestreden_besluit.findings.bezwaartermijn_einddatum. For a decision taken on objection that is the period for appeal (Awb 7:1 lid 1 onder a); the name does not say so.decides_on, PR #1689). That adds a key; requests already does it.record_objection, decide_on_objection and one Awb name in the cell.BEZWAAR in produces.submission.kind, as a list item’s type and in applies_to.submission.source.article, source.parameters_from, the field type decision and derived on the decision item of produces. The engine calls the article (resolve_article_call in packages/engine/src/service.rs), checks a fixed target at load (T5 in typecheck.rs), calls a decision value anew and takes findings apart from the parameters (evaluate_law_with_findings), reports per open term who filled it (open_terms), and compares lists and records strictly in EQUALS: an integer against a decimal of the same value is an error.bezwaar.feature, which passes the contested decision as a JSON object and what is found anew as findings; the school’s reduction reads the decisions under 7:11.packages/cel: record_submission with refers_to, decide with findings and decision outputs, rows with id. The chronicle stores a decimal without loss (#1732), so a decision value read back and called anew compares equal to its stored outputs.A lexostatus addressed by the term that asks for it. A reduction answers one open term, named by the law and article that declare it (implements on art. 13a, verlof_al_verleend_in_schooljaar). That suits one school answering one law. It does not scale to a cell that many laws ask the same thing. The Kamer van Koophandel would give the type of registration of an organization as one lexostatus, and every law that reads it declares its own open term, so the KvK cell would need an implements entry per asking law. Another address is open: a lexostatus the cell names itself, which an open term in the law points to. That address must not make the law name the cell; the law defines the interface, and the cell decides how it answers (2026-10-17).
A second answerer. For the school holidays the school answers where it is established, from its own executogram (RFC-051). A DUO cell with the register of institutions (RIO) could answer that instead. That needs more than one answerer in an execution and a rule for which one answers a term. Not built (2026-10-18).
An exploration into transparent, executable legislation, and one of the three projects in the starting selection of the Nederlandse Digitale Dienst.
GitHub repository
How it works
Stay informed
Roadmap (Dutch)
Documentation
Research
Nederlandse Digitale Dienst
Ministry of Economic Affairs and Climate Policy