Boring cryptography, composed so that lying stops being possible
Nothing here is novel — that's deliberate. Every primitive has been reviewed for a decade or more. The engineering is in the composition and in refusing every shortcut that would require you to trust us.
ConstatVault is the platform. It runs on two engines: TruthLayer, which captures and seals the ledger, and EvidenceVault, which turns a sealed record into a certificate. The two share no trust — EvidenceVault independently re-derives every Merkle root it certifies. (Constat, from the French constat d'huissier: an official, independent record of what happened.)
Write timeCanonicalise, then sign
Per agentHash-chain the sequence
Hourly · dailyFold into Merkle roots
Once a dayAnchor outside our control
Any timePublish a self-contained bundle
ForeverVerify without us
From one agent action to a Bitcoin block
- 01 · eventAgent acts. Event canonicalised and Ed25519-signed at write time.
- 02 · chainEvent links to the previous one; head_index increments.
- 03 · hourHour closes. Merkle root computed over that hour's leaves.
- 04 · dayDay closes. Daily root computed over 24 hourly roots and sealed.
- 05 · anchorDaily root submitted to OpenTimestamps; Bitcoin confirms it.
- 06 · auditAnyone downloads the bundle and re-derives every step offline.
The honest boundary: ConstatVault proves what was recorded, when, and that it hasn't changed since. It does not prove that the agent's decision was correct — no cryptography can. It makes the record of that decision impossible to revise afterwards.
On the roadmap: qualified electronic timestamps and seals under eIDAS 2.0, so the same record carries an EU-recognised legal presumption alongside its Bitcoin anchor. The anchor already stands on its own; this adds a second, statutory footing.
One SDK call at the boundary you already have
Evidence is created where the action happens, not scraped from logs later. Most teams instrument in an afternoon.
from constatvault import Vault
vault = Vault(tenant_id="tnt_acme", agent_id="agt_settlements")
vault.record(
action="wire.transfer.approve",
subject="INV-88213",
authority="policy:treasury.v7", # under whose rule it acted
inputs={"amount": 41250.00, "ccy": "EUR"},
outcome="approved",
)
# → signed, chained, and folded into today's Merkle rootPayloads can be hashed rather than stored, so the evidence layer never becomes a second copy of your sensitive data. What gets proven is the commitment, not the contents.