Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The parser-free core

Reading source code is the most dangerous thing vidi does. Nineteen tree-sitter grammars, all of them generated C, run over whatever happens to be in your repository.

So the code that decides whether you pass never does it.

The one-way edge

The workspace manifest states the doctrine in its own header: six crates whose dependency edges point one way, into a parser-free trusted core. Nothing the core trusts ever sees a parser.

vidi-lang    19 tree-sitter grammars + a Markdown profile  ─┐
vidi-graph   significance scoring, advisory only           ─┼─→  vidi-core
vidi-cli     filesystem and CLI glue                       ─┘     decides

vidi-core holds everything that produces a verdict: addressing and digests, in-toto records, the ledger, trust policy, signature and notary verification. It depends on no internal crate, not one path dependency in its manifest.

The mechanism is that simple, and Cargo checks it on every build. Doctrine in a comment is a wish; doctrine as a dependency edge is enforced.

Why parsers specifically

A parser’s input is untrusted by definition. The scan reads whatever is committed, and a generated, minified, or deliberately hostile file can nest arbitrarily deep: a 20,000-level parenthesis chain, a 50,000-segment qualified name. Every recursive descent in vidi-lang carries a depth cap for exactly that reason.

Keeping the grammars out of the deciding path bounds what a bad file can do. It can crash the scanner, produce nonsense units, or refuse to parse. It cannot forge a verdict, because nothing it touches is trusted by the code that computes one.

What the name overstates

vidi-core is not literally free of parsing. It depends on seven external crates, and two of them decode formats:

CrateWhy it is there
blake3the sole content-addressing hash
serde · serde_jsonthe exact bytes a record is hashed from, and the ledger line format
toml.vidi/policy.toml, with Spanned byte offsets for diagnostics
ed25519-dalek · sha2signature verification and the keyid fingerprint
libcO_NOFOLLOW for the ledger custody seam, Unix targets only

So the core does parse, but only its own small, controlled formats. What it never parses is a programming language. That claim is narrower than the name suggests.

The cost, in hand-written code

Adding a dependency to the core is expensive, so small things get written rather than imported. The policy glob matcher is 186 hand-rolled lines, and its module docs say why plainly: a vendored glob engine would be far more attack surface than these few lines. Errors are hand-rolled too, with no thiserror.

Every dependency in the core’s manifest carries a comment arguing for its existence, and the workspace catalog is grown at first use, never ahead of a consumer, so the tree never carries an unused edge.

What sits outside, and why

Two crates are excluded on purpose, and neither is a parser:

vidi-graph computes significance, meaning how much a change matters. It is advisory and never feeds a content hash. Ranking is allowed to be clever, heuristic, and wrong; it orders a queue rather than deciding an outcome, so it does not need to be trusted.

vidi-interop binds the engine’s output for renderers and never re-derives a verdict. Clients display what the core decided; they do not recompute it.

The line is not “parsers outside, everything else inside”. It is: anything that could be wrong without being dangerous stays out.

No unsafe anywhere

All six crates carry #![forbid(unsafe_code)], the core included. The compiler rejects hand-written unsafe, so memory-safety review has no surface to cover. The tree-sitter grammars are still C, linked in. The forbid applies to vidi’s own Rust, not to what it links.

Where it frays

The core still decodes untrusted input. Ledger lines, policy files, and signature envelopes all arrive from outside and all go through a decoder. Parsing is reduced to small controlled formats, not eliminated, which is why those paths fail closed on any doubt rather than trusting a successful parse.

Hand-rolled means fewer eyes. A bespoke glob matcher has bespoke bugs, and 186 lines maintained here get far less scrutiny than a widely used crate. The trade buys a smaller, auditable surface at the price of shared maintenance. That is a trade rather than a free win.

The grammars still ship. They are excluded from the deciding path, not from the product. A parser bug is still a bug you experience; the guarantee is only that it cannot become a forged verdict.

Next

Why review files never conflict