Skip to main content
A contract belongs to a channel. Not to a release train, and not to a station. vexa-internal has one contract; a subscriber shape such as oenb-stable has one; and a station — staging, prod, a subscriber’s estate — is a place where that channel’s contract is enforced, never a thing that owns a contract of its own. Founder correction, 2026-08-29, recorded on #12. The reason is that two stations of one channel do not disagree about what a release must prove. They disagree about what has been proven so far, and about what it was proven against. Writing that difference as two contracts encodes it as a difference in demand, which is false, and leaves two documents to keep in step — the copy problem this whole page exists to delete. The difference is written instead as the proof column of one filled instance per train.

Zero duplication, by construction

Five mechanisms, and each one exists to delete a copy.
  1. Values are declared once, in a per-channel registry. One entry per value: id, claim, rank, validation, surface. The sentence a human witnesses is written in exactly one file.
  2. A channel’s contract is rows of references{value_id, enforcement, freshness} — never restated claims. A contract that contains a claim sentence is a contract that will disagree with the registry eventually.
  3. A derived channel extends the channel it derives from. A contract carries only its own delta.
  4. Tighten-only, enforced by the compiler. Monotone growth is a checked property, not a convention, and it is checked across channels — the direction that matters commercially, because it is what makes a subscriber’s channel provably no weaker than ours:
  5. contract compile flattens the chain into one effective, content-addressed JSON per channel — the sha256 a station verdict pins — plus a derived human rendering. Every station of that channel mounts the same compiled bytes. Charts and humans read compiled output, never fragments. Same principle as the rendered chart contract: the record is the fragments, the thing anyone reads is generated from them.

The contract is a form; a train fills it in

There is no separate validation document. Founder ruling, 2026-08-29, recorded on #12: the contract is the form, and a station run fills it in. A train yields exactly one filled instance of its channel’s contract — same contract_id, sha-linked back to the unfilled demand it was filled from, so the two can never be read apart. The proof column is inline, on the row it answers: The vocabulary is not new — it is the fidelity and decomposition vocabulary that used to live in a standalone document, moved onto the rows it qualifies. What changes is that a reader no longer holds two files side by side and works out which caveat attaches to which claim; the caveat is on the claim. Every row of the demand appears, in the demand’s own order and the demand’s own words, whether or not it was answered — an instance that dropped the rows it could not fill would read as complete while being quietly narrower than the contract it claims to fill. The verdict is that instance’s bottom line — ELIGIBLE when every required row is proven, NOT_ELIGIBLE when one is refuted, and INCOMPLETE when the run ended with required rows neither proven nor refuted, so that a run which could not reach a dependency cannot be filed as either — and the PROOF card is the filled contract rendered. One record, two readings, neither written by hand. The evidence kind stays validation_contract. The name is now wrong for what it carries and is kept anyway this turn, because renaming it would break the entry schema, the carriage predicates that name it in require_evidence_kinds and forbid_absent_evidence, and the entries already published under it. The prose says the filled contract; the wire says validation_contract. That gap is a deliberate debt, named here rather than left for a reader to trip over. The definition of the filled shape is spec/filled-contract.schema.json — everything above is a reading of that file, not a second copy of it. It is committed with this page in the seq-7 respin and is not on main yet. As of that turn it defines the document and validates instances offline; the in-cluster verifier does not evaluate it, and the gate still admits an entry on its carriage block alone.

What format a contract is

Bespoke JSON, sha-pinned, unsigned. That is the honest answer today, and the sha is what carries the weight: a verdict names the contract id and its hash, so a claim is always attributable to exact contract bytes, and changing a contract changes what every verdict rendered under it means. Contracts live in the stations ledger and move only by pull request. Nothing was rejected to get here. Policy format is the layer the industry has not standardised — each system ships its own (attestation-requirement documents with embedded expression languages, per-cluster attestor rules, admission CRDs), and none of them is a format a second vendor reads. There was no widely-adopted thing to adopt, so this is one of the places #12 leaves bespoke rather than borrowing. The target closes the gap that matters, which is not the syntax: The syntax stays ours. The signing does not.

Worked example

The values registry — three values, each written once, one registry per channel:
The vexa-internal contract — two rows, no claims. Both of that channel’s stations enforce this one file:
The oenb-stable contract — a different channel, extending it: raises one, adds one:
The compiled effective oenb-stable contract — what that channel’s charts mount and its verdicts pin, at every station on it:
V-ready was never restated — it arrived by inheritance, carrying where it came from. V-join shows the only two moves a derived channel gets: enforcement up, freshness down. Nothing in the chain mentions a station, because no station owns any of it. Every train that runs on oenb-stable fills in that same compiled document — the demand does not move between trains, and the proof column is what varies per set. A filled instance against the contract that actually exists today is below.

Today, and the target

Contracts are flat today: one file, claims written out in it, no registry and no extends — and the file is named after an estate rather than after the channel it belongs to. The live internal contract carries its values inline beside a carriage block — two of its six rows, to show the shape:
— which is already the right vocabulary (values with a rank, a validation kind and an enforcement level, separated from the carriage predicates), and is still one flat file with the claims copied into it and, until now, nowhere on it to write what a run proved. The same contract, filled — what SET seq-7 returns, the first instance of the shape and authored by hand. Two rows again, per spec/filled-contract.schema.json; each carries the demand’s own row id and the demand’s own words, and adds nothing but the proof block:
Same id, sha-bound to the demand it answers, every demand row present whether or not it was answered — and the caveat that used to sit in a separate document now sits on the row it qualifies.

What that contract says, in words

The same file, read out. This rendering is derived from the JSON, never written beside it — one source of truth, or the two disagree and the readable one is the one people believe:
The channel requires, and refuses the release without them: every platform deployment reaches ready, a bot joins a live meeting and transcript segments arrive over websocket, and runtime-spawned bot pods carry explicit cpu and memory resources — each machine-checked. It asks for, and reports but does not refuse on: the documented API surface responds as documented (proven against the whole digest set), join success over the declared window stays above threshold (a rate, not a run), and transcription quality is acceptable — which only a person can say. Whatever ships must carry its filled contract, may not declare that document absent, must be a candidate entry, may not be break-glass, and may not be more than 30 days old.
Three things are visible in that paragraph and in no JSON diff: what is enforced versus merely watched, which claims rest on a human, and that the freshness ceiling exists at all. It is generated on compile and lives with the contract in the ledger, beside the record it renders. The filled instance renders the same way, with the proof column showing — that rendering is the PROOF card.
State: RULED, NOT BUILT. The values registry, extends, the tighten-only compiler check, contract compile, and contracts keyed to a channel rather than to an estate are decided and unimplemented; what runs today is the flat shape above. The filled shape is definedspec/filled-contract.schema.json is committed here and validates instances offline — but nothing produces one: the seq-7 instance is authored by hand, the in-cluster verifier does not evaluate it, and the gate still admits an entry on its carriage block alone, so required values are checked by script rather than by reading demand rows against proof rows in one pass. See the evidence model for the full per-element state.

Setting and amending a contract

A contract states the standing properties of one channel. It is amended rarely and deliberately — cargo never edits it, because one durable carriage clause (require_entry_values_proven) already gates whatever an entry claims.
  1. The consumer owns it. A contract belongs to the party who consumes the channel, never the publisher — the subscriber for theirs, us for vexa-internal. The vendor may draft; the owner decides. A station operator does not get a contract of their own by running a station; they get the channel’s.
  2. Immutable — succession, not mutation. A change mints a successor (…-2026-09…-2026-10) committed to the ledger. The predecessor stays in the record forever: old verdicts name it by id and sha and must remain auditable.
  3. The change vehicle is a reviewed commit carrying the reason. Tightening (add a value, flip advisory → refuses, shorten freshness) is routine. Loosening requires the justification in the commit and the owner’s explicit word — and a derived channel’s contract can never loosen the one it extends; the compiler refuses it.
  4. Taking effect is mechanical, never silent. A contract binds when a station’s enforcement copy is rendered from the record, sha-pinned; every verdict names the contract id and sha it judged under, so which rules were in force for entry N is always answerable — and the answer does not depend on which station asked.
  5. There is no emergency edit path. allow_break_glass: false means none exists. A real emergency mints a successor through the same protocol — fast is fine, silent is impossible.
  6. Target: the contract itself becomes a DSSE-signed document under the owner’s key. A subscriber’s contract signed with their key makes their refusal of the vendor cryptographic rather than procedural. (RULED, NOT BUILT.)
Next: Evidence reuse and blast radius · The station gate