Implementation note. The core of this RFC exists: a conformance manifest (
conformance/v0.5.0/manifest.json) and a CI test (packages/engine/tests/conformance_coverage.rs) that fails when a schema operation is not covered by a conformance level. The full multi-version suite envisioned here is not complete (only the v0.5.0 manifest is present so far).
RFC-013 establishes that the schema is a specification and the engine is an implementation. Independent versioning allows third-party organizations to build their own engine. Without a shared behavioral contract, though, two engines claiming to support schema v0.5.1 might produce different outputs for identical inputs, with no way to determine which is correct.
Today, the RegelRecht engine’s correctness is verified through BDD tests (features/*.feature) using cucumber-rs. These are Rust-specific. A third-party Java or Python engine cannot run them. The tests verify integration behavior (loading regulations from the corpus, resolving cross-law references), not isolated schema-level operations. There is no artifact that says “if your engine supports schema v0.5.1, these are the exact inputs and outputs it must produce.”
Three things depend on this:
Multi-org execution (RFC-009): when Org A accepts a value from Org B’s engine, both engines must agree on what the law means. If they disagree, one has a bug. The conformance suite defines “correct.”
Reproducibility (RFC-013): an Execution Receipt records which engine version produced a result. If a different engine (or engine version) re-executes the same regulation with the same inputs, it must produce the same outputs. The conformance suite makes this testable.
Schema as execution specification: without conformance tests, the schema only validates structure (does the YAML have the right fields?). It does not specify computation (what should the engine produce?). The conformance suite encodes the intended semantics of each operation.
The engine has three layers of tests:
packages/engine/src/*.rs #[cfg(test)]): individual functions and operations in isolation. Rust-specific.features/*.feature + packages/engine/tests/bdd/): end-to-end scenarios using real regulation YAML from the corpus. Rust-specific (cucumber-rs). Cover realistic scenarios (zorgtoeslag, bijstand, erfgrensbeplanting) but do not test each operation in isolation..github/workflows/mutation-testing.yml): cargo-mutants to find untested code paths. Rust-specific.None of these can be used by a third-party engine implementation.
A conformance test suite defines the expected behavior for each schema version. The suite is a collection of JSON files with no dependency on a specific runtime or test framework. Any engine that can read JSON and YAML can run the tests.
The suite lives under conformance/ in the repository:
Each schema version has its own directory. A new schema version inherits all tests from the previous version (they must still pass) and adds tests for new features.
Each test file contains an array of test groups. Each group has a description, a regulation YAML (inline or referenced), and an array of test cases:
For tests that require multiple regulations (cross-law resolution, IoC):
The expected block can assert error conditions:
Or trace properties (for engines that support tracing):
Trace assertions are optional. An engine that does not produce traces can skip them. Output assertions are mandatory.
Tests are tagged with a conformance level. An engine declares which levels it supports per schema version.
| Level | Scope | Operations covered |
|---|---|---|
| Core | Single-article evaluation with basic operations | ADD, SUBTRACT, MULTIPLY, DIVIDE, EQUALS, GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL, AND, OR, NOT, IF, IN, LIST, MAX, MIN |
| Cross-law | Multi-regulation evaluation with source references | All Core operations + source.regulation resolution, parameter passing |
| IoC | Delegated legislation via open terms | All Cross-law operations + open_terms, implements (RFC-003) |
| Temporal | Date operations and multi-version law selection | All Core operations + AGE, DATE_ADD, DATE, DAY_OF_WEEK, valid_from filtering, reference_date |
| Advanced | Full engine features | All above + hooks (RFC-007), overrides, procedures (RFC-008), untranslatables (RFC-012), data sources |
Each level includes all operations from previous levels. A Core-level engine can execute simple single-law computations. An Advanced-level engine can participate in the full multi-org execution model (RFC-009).
Note: the engine’s ADD operation handles numeric addition, array concatenation, and string concatenation. String concatenation tests are in arithmetic.json alongside numeric ADD tests. Rounding operations (ROUND, CEIL, FLOOR) are not in the operation set yet (RFC-012 lists rounding as an untranslatable). When added, they join the Core level and get their own conformance tests.
The manifest file declares the level structure. Each level lists its test files and which operations it covers:
Levels without new operations (cross_law, ioc, advanced) have an empty operations array. They test resolution patterns and features rather than new operation types.
The engine defines Operation::SCHEMA_OPERATIONS, a const array of all operations that are part of the schema specification (excluding backward-compat aliases like NOT_EQUALS). An integration test (conformance_coverage.rs) reads the manifest and verifies:
SCHEMA_OPERATIONS appears in at least one conformance levelSCHEMA_OPERATIONS (no phantom operations)A separate unit test in types.rs verifies that SCHEMA_OPERATIONS + COMPAT_ALIASES account for every variant in the Operation enum. Adding a new operation variant without classifying it fails this test.
The chain of invariants: add an Operation variant → compiler forces a name() match arm → unit test forces adding it to SCHEMA_OPERATIONS or COMPAT_ALIASES → integration test forces adding schema operations to a conformance level in the manifest.
A dedicated provenance.json verifies that the engine produces correct Execution Receipts (RFC-013):
engine_version fieldschema_version matching the regulation’s $schemaregulation_hash as SHA-256 of the YAML contentProvenance tests are required at all conformance levels. Even a Core-level engine must stamp its outputs with provenance metadata.
The initial conformance test suite is derived from the existing BDD features. The process:
features/*.feature, extract the regulation YAML, input parameters, and expected outputsThe BDD features remain as integration tests for the RegelRecht engine. The conformance suite is the portable subset.
The conformance suite is validated in CI:
A new CI job conformance runs alongside the existing test job. It uses the evaluate binary to execute each test case and compares outputs.
Alternative 1: Shared BDD features with multi-language runners
Alternative 2: WASM-based conformance (compile the test runner to WASM)
Alternative 3: Conformance via the inter-engine protocol
Phase 1: Test format and Core level
conformance job to CIPhase 2: Cross-law and IoC levels
open_terms and implements resolutionvalid_from filteringPhase 3: Advanced level and provenance
provenance.json testing Execution Receipt fields (RFC-013)Phase 4: Documentation and third-party guide
Affected components
| File | Change |
|---|---|
conformance/ | New: test suite |
conformance/v0.5.0/manifest.json | Test manifest for schema v0.5.0 |
packages/engine/src/types.rs | SCHEMA_OPERATIONS and COMPAT_ALIASES consts, exhaustiveness test |
packages/engine/tests/conformance_coverage.rs | New: coverage invariant tests (manifest vs engine operations) |
packages/engine/tests/conformance.rs | New: Rust test runner for the conformance suite |
.github/workflows/ci.yml | New conformance job |
open_terms and implements (IoC conformance level)An exploration by Bureau Architectuur of the Dutch Ministry of the Interior into the possibilities of transparent, executable legislation.
Bureau Architectuur
Ministry of the Interior and Kingdom Relations