The Voce validator runs 9 ordered passes over the IR, enforcing 46 rules that
span structural correctness, accessibility, security, and more. Validation
errors block compilation – there is no way to skip or suppress critical
failures. This is by design: accessibility and security are compile errors,
not warnings.
The VoceIr is a serde-based IR model, separate from the FlatBuffers generated
types. This decoupling is intentional – the validator works with JSON-
deserialized data, not raw FlatBuffers buffers. The NodeIndex provides
pre-built lookup tables (ID-to-node maps, parent chains) so passes can resolve
references without redundant traversals.
Passes execute in dependency order. Structural checks run first because later
passes assume the document shape is valid. Reference resolution runs second
because domain passes may follow reference chains.
The validator does not read FlatBuffers binary directly. Instead, it
deserializes JSON into a parallel serde-based IR model defined in
packages/validator/src/ir.rs. This model mirrors the FlatBuffers schema
but uses standard Rust types (String, Vec, Option) rather than
FlatBuffers accessors. The separation keeps validation logic clean and
testable without requiring binary serialization in test fixtures.