CAST is a bilateral coordination protocol. Before any commercial payment settles, payer and counterparty co-author one cryptographically bound record. That record is the authorization — and it travels through your ERP, audit, lenders, and insurers as tamper-evident proof.
# Vendor confirms via passkey — the bilateral pivot
{
"event": "bilateral.confirmed",
"work_order": "wo_8fa2c1",
"payload_hash": "3a9f…e21b",
"signature": {
"method": "webauthn-p256",
"bound_to": "payload_hash",
"signer": "agent_riverdale"
},
"policy_version": "POL-v4.2",
"lineage_hash": "7c0d…b48a"
}
→ Posting blocked until signature verifies.
→ Posting carries lineage to this event. Forever.
The payer approves an invoice internally. The vendor learns of the transaction only when — or if — money arrives. Digital tools removed checks, branches, and paper, but left the trust model untouched. A payment process where only one of two parties confirms terms before value moves is not bilateral authorization. It is a unilateral instruction with hope attached.
The AP instantiation — Confirm & Pay — walks one invoice through the loop. Steps 1–5 are the entire prototype. The cryptographic chain is the product; the screens are its packaging.
Trigger conditions evaluate. First payment, bank change, threshold breach. A Proposed Event is written with policy version pinned.
Counterparty receives a browser link: amount, date, bank last 4, three buttons. No app. No account. State advances to sent → viewed.
A passkey assertion is verified and bound to the Work Order hash. The Bilateral Event is written. Lineage hash computed from the prior chain.
The pivotSeven auto-approve conditions evaluate against the pinned policy. The Posting is generated as a derived output — with a non-nullable FK to the bilateral event.
Append-only by construction. A Posting cannot exist without a bilateral co-authorship. This is enforced at the database layer — not by the UI.
An immutable record of something that happened. Proposed events are unilateral; bilateral events are co-authored by both parties.
A versioned, immutable rule set. Pinned to every event at processing time. Governs triggers, auto-approve conditions, and escalation.
The execution context for human and agent decisions. Three parallel state tracks: Bilateral, Control, Settlement — never collapsed.
A journal-ready ledger entry, generated as the output of a completed Work Order. Carries full lineage back to the originating event.
A governed exception — dispute, non-response, budget breach, policy gap. Appends resolution events; never unwrites prior ones.
event → work order decisions → policy version → posting. Verification cost drops to near zero because checking a hash is structurally cheaper than reconstructing a decision chain.
CAST eliminates the class of fraud that depends on one party acting without the other's knowledge. Collusion isn't eliminated — but it becomes documented and detectable rather than invisible.
Follow a single transaction — PO-2026-0142, Acme buying $47,000 of textiles from Riverdale — from issue to confirmation to independently replayable proof. Scroll through the buyer's books, the seller's mirror, and the verifier's evidence surface. Toggle dev notes for the v1.4 API and control-plane internals.
Every PO you send is tracked from draft, to vendor acceptance, to the accrual that hits your GL — supported by evidence your auditor can pull up in seconds. Your workflow unchanged, your controls strengthened.
Every PO your team issues flows through this board. The system stamps each PO the moment it's authorized — quantity, price, delivery date, terms — and watches for the vendor's confirmation. Nothing hits the GL until it's back.
| PO # | Vendor | Issued | Amount | State |
|---|---|---|---|---|
| PO-2026-0142 | Riverdale Textiles Ltd. | 20 Apr · 14:02 | $47,000.00 | Sent, awaiting |
| PO-2026-0141 | Pacific Packaging Inc. | 19 Apr · 11:30 | $8,250.00 | Confirmed |
| PO-2026-0140 | Kestrel Hardware Co. | 18 Apr · 09:15 | $14,800.00 | Posted to GL |
| PO-2026-0139 | Meridian Dye Works | 17 Apr · 16:40 | $23,100.00 | Draft |
GET /v1/control-items?track=outboundPOST /v1/events → canonicalize → hash → Work Order draftcontrol_item_view.bilateral_statuscontrol_item_view, a refreshable projection over Work Orders — not a source of truth. last_actor_mode and accountable_owner render per row.The PO is sealed and sent. Until the vendor accepts, nothing moves on your GL. You can resend, edit, or cancel — but once they confirm, the accrual is supported and posting begins automatically.
GET /v1/control-items/{id} (SSE for sig arrival)event_signatures → "awaiting" UIevents row createddecision_view with reason codes — not hardcoded in the UI.Riverdale's confirmation came in at 14:32. The system immediately posted the accrual: a debit to raw-materials inventory and a credit to your vendor payable. Every line traces back to PO-2026-0142.
| Dr/Cr | Account | Debit | Credit | Support |
|---|---|---|---|---|
| Dr | acme.inventory.raw_materialsOrganic cotton + French terry inbound | $47,000.00 | — | PO-0142 |
| Cr | acme.vendor_payable.riverdaleNet-30 obligation | — | $47,000.00 | PO-0142 |
Month-end close, lender reporting, board pack — same five documents, always.
postings_require_signed_eventWhen a buyer's PO arrives, you review the terms, confirm them, and your AR accrues against a document both sides agreed to in writing. A cleaner inbox and a better set of receivables.
When a customer sends you a PO, you receive one link. You review the exact terms, then confirm. Your confirmation is the bell that makes the sale real — and the evidence your AR team, your auditor, and your customer's bank can all rely on.
GET /v1/control-items — filtered by counterparty_agent_idevent_signatures row → confirm enabledperformed_by_mode = counterparty; the Work Order's accountable_owner_id stays an internal human.Confirming binds you, on behalf of Riverdale Textiles, to exactly these terms — and only these. If the buyer later changes any field, your acceptance no longer applies.
POST /confirm/:token/beginPOST /confirm/:token/finish — challenge = payload_hashevents + event_signatures → consume tokenfmt='none'; reject UV=falseperformed_by_mode = counterparty, performed_by_role = vendor signer; review_required is policy-driven.The moment you confirmed, your AR team saw the receivable post. Same bilateral event as Acme's accrual — your mirror image of the same agreement, on your side of the ledger.
| Dr/Cr | Account | Debit | Credit | Support |
|---|---|---|---|---|
| Dr | riverdale.ar.acmeNet-30 receivable from Acme Apparel | $47,000.00 | — | PO-0142 |
| Cr | riverdale.revenue.deferredSpring production run · delivery 15 Jun | — | $47,000.00 | PO-0142 |
Every open receivable traces to a customer-confirmed PO. Cleaner aging, fewer disputes, stronger credit package.
postings ×2: Dr AR, Cr Revenue — same event_idstate_snapshot_view — current vs. expected value, unexplained variance surfaced automatically.Given only the database rows, the committed source code, and a standard cryptographic library, any external party can reproduce the signed content byte-for-byte, verify the signature, and walk the attestation chain back to a manufacturer certificate authority.
This is the purchase order as sealed evidence. A verifier in 2031 can recompute this fingerprint from the raw JSON and the pinned source code, and confirm the bytes have not changed.
events + schema_registryactor_mode, actor_role, authority_context and accountable_owner_id — all replayable from the same row.Every byte a verifier needs to prove, independently, that Riverdale Textiles agreed to PO-2026-0142's exact terms at a specific moment, using a hardware-attested credential registered to them.
event_signatures + webauthn_credentials + agentshistory_view as a counterparty action — ordered alongside human, agent, and system actions for full attribution replay.Given nothing but the database rows and the committed canonicalizer source, any verifier can walk this chain in five steps, with standard cryptographic primitives and no access to either counterparty or the platform operator.
No trust required. No account at Acme, Riverdale, or CAST. Just SHA-256, ECDSA, and X.509.
Why the verifier view matters, commercially.
For an auditor — every GL posting has cryptographic support that cannot have been fabricated after the fact. Support documentation is produced automatically, not reconstructed at year-end.
For a lender — a receivable on a borrower's balance sheet can be verified against a counterparty-confirmed PO, with hardware-attested identity. Borrowing-base diligence becomes a query, not a request.
For an insurer — the event chain is an underwritable fact pattern. Loss prevention, dispute defense, and fraud investigation all rest on the same rows.
schema_registryGET /v1/control-items/{id}/timeline, /invariants, /history expose the replay surface; POST /evaluate recompiles invariant results. Projections are replayable, never the source of truth.The four layers don't change between use cases. Only event types, policy rules, and Work Order structures do. CAST sits alongside your ERP — not in place of it — and produces posting-ready exports with the lineage hash in the memo field.
// Any third party, no counterparty contact
const ok = await replay(eventId);
// Standard libs only — no proprietary verifier
- SHA256(canonicalize(payload, v1))
- ECDSA-P256 signature check
- X.509 chain validation
return {
valid: ok,
proves: "both parties confirmed",
at: "signed timestamp",
unmodified_since: true
};
It travels with the payment through every downstream system. That's what makes a transaction insurable, financeable, and survivable in audit.