Zero-knowledge proofs
Four layers of proof -- signatures, Merkle, Circom, RISC Zero -- each answering different questions about your agent workflows.
Treeship stacks four ZK-adjacent layers. Each one answers a different question, and each one has different performance characteristics. You pick the layers you need; Ed25519 signatures are always on.
Current status (2026-07, ZK layer under rebuild). Only the first two
layers (Ed25519 signatures and the Merkle audit log) ship enabled by default,
and they are the entire trust story of every release binary. The ZK layers 3
and 4 live behind the --features zk build flag, are excluded from release
binaries, and are being rebuilt statement-first. A July 2026 internal audit
applied cryptographer-level scrutiny to this layer and it did not pass; the
findings and the rebuild are in
the ZK verification spec.
- Layer 1 (Ed25519 signatures): stable, always on.
- Layer 2 (Merkle audit log): stable, always on.
- Layer 3 (Circom/Groth16): quarantined. The path generated proving
keys locally with no real trusted-setup ceremony, which makes it forgeable
by construction, and its policy constraint was unsatisfiable.
treeship prove/verify-prooffail closed with a pointer to the rebuild. The.circomsources are retained as design references; a sound path returns only under a real ceremony or a transparent proof system. - Layer 4 (RISC Zero zkVM): the transparent path (STARK-based, no trusted setup) that re-verifies signatures and chain linkage inside the guest. This is the primary non-interactive path in the rebuild; it is being hardened (in-guest artifact-id re-derivation, payload-extracted linkage, nonce binding, abort-on-violation) before it is unhidden.
- TLSNotary: not implemented. A designed direction for external-transcript capture, not a current capability.
Browser ZK verification is part of the rebuild target, not a current shipping
capability: the published @treeship/core-wasm build does not enable the ZK
feature. The always-on browser verification of signatures and Merkle proofs at
treeship.dev/verify is real today; browser verification of ZK proofs is not.
The four layers
Layer 1: Ed25519 signatures (always on)
Every artifact is signed the moment it's created. This is not optional and adds no measurable latency.
What it proves: this artifact was created by this Treeship and has not been modified since.
What it does not prove: anything about the artifact's contents, timing relative to other artifacts, or policy compliance.
Layer 2: Merkle audit log (instant)
Every artifact hash is appended to a local Merkle tree. The tree is append-only and tamper-evident. Generating a Merkle inclusion proof is instant because it's a tree traversal, not a computation.
What it proves: this artifact existed at this position in the log, and no artifacts before it have been removed or reordered.
What it does not prove: anything about what the artifact contains or whether it complied with policy.
Layer 3: Circom/Groth16 (quarantined, under rebuild)
The intended shape of this layer is a circuit that proves an action conforms
to a policy without revealing the action or the policy set. The implementation
shipped behind --features zk did not achieve that: it generated proving keys
with no real trusted-setup ceremony (forgeable by construction), left the
artifact binding unconstrained, and used a placeholder hash that made the
policy constraint unsatisfiable.
The path is therefore quarantined. treeship prove and verify-proof
fail closed with a pointer to the rebuild rather than produce a proof that
looks valid but establishes almost nothing. The rebuild (see
the ZK verification spec)
binds the committed value inside the signed artifact so a proof is meaningless
unless the classical signature verifies, states each proof as a formal
statement the verifier's own policy pins, and reaches for either a real
multi-party ceremony or a transparent proof system before this layer returns
to a release path.
Layer 4: RISC Zero (minutes, per-session, background)
A RISC Zero proof covers an entire session: a sequence of artifacts, their Merkle positions, and the session's causal chain. This is the most expensive layer and is intended to run in the background.
What it proves: the session chain is intact and every artifact's Ed25519 signature verifies against the same public key, all checked inside the zkVM. The verifier learns the chain is well-formed without re-running every per-artifact check itself.
What it does not prove today: the per-artifact Circom policy proofs are not currently re-verified inside the RISC Zero guest. Composing the two layers end-to-end is roadmap work, not a property of the v0.10.4 receipt.
What it does not prove at all: anything about network interactions or external API responses (that's TLSNotary's job, and TLSNotary is not yet implemented in this repo).
Performance: local CPU proving takes several minutes per session and is expected to run in the background -- the daemon kicks off chain proofs asynchronously. Verification of a finished receipt is well under a second. Bonsai hosted proving would be faster but is not wired yet (see status callout at the top of this page).
Requirements today: --features zk build flag. The RISC Zero zkVM links
in via treeship-zk-risc0. The image ID is embedded at compile time, so
verification is fully offline once a receipt exists.
How layers compose
Each layer builds on the ones below it. A fully-proved session looks like this:
{
"artifact": {
"content_hash": "sha256:abc123...",
"ed25519_signature": "sig:...",
"merkle_proof": {
"root": "0xdef...",
"path": ["0x1a...", "0x2b...", "0x3c..."],
"index": 42
},
"circom_proof": {
"policy": "budget_under_10k",
"proof": "base64:...",
"public_signals": ["1"]
}
},
"session_proof": {
"risc_zero_receipt": "base64:...",
"session_id": "session:...",
"artifact_count": 47
}
}You don't need all layers for every use case. A simple audit trail needs only layers 1 and 2. Policy compliance adds layer 3. Full session integrity adds layer 4.
Verification commands
Verify an artifact's signature (always available):
treeship verify artifact.jsonVerify a Merkle inclusion proof (always available):
treeship verify --merkle artifact.jsonVerify a Circom policy proof (requires --features zk build and snarkjs
installed on PATH):
treeship verify-proof art_xxx.policy-checker.zkproofGenerate a Circom proof for a single artifact (same build requirements as
above, plus circom and node on PATH):
treeship prove --circuit policy-checker --artifact art_xxx --policy ./policy.jsonProve a full session chain via RISC Zero (requires --features zk, runs for
several minutes on CPU):
treeship prove-chain <session_id>TLSNotary (roadmap)
TLSNotary would prove that a specific HTTPS request and response occurred between an agent and an external API. This is intended for commerce workflows where you need to prove that a payment API returned a specific confirmation, or that a price quote was real.
TLSNotary is not yet implemented in Treeship. There is no notary integration in packages/ today; the section here describes the intended shape, not shipping code.
TLSNotary is scoped to commerce workflows and is roadmap only. Most agent attestation use cases do not need it.
Status
| Layer | Status | Notes |
|---|---|---|
| Ed25519 signatures | Stable, always on | Since v0.1.0 |
| Merkle audit log | Stable, always on | Since v0.2.0 |
| Circom/Groth16 proofs | Quarantined | Forgeable as implemented (no real trusted setup) and unsatisfiable policy constraint. prove / verify-proof fail closed; .circom sources kept as design references. Being rebuilt statement-first. |
| RISC Zero chain proofs (local) | Under rebuild | --features zk build, excluded from release binaries. Local CPU proving via risc0-zkvm. The transparent, no-trusted-setup path being hardened as the primary non-interactive proof path. |
| RISC Zero Bonsai (hosted) | Roadmap | BONSAI_API_KEY is detected but unused; logs "coming in v0.6.0" and falls back to the local prover. |
| TLSNotary | Roadmap | Not implemented in this repo. |
Build flag
ZK layers (Circom and RISC Zero) are behind a feature flag to keep the default binary small. To build with ZK support:
cargo build --features zkThe Ed25519 and Merkle layers are always included.
Trust model
Every ZK layer in Treeship is designed to work locally without contacting a Treeship-operated service to produce or verify a proof.
Fully local, no external trust:
- Ed25519 signatures -- your key, your machine.
- Merkle proofs -- your key, your machine, self-contained proof file.
- Circom/Groth16 (quarantined) -- the previous path shelled out to local
snarkjsand generated proving keys locally with no real trusted-setup ceremony, which makes it forgeable by construction. It is quarantined and fails closed. The rebuild binds the proven value inside the signed artifact and reaches for a real ceremony or a transparent system before this layer returns. - RISC Zero chain proving and verification -- local zkVM via the
risc0-zkvmcrate, transparent (no trusted setup). The image ID is embedded at compile time, so a finished receipt is verified offline. Under rebuild: the guest is being hardened to re-derive artifact ids and extract chain linkage from the signed bytes, and CLI verification is being wired.
Trusted setup:
- The quarantined Groth16 path had no real phase-2 ceremony -- proving keys were generated locally with zero contributions, which is exactly why it is quarantined. Any future succinct path either uses a transparent system (no setup) or relies on a named, real multi-party ceremony, and says which.
Roadmap (not opt-in today):
- RISC Zero Bonsai would be a hosted prover for chain proofs. Setting
BONSAI_API_KEYis detected by the prover but is not yet wired -- the code logs "Bonsai integration is coming in v0.6.0" and runs the local prover instead. Track this as roadmap, not as an available opt-in.
Verify offline with no server trust (requires --features zk build and
snarkjs on PATH):
treeship verify-proof art_xxx.policy-checker.zkproofThis works air-gapped today via the local snarkjs verifier. The browser
verifier at treeship.dev/verify runs the equivalent Groth16 pairing check
in pure Rust WASM with no shell-out and no network call -- Hub cannot forge a
passing result. Once the in-repo ark-circom path lands, the CLI will offer
the same pure-Rust verification with no toolchain dependency.