The principles in this guide are not aspirational. This page shows where each one is enforced in a working build — a demo that walks one bilateral payment confirmation from a held invoice to a signed, independently verifiable record. The snippets below are taken verbatim from the build’sDocumentation Index
Fetch the complete documentation index at: https://docs.cast.digitalfinancehq.com/llms.txt
Use this file to discover all available pages before exploring further.
schema.sql and canonicalize.ts. Where the guide makes a structural claim, the code that backs it is shown next to it — so the claim and the constraint are the same characters on the page.
This is Session 1 scope: the bilateral event loop. It deliberately proves the foundation — that a verified, co-authored record can be created and independently checked — before any downstream ledger automation is built. See Session 1 scope below for exactly what is and isn’t included.
What the demo does
One payment, three screens, each written for a different audience. The asymmetry is the point: the people doing the work never see cryptography; the people who underwrite the result see all of it.| Screen | Audience | Shows JSON / crypto? |
|---|---|---|
| Buyer AP queue | Controller | No — operational queue only |
| Seller Trade Message | Vendor AP clerk, on a phone | No — amount, invoice, destination, three actions |
| Verifier view | Lender / auditor / insurer | Yes — payload JSON, hashes, signature, recompute |
See the demo
The Layer 0 build is a working application, available on request. Reach out to book a walkthrough of the full buyer → seller → verifier flow, including the in-browser recompute.
Verification is a precondition to insert
The central claim of the architecture is that a record cannot exist unless it was verified first. This is not a status column that an event can sit in as “unverified” — it is the structure of the only code path that reaches the database. The single transaction recomputes the hash, checks the signature, and only then writes both the event and its signature together. If either check fails, the transaction rolls back and nothing is written:The gated transaction (shape, from schema.sql)
The two assertions run in application code inside the same database transaction as the insert. The guarantee is that the only path to insertion is gated by those checks, and the event row and signature row live or die together — not that the database engine itself performs the cryptography. (Stock Postgres can’t verify Ed25519 without an untrusted procedural language, and the build keeps to stock Postgres so a verifier in 2031 needs no exotic extensions.) There is no “pending” state and no “unverified” flag anywhere in the schema.
A posting cannot exist without a bilateral event
The strongest structural guarantee, and the easiest to verify: it is a non-nullable foreign key. A ledger entry with no co-authored event behind it cannot be inserted — the database rejects it.postings — from schema.sql
Signatures are over canonical hashes, not rows
A signature made today must still verify years from now, even after theevents table gains new columns. That only works if the exact bytes that were signed are reproducible. The build signs a hash of the canonicalized payload, never the database row:
canonicalize.ts — the single definition of the signed bytes
Lineage — why this is the asset
The property that makes a transaction insurable, financeable, and survivable.
One active policy, enforced in SQL
policy_versions — from schema.sql
How the record stays append-only
The system never updates and never deletes. Every state transition appends a new event; every correction is a new event, not an edit. The buyer queue even distinguishes held from confirmed by whether a work order’sbilateral_event_id is null yet — a value that can only ever be set, and only through the verified insert path.
This is a property of how the system operates: there is no code path that updates or deletes an event. It is described here as behavior rather than as a database-level prohibition, which is the precise and honest framing.
Five of the seven invariants, enforced today
The full architecture defines seven structural invariants. This build, operating on the bilateral loop without settlement, enforces five of them — and adds two implementation-level guarantees of its own.| Architecture invariant | In this build? |
|---|---|
| Posting requires a Bilateral Event | Enforced — non-nullable FK shown above |
| Lineage hash chain integrity | Enforced — recomputed at verify time |
| Single active Policy Version | Enforced — partial unique index |
| Hard-coded triggers cannot be suppressed | Enforced — first-payment and bank-change |
| Events are append-only | Enforced — no update/delete path |
| Bilateral Event requires confirmed Work Order state | Exercised when the full state machine lands |
| Settlement export requires approved Control track | Out of Session 1 scope — settlement is gated |
The two not yet exercised both concern settlement, which Session 1 deliberately gates out. They are not unenforced by oversight — the demo never reaches the stage where they apply. On top of the five, this build adds two implementation guarantees the schema-level list doesn’t enumerate: signature verification as a precondition to insert, and WebAuthn attestation stored on every signature.
Session 1 scope
The demo proves the foundation deliberately before building on it. What that means precisely:Implemented
The bilateral loop: Event, Policy Version, and Work Order as live objects, plus the Posting constraint (the table exists with its non-nullable FK, enforcing the guarantee even though it is never written this session).
Scoped for later
Case — the exception primitive — becomes a table when exception handling is built. Postings, GL coding, budget checks, ERP export, and settlement are gated until the bilateral loop is proven at volume.
settlement_state column is even CHECK-locked to a single value, so the schema itself rejects a settlement write this session.
Why prove the loop first: the bilateral event is the entire architectural claim. If a co-authored, independently verifiable record can be created and checked, everything downstream is a configuration problem. If it can’t, no amount of downstream automation rescues it.
What an external reader should take away
Most of these guarantees are not promises in prose — they are constraints in a schema and a hash in a registry. A skeptical reader does not have to trust the operator; they can read the same constraints shown here, and on the verifier screen, recompute the proof themselves.See the five primitives these enforce
Event, Policy Version, Work Order, Posting, Case — the objects this build instantiates.