RFC-050: The Objection Is a Second Submission

DraftPartially implemented
Depends on

Decision

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.

  1. Awb 7:11 establishes the objection and decides on it. 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).
  2. The Awb hooks onto every objection. 6:5 asks what the bezwaarschrift contains. 6:9 makes the receipt the moment that counts and says whether it came in on time. 7:10 gives the last day to decide.
  3. The heroverweging is the contested decision taken anew. 7:11 calls the contested decision anew, on the day of the decision on the objection (ex nunc). The call runs the decision’s article with the decision’s own fields and findings, plus what the deciding authority finds anew. It gives cause when an outcome of that article’s decision item comes out different.
  4. A revoked decision stays. 7:11 gives the new decision as 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.
  5. Schema v0.8.3 adds 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.

Awb 7:11 in rulework

The contested decision reaches 7:11 as a decision value:

KeyWhat it holds
grondslagThe article the decision was taken under.
taken_onThe article of the submission the decision was taken on. The cell derives it from the chronolexogram the decision refers to, and stores nothing new.
fieldsThe parameters the article declares.
findingsWhat 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.
outputsOnly 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:

NameKindWhat it is
bestreden_besluitparameter, type decisionThe contested decision (lid 1 and 2, and Awb 6:5 lid 1 onder c). The objection holds it.
bezwaarschrift_tijdig_ingediendparameterWhat 6:9 gives on the objection.
heroverweginginput, type decision, nullablesource.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_ontvankelijkoutputOn 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_aanleidingoutput, nullableIF 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_herroepenoutputWhether the heroverweging gives cause.
nieuw_besluitoutput, type decision, nullableIF 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”.

What the cell does

The cell has one record_submission and one decide. It follows six rules. None of them names an Awb article.

RuleWhat the cell doesWhyExample
A reference fills the decision fieldrecord_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 separatelydecide 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 decisionEach 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 onceA 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 itselfDuring 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 anewThe 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.

CaseArt. 13a anewResult
Second leave in a school yearRefused againOngegrond, the decision stands
Profession judged anew on the employer’s statementGrantedGegrond, revoked, leave granted
Refused anew on another groundRefused againOngegrond: the outcomes do not name the ground
Late objectionNot runNot admissible, the decision stands
Objection against the decision on an objectionNot runNot admissible (Awb 7:1 lid 1 onder a)
Objection against the new decision taken on objectionNot runNot admissible: its taken_on is 7:11
Second objection against a decision already replacedWould replace it againThe 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.

What moved out of the cell

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 versionNow
Recordingrecord_objection next to record_submissionOne record_submission, with refers_to.
Decidingdecide_on_objection next to decideOne decide. It runs the deciding article and records what that article produces.
Admissibility firstOrder in Rust7:11 itself: the heroverweging is only read when bezwaar_ontvankelijk holds.
HeroverwegingThe cell reruns the contested article7:11 calls the contested decision anew, with its own fields and findings and what is found anew.
”Aanleiding”The cell compares outputs7:11 compares the outputs of the call with those of the contested decision.
Revoke and replaceThe cell appends two chronolexograms7:11 gives the new decision as an output; the cell records both.
Awb names in the cellbestreden_besluit_herroepenNone. The reduction reads the revocation by that name, in YAML.
Reduction in the nested callThe cell ran art. 13a anew with its reductions boundThe 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 objectionRefused by the cell7: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 decisionRefused by the cellIt 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 admissibleNot possibleThere 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.

Why

Benefits

  • “Gegrond” is no choice of the cell. It is art. 13a on the facts of that day, called by 7:11.
  • The cell knows no Awb. Another article that decides on a submission referring to a decision works the same way.
  • The reduction gives the whole answer. Whether a revoked decision counts is its rule.

Tradeoffs

  • “Differs in an outcome” is our reading of “aanleiding geeft”. A heroverweging that refuses on another ground gives no cause: the outputs of art. 13a do not name the ground.
  • Which article 7:11 calls is known only when it runs. The dependency graph and the editor do not see that edge, and the type checker knows the result only as a decision value.
  • What is found anew is not in 7:11: it comes in from the top, apart from the parameters. A form for the deciding authority builds on $bestreden_besluit.findings.
  • The new decision gets a period under Awb 6:7 and 6:8, recorded as 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.

Alternatives Considered

  • Awb 6:4 establishes the objection, 7:11 links to it (decides_on, PR #1689). That adds a key; requests already does it.
  • The cell leaves revoked decisions out. Then the reduction would not give the whole answer.
  • The cell runs 7:11 (the first version of this RFC). It needed record_objection, decide_on_objection and one Awb name in the cell.

Implementation

  • Schema v0.8.3: BEZWAAR in produces.submission.kind, as a list item’s type and in applies_to.submission.
  • Schema v0.8.4: 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.
  • Corpus: Awb 6:4, 6:5, 6:9, 7:2, 7:10 to 7:12 with 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.
  • Not built: beroep, the hearing, third parties, partial revocation, and replacing a decision a second time (the cell refuses it).

Open questions

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

References

  • Awb 1:5, 6:4, 6:5, 6:7 to 6:9, 6:11, 7:1, 7:2, 7:10 to 7:12
  • RFC-043: inputs are read when an action needs them
  • RFC-047: the decision on the application
  • RFC-048: reading the chronicle back

RegelRecht

An exploration into transparent, executable legislation, and one of the three projects in the starting selection of the Nederlandse Digitale Dienst.

Links

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

Contact

regelrecht@minbzk.nl

Part of

Nederlandse Digitale Dienst
Ministry of Economic Affairs and Climate Policy