Verifier System
Offline verifier and bundles
A verifier bundle is a portable evidence pack. It contains the proof objects needed to verify a stream range without Attesto backend access, plus a manifest that binds the included files.
Offline verifier
The offline verifier checks locally. Online anchor re-checks are optional and explicit, so a reviewer can still verify the core bundle when network access is restricted.
attesto receipts verify \
--file ./receipt.json \
--public-key-hex "$ATTESTO_RECEIPT_SIGNER_PUBLIC_KEY_HEX"
attesto bundles offline-verify --file ./attesto-bundle.json
attesto verify file --file ./receipt.attesto.json \
--public-key-hex "$ATTESTO_RECEIPT_SIGNER_PUBLIC_KEY_HEX"
attesto verify truth-package --file ./truth-package.zip
Window, checkpoint, anchor, IVC, and full bundle verification can also be run through the online verifier API from the same CLI:
attesto windows verify --file ./window.json
attesto checkpoints verify --file ./checkpoint.json
attesto anchors verify --file ./anchor.json
attesto ivc epochs verify --file ./ivc-epoch.json
attesto bundles verify --file ./attesto-bundle.json
Portable receipts
A portable receipt is a self-contained *.attesto.json
export around one signed receipt. It lets a recipient verify the
receipt with the Python SDK, TypeScript SDK, Go SDK, CLI, or browser
verifier without calling the Attesto backend. A pinned public key is
the trustworthy verification path; an embedded key is only a transport
hint and must not replace a verifier's trust policy.
Portable receipts are useful for email attachments, support tickets, data-room uploads, and regulator workflows where a full bundle is not needed yet. They still fail closed on changed payload commitments, changed event hashes, wrong signatures, or mismatched stream linkage.
Browser WASM verifier
The verifier-only WebAssembly build exposes receipt, inclusion, checkpoint-root, and completeness verification to a browser page. It has no client creation flow, no API key handling, and no background network requirement. The JavaScript shell passes JSON into the WASM verifier and receives a JSON report back, so browser verification stays a thin local wrapper around the same Go verifier semantics used by the CLI.
Verify portal
The browser Verify portal at /verify.html is for quick
receipt verification by an external recipient, auditor, or support
team. Drop a receipt JSON or portable receipt file into the page,
paste the pinned witness public key, and verify locally. The page
loads the WASM verifier from /assets/attesto-verify.wasm
but does not upload the receipt, payload, public key, or verifier
result to Attesto.
For regulated workflows, pin the witness public key out-of-band and
compare the WASM asset hash with the release manifest before relying
on a browser result. Use POST /v1/public/verify for
receipt verification in a server workflow, and POST /v2/verify
for Proofstream object and bundle verification. Browser verification,
CLI verification, SDK verification, and API verification must agree on
the same canonical JSON and signature semantics.
Bundle structure
{
"manifest": {
"bundle_id": "bundle_...",
"protocol": "ATTESTO-PROOFSTREAM-001",
"created_at": "2026-06-07T12:00:00Z",
"stream_id": "str_...",
"from_seq_no": 1,
"to_seq_no": 250,
"artifact_hashes": {
"receipts.json": "sha256-hex",
"windows.json": "sha256-hex",
"checkpoints.json": "sha256-hex",
"witnesses.json": "sha256-hex",
"anchors.json": "sha256-hex"
}
}
}
Truth packages
Tenant export ZIPs are also lifecycle evidence. When Attesto builds a
package, it writes attesto.truth-package.manifest.json
into the ZIP, hashes the finalized ZIP, and records a
truth_package.generated Proofstream event. Every
meaningful dashboard or auditor access records a
truth_package.accessed event with a unique access id,
timestamp, package hash, manifest hash, actor type, access method,
and hashed network metadata. When a user, auditor, SDK, or CLI submits
a successful cryptographic verifier report back to Attesto, the
backend validates the report against the stored package and manifest
hashes and records a truth_package.verified event.
This proves package integrity and lifecycle provenance. It does not
prove legal compliance by itself, and it does not prove that a
recipient read or accepted the contents. Download/access proves that
the package was served; truth_package.verified proves
that a verifier actually recomputed the ZIP and artifact hashes.
The final ZIP hash is deliberately recorded after ZIP finalization and outside the ZIP itself. Embedding the receipt over the final ZIP hash inside the same ZIP would create circular self-reference: changing the ZIP to add the receipt would change the hash the receipt signs.
attesto verify truth-package --file ./truth-package.zip
The command reads the ZIP, recomputes the full package SHA-256,
requires attesto.truth-package.manifest.json, verifies
every manifest-listed artifact hash, and rejects forbidden archive
paths such as absolute paths, parent traversal, macOS metadata,
workstation paths, and local filesystem references. A changed
events.csv, proofs.json, or
manifest.json must fail verification before the package
can be treated as trustworthy evidence.
curl -X POST https://dashboard.attesto.eu/v1/exports/exp_.../truth-package/verify \
-H "Authorization: Bearer $ATTESTO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"verifierKind": "attesto-cli",
"verifierVersion": "0.4.0",
"accessId": "tpa_...",
"verificationReport": {
"ok": true,
"packageSha256": "hex...",
"manifestSha256": "hex...",
"verifiedArtifacts": 4,
"problems": []
}
}'
Verifier matrix
| Mutation | Expected result |
|---|---|
| Changed payload | Reject: payload hash no longer matches event commitment. |
| Changed sequence number | Reject: stream ordering and head hash break. |
| Removed event | Reject: window inclusion or stream range is incomplete. |
| Inserted event | Reject: sequence, previous hash, or window commitment changes. |
| Stale checkpoint | Reject: checkpoint does not match expected stream progression. |
| Wrong witness signature | Reject: statement signature or key epoch is invalid. |
| Wrong anchor | Reject: anchor commitment does not bind the included epoch. |
| Conflicting checkpoint heads | Reject and report fork evidence. |
Public verification API
Use POST /v2/verify when an online service wants the same
verifier semantics as the CLI.
curl -X POST https://verify.attesto.eu/v2/verify \
-H "Content-Type: application/json" \
--data-binary @attesto-bundle.json
