Three components. One guarantee: any modification to the chain is detectable.
Every piece of data you append to a vault becomes an event. Each event has a sequence number, a timestamp, your data payload, and two cryptographic fields that make tampering detectable: prev_hash and signature.
The seq field establishes ordering. The data field is yours — any JSON payload. The cryptographic fields are computed by Provara and cannot be forged without your private key.
{
"seq": 42,
"type": "decision",
"timestamp": "2026-03-07T14:22:10Z",
"data": {
"model": "claude-3-5-sonnet",
"output": "approved",
"confidence": 0.94
},
"tags": ["production", "compliance"],
"prev_hash": "3e3b7f88c637...",
"signature": "ed25519:a1b2c3d4..."
}
# Ed25519 private key — never leaves your system private_key = Ed25519PrivateKey.generate() # Event content is serialized canonically # then signed before writing to the vault event_bytes = canonical_json(event) signature = private_key.sign(event_bytes) # The public key verifies — the private key forges. # We store neither. You hold both.
When you append an event, Provara signs it with your Ed25519 private key. The signature covers the entire event content — sequence number, timestamp, data, tags, and prev_hash.
To forge an event, an attacker needs your private key. That key never leaves your system — Provara only ever sees the public key, which verifies but cannot sign.
Ed25519 is a modern elliptic curve signature scheme. It is fast, compact, and used by SSH, Signal, and TLS 1.3. The signatures are 64 bytes. The math has been audited extensively.
Every event includes a SHA-256 hash of the previous event in its prev_hash field. This creates a chain. The first event hashes a genesis value; every event after hashes its predecessor.
To modify event N without detection, you would need to:
prev_hash to matchMiss any step: verification fails immediately. The chain is as strong as its weakest link — and every link requires the private key to reforge.
# Each event hashes the one before it def compute_hash(event: dict) -> str: canonical = canonical_json(event) return sha256(canonical).hexdigest() def append_event(vault, event_data): prev = vault.last_event() event = { "seq": prev["seq"] + 1, "data": event_data, "prev_hash": compute_hash(prev), # ... } event["signature"] = sign(event) vault.write(event) # To tamper with seq=5, you must re-sign # seq=5, 6, 7 ... N. Every. Single. One.
$ psmc --vault ~/.provara/my-vault verify Chain integrity: CLEAN (142 events, 0 gaps) $ psmc --vault ~/.provara/my-vault verify # (after tampering) Chain integrity: FAIL event seq=12 — hash mismatch Expected: 3e3b7f88c637... Got: d41d8cd98f00...
The psmc verify command walks the entire chain. It re-checks every signature against the public key and re-hashes every event to confirm the links hold.
A clean vault outputs a single line. A tampered vault tells you exactly which event failed and what the expected vs. observed hash was.
Verification is deterministic and requires no network access. You can run it offline, in CI, or in a legal proceeding. The vault proves itself.
The protocol is open and self-hostable. Provara.app is a managed layer on top: a hosted vault endpoint, a REST API for appending and querying events, and a dashboard for browsing your chain.
You keep the private key, or use Provara-managed keys with hardware-backed isolation. We store the vault. You verify whenever you want — using the same open-source CLI as self-hosted deployments.
No lock-in. The vault format is NDJSON. Download it at any time and run it locally.