Treeship
Concepts

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-proof fail closed with a pointer to the rebuild. The .circom sources 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.json

Verify a Merkle inclusion proof (always available):

treeship verify --merkle artifact.json

Verify a Circom policy proof (requires --features zk build and snarkjs installed on PATH):

treeship verify-proof art_xxx.policy-checker.zkproof

Generate 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.json

Prove 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

LayerStatusNotes
Ed25519 signaturesStable, always onSince v0.1.0
Merkle audit logStable, always onSince v0.2.0
Circom/Groth16 proofsQuarantinedForgeable 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)RoadmapBONSAI_API_KEY is detected but unused; logs "coming in v0.6.0" and falls back to the local prover.
TLSNotaryRoadmapNot 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 zk

The 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 snarkjs and 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-zkvm crate, 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_KEY is 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.zkproof

This 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.