LearnEvidence and Assurance
Verifiable Evidence
A verifier recomputes the receipt log from stored bytes, including signatures and Merkle roots.
Merkle receipt log
The kernel batches pending receipts and commits the batch into a Merkle tree, the same construction Certificate Transparency logs use under RFC 6962. Each commit produces a KernelCheckpoint: a KernelCheckpointBody and an Ed25519 signature over the canonical JSON of that body. The body carries previous_checkpoint_sha256, the hash of the preceding body, so changing a historical receipt requires recomputing every checkpoint after it.
| Field | Type | What it holds |
|---|---|---|
schema | String | Schema identifier for new checkpoint issuance |
checkpoint_seq | u64 | Monotonic checkpoint counter |
batch_start_seq | u64 | First receipt seq in this batch |
batch_end_seq | u64 | Last receipt seq in this batch |
tree_size | usize | Number of leaves in the Merkle tree |
merkle_root | Hash | Root from MerkleTree::from_leaves |
issued_at | u64 | Unix seconds when the checkpoint was issued |
kernel_key | PublicKey | The kernel signing key that the signature verifies against |
previous_checkpoint_sha256 | Option<String> | Hash of the immediately preceding checkpoint body, when this checkpoint extends a prior batch |
chain_root | Option<Hash> | RFC 6962 root over the checkpoint-chain leaves that consistency proofs verify against; absent on v1 checkpoints and on detached v2 checkpoints built without chain context |
crates/kernel/chio-kernel/src/checkpoint.rs:99-146at fe56570The kernel can also produce a per-receipt inclusion proof. A ReceiptInclusionProof names the checkpoint_seq it is drawn against, the receipt_seq and leaf_index of the receipt, the merkle_root it proves against, and the audit path. Its verify() takes the receipt's canonical bytes and an expected root, so a holder can show one receipt was in the tree without shipping the log.
For the fields inside one receipt itself (the signature, the trust and boundary tags, the call it attests to) see Receipts. This page covers how batches of receipts are chained and verified.
External anchoring
A checkpoint hash chain makes edits to an old receipt visible during verification. It does not prevent an operator from replacing an entire chain stored on its own infrastructure. chio-anchor records a checkpoint root through infrastructure outside that operator: Bitcoin, Solana, and EVM backends, plus Rekor and OpenTimestamps witnesses.
An anchored root records its existence at a particular time. It adds no fields to an individual receipt, but a different history will conflict with prior anchors.
Offline verification
chio replay reads a directory of signed receipts or an NDJSON tee stream, re-verifies every signature, recomputes the Merkle root incrementally, and reports the first divergence by byte offset and JSON pointer. The log path is positional; --from-tee declares a tee stream and takes the tenant public key the frames are signed under. Its exit code names the failure: 10 for verdict drift, 20 for a signature mismatch, 30 for a parse error, 40 for a schema mismatch, 50 for a redaction mismatch.
# a receipt-log directory or an NDJSON file
chio replay ./receipts --trusted-kernel-pubkey ./kernel.pub
# a tee stream, checked against the tenant key its frames carry
chio replay --from-tee ./tee.ndjson --tenant-pubkey ./tenant.pubPass --expect-root <HEX> to assert the recomputed root, and --json for a structured report instead of human text.
chio-siem applies the same arithmetic to a live export. Building a SiemEvent from a receipt recomputes the receipt id, verifies the Ed25519 signature against the embedded kernel key, and re-derives the action parameter hash; a row counts as authoritative only when all three agree, and as authorized only when its signer is also in the trusted-kernel key set.
Export a package, then verify it
chio evidence export writes the selected receipts, the capability lineage, the checkpoint chain and its transparency records, the retention window, and a README into one directory, alongside a manifest of per-file hashes. Pass --policy-file and the policy bytes are copied in and hashed with the rest. chio evidence verify reads that directory back and recomputes them.
$ chio --receipt-db .chio/receipts.db evidence export --admin-all --output ./evidence
$ ls evidenceREADME.txt capability-lineage.ndjson checkpoint-consistency-proofs.ndjson checkpoint-equivocations.ndjson checkpoint-publications.ndjson checkpoint-witnesses.ndjson checkpoints.ndjson child-receipts.ndjson inclusion-proofs.ndjson manifest.json query.json receipts.ndjson retention.json
$ chio evidence verify --input ./evidenceevidence package verified tool_receipts: 2 child_receipts: 0 checkpoints: 0 checkpoint_publications: 0 checkpoint_witnesses: 0 checkpoint_consistency_proofs: 0 checkpoint_equivocations: 0 capability_lineage: 2 inclusion_proofs: 0 uncheckpointed_receipts: 2 authorized_receipts: 1 trace_observations: 0 advisory_evaluations: 0 verified_files: 12 child_receipt_scope: FullQueryWindow transparency_preview_logs: 0 publication_state: transparency_preview
The counts are the claim. Editing one exported receipt breaks the manifest hash for the file that holds it. Copying the package, appending a byte to receipts.ndjson, and re-running the verifier produces a refusal and exit 1. It names the file, so a reader knows where the history was rewritten.
$ cp -R evidence evidence-tampered
$ printf '\n' >> evidence-tampered/receipts.ndjson
$ chio evidence verify --input ./evidence-tamperederror [urn:chio:error:attest:provenance-missing]: evidence package file hash mismatch for receipts.ndjson
context: {"domain":"attest","severity":"error","stability":"unstable","string_code":"CHIO-ATTEST-PROVENANCE-MISSING"}
suggested fix: Regenerate the evidence bundle and include provenance before submitting the operation.Verify from recorded bytes
Evidence classes
chio-lineage builds a provenance graph over how information and effects flow through a system. Every LineageNode and every LineageEdge carries an evidence_class, which separates caller-supplied claims from kernel-written rows and from independently checked facts.
| Tag | What it means |
|---|---|
Asserted | Caller-supplied or imported attributes that this kernel has not signed or independently verified |
Observed | Local kernel runtime truth: rows in this store written by the kernel itself |
Verified | Independently signed or proof-checked |
Receipts record related limits in two fields. TrustLevel (Mediated / Verified / Advisory) records how the kernel mediated the call and its effect. BoundaryClass (Prevent / DetectOnly / AdvisoryOnly / CannotSee) records what the runtime could see, independent of whether it acted. Definitions for both are in Assurance Boundaries & Limits; the fields state the runtime's authority and visibility for the recorded call.
Using receipt bundles
A receipt bundle can be recomputed offline. Before paying, a buyer replays the included signatures, inclusion proofs, and checkpoint chain.
The Cognition Market depends on that check: a buyer has to be able to verify the records a seller supplies. See Formal Assurance for the formal claims related to policy enforcement.
Next steps
- Receipts · the object this log is made of: fields, signature, and the trust and boundary tags a single receipt carries
- Formal Assurance · how recompute-based verification extends to the guarantees behind policy enforcement
- Assurance Boundaries & Limits · full definitions for every
TrustLevelandBoundaryClassvalue - On-Chain Settlement · where anchored checkpoints meet on-chain payment
- Receipt Query API · pulling receipts and inclusion proofs programmatically
- SIEM Export · streaming independently re-verified rows into a live security pipeline