Skip to main content

Module schema

Module schema 

Source
Expand description

The cheapest deterministic check there is: does this output match its declared shape?

A step that promises { "severity": "high" | "low", "files": [string] } and delivers prose has failed, and it has failed in a way that no downstream step can recover from — it will either crash on deserialisation or, worse, silently read a field that is not there. Catching it here costs microseconds and needs no tools, no sandbox, and no model.

§A subset, and unknown keywords are refused

This validates a documented subset of JSON Schema, listed on SUPPORTED_KEYWORDS. Anything outside it — $ref, pattern, format, if/then/else — makes Schema::compile fail.

Refusing is the whole design, and the alternative is worse than it sounds. A validator that ignored the keywords it did not implement would hand a schema author a Pass on a payload their schema said was invalid, and nothing anywhere would report that a constraint had been skipped. That is a silent downgrade of a security property, which is the failure mode Goal G5 exists to prevent. A build error naming the keyword is a cheap failure; a check that quietly stopped checking is not.

§Why it cannot hang

Two independent bounds.

The schema is a finite tree. $ref is not supported, so a schema cannot refer to itself, and schema depth is capped at compile time (MAX_DEPTH). That is a stronger property than it first looks: validation descends only where the schema descends, so recursion is bounded by the schema and not by the instance. A payload nested a thousand levels deep against a two-level schema is walked two levels deep.

Validation has a step budget. A finite schema still multiplies work: oneOf re-validates the same subtree once per alternative, and against a large array that compounds. So every comparison decrements a counter, and running out is Verdict::Inconclusive — never Pass, and never Fail either, because “we ran out of budget” is not the same claim as “your payload is wrong”.

What this module does not defend against is a payload so deeply nested that operating on it at all overflows the stack — enum and uniqueItems compare values structurally, and comparison recurses over the instance. That hazard is real but it is not created here and cannot be fixed here: by the time a Condensate exists, something has already built the value, and whatever built it would have overflowed first. Capping payload depth belongs where payloads are produced.

§What a Pass actually guarantees

That the payload was representable as JSON and satisfied the schema. Both halves matter: the checker converts the condensate’s CBOR payload into JSON before validating, so a payload that could not survive that trip fails here rather than three steps later. A downstream step deserialising into a type that matches the schema will therefore succeed.

Structs§

Schema
A compiled schema: a finite tree of constraints, plus its content address.
SchemaChecker
Rejects a condensate payload that does not match a declared schema.
Violation
One way in which a value did not match its schema.

Enums§

SchemaError
A schema could not be compiled.
Validation
What validating a value produced.

Constants§

DEFAULT_BUDGET
How many comparisons a validation may make before giving up.
MAX_DEPTH
How deeply a schema may nest.
SUPPORTED_KEYWORDS
The keywords this validator implements.