ADR 0001: The spec is data with a closed vocabulary
- Status: accepted
- Date: 2026-09-23
Context
Many DSLs grew expression languages: rule expressions, policy expressions, workflow expressions — each with its own parser, evaluator, sandbox, and error model. They became second programming languages: powerful, unlintable, and impossible to reason about exhaustively.
Decision
The spec files contain no expressions. Types are a closed vocabulary of
nine primitives (string, bool, i64, i32, u64, u32, f64,
uuid, datetime), declared entities and enums, and one level of
lists. Behavior is expressed by referencing a hand-written Rust
function; middleware is a closed vocabulary (v0: cache). Anything
outside the vocabulary is a parse error, not a runtime surprise.
An expression language (a small CEL-like one) is explicitly deferred: it may come in a later version, as an ADR, when a concrete need exists.
Consequences
- The parser is serde itself; there is no grammar to maintain.
mosaic schemacan describe the entire input precisely.- Features are added one vocabulary word at a time, each visible in the schema and the goldens.
Proof
cargo test -p mosaic-grammar → ty::tests::rejects_option_and_nested_arrays
(optional types, nested arrays, and empty types are rejected at parse
time) and ty::tests::accepts_both_list_spellings.