Treeship
Concepts

Verification surfaces

There is no single universal "verify." Every surface checks a specific set of properties against a specific trust input — this page is the map.

Treeship exposes several verification commands and APIs, and they deliberately do not all prove the same thing. A verifier that reports a stronger claim than its evidence supports is worse than no verifier, so each surface checks a scoped set of properties and names its scope in the verdict. This page is the map.

The matrix

SurfaceWhat it actually checksTrust inputStrongest verdict
treeship verify <artifact-id>Ed25519 signatures, content-address re-derivation, parent chain, approval nonce bindingLocal keys + pinned rootspass, with actor proof: proven (key-bound) or asserted
treeship verify <URL> / <package path>Structure only: Merkle root recomputation, inclusion proofs, leaf count, timeline orderNone — no issuer trust, no signaturesstructural-pass (never pass); signatures_verified: false
treeship package verifyPackage/artifact integrity: determinism, Merkle root, inclusion, plus approval-evidence replay rowsLocal keys + pinned rootsPass with an explicit receipt_body_binding warning — narrative is unsigned
treeship verify-capabilityCard + action envelope signatures, in/out-of-scope cross-checkPinned agent_cert rootsverified (key-bound); self-asserted without a pin
treeship verify-presentationCard, certificate chain, revocations, Merkle staple, optional live challenge — fully offlineYour pinned roots (agent_cert leaf or cert_issuer chain, hub_checkpoint staple, revoker)verified (key-bound, anchored, live)
treeship verify-profileEnvelope signature + field-by-field recomputation from the log at the pinned checkpointLocal keys + pinned rootschecked (a mismatch is a provable lie)
treeship resolve [--hub]Card, chain, revocation, transparency inclusion — Hub proposes, your machine decidesPinned cert_issuer + hub_checkpoint rootsverified (chain to pinned ship root)
@treeship/verify (WASM)Receipt structure, certificates, capabilities, cross-verify — in-process, any runtimetrustRoots you pass (fails closed when omitted)pass / structural-pass per function
Hub GET /v1/verify/:idNothing — retired410 Gone; verify locally

Why the split exists

Signature checks need the original envelope bytes and a trust decision. A receipt fetched from a URL carries neither: the JSON is self-referential, so the strongest honest claim is that its Merkle structure is internally consistent — structural-pass. Calling that "authentic" would launder structure into authorship. The full pass verdict lives where the envelope bytes and your pinned roots are: the local artifact path.

Trust is the verifier's, never the server's. The Hub's server-side verify endpoint was retired (it returns 410 Gone) because any verdict a server produces represents the server's trust policy. Every surviving surface resolves trust against roots you pinned — and fails closed when you haven't pinned any.

Different questions, different evidence. "Is this artifact intact?" (verify), "is this package self-consistent?" (package verify), "is this agent who it claims and allowed to do this?" (verify-capability / verify-presentation), "is this track record real?" (verify-profile) are distinct questions with distinct evidence. The one thing every surface shares: the verdict line states how it knows.

When gating automation (CI, pre-delegation checks), match the gate to the surface: exit codes or outcome == "structural-pass" for fetched receipts, outcome == "pass" only on the local artifact path, cross_verify.ok for certificate cross-checks, and a --challenge handshake before acting on a presentation.