Verifiable Evidence
Export the kernel’s signed records so another operator can check them from the bytes, and know what each check proves.
On this page
Another operator ran work on your behalf. Its logs say every call was authorized and every result was delivered. Those logs are the operator’s own account, and you cannot inspect its running kernel. You need records you can check from the exported bytes.
Chio turns governed execution into that kind of evidence. An operator exports receipts, capability lineage, and checkpoint proofs; a recipient checks them without access to the producer’s kernel. That supports cross-operator audits, swarm handoffs, and markets for agent work.
Verification checks byte integrity, signatures, and receipt inclusion in committed batches. Which signers and checkpoints to trust remains the recipient’s decision, and a valid signature does not establish the truth of an external event the kernel could not observe.
A decision becomes evidence in stages
Evidence accumulates before anyone exports it. The kernel signs a receipt for every call it evaluates, refusals included, over the canonical JSON of the receipt body, and appends it to the receipt store. Every hundred receipts by default, a background signer commits the batch to a Merkle root and signs a checkpoint whose body carries the hash of the checkpoint before it. One kernel key signs both, and each signed body carries its public half.
Export copies the records into a directory with a manifest of per-file hashes. A recipient verifies them without access to the producer’s kernel. Receipt checks compare the id with the body and verify the signature. Checkpoint checks establish batch membership and chain continuity. Package checks detect files changed since export.
A governed call becomes evidence in stages
A signed receipt, a retained record, a signed checkpoint, an optional outside commitment, an exported package, and an offline check. Each stage adds something a verifier can check from bytes alone. Verifiable evidence.
checkpoint.rs:139/// A signed kernel checkpoint statement.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct KernelCheckpoint {
/// The signed body.
pub body: KernelCheckpointBody,
/// Ed25519 signature over canonical JSON of `body`.
pub signature: Signature,
}
Independent commitments and signer selection sit outside the producer’s control. A commitment held by an independent party or an anchor backend is optional, and it is what lets a recipient notice a history the producer has re-signed; retain a commitment outside the producer compares the backends. The trusted signers belong to the recipient: a package names the key that signed it, never whether to believe that key.
Export a package, then verify it
After Quickstart part 3, the pricing project’s history holds 61 signed decisions from two kernels: yours and your partner’s. You commit the pending receipts to a checkpoint and export the history for your auditor. chio evidence export writes the selected receipts, the capability lineage, the checkpoint chain and its transparency records, the inclusion proofs, the retention window, and a README into one directory, alongside a manifest of per-file hashes. --require-proofs refuses the export if any selected receipt lacks checkpoint coverage.
chio receipt checkpoint create
chio evidence export --admin-all --require-proofs --output ./larkfield-evidencecheckpoint 2 receipts 41 to 61, root 9d2e…41a7, signed by 4f1c…a2e9 exported 61 receipts from 2 kernels, 2 checkpoints, 61 inclusion proofs package ./larkfield-evidence, 13 files listed in manifest.json
The auditor receives the directory and the two partner cards. It pins each kernel key itself, from the cards, so trust never comes from the package it is checking. chio evidence verify then reads the directory back, checks the file hashes and the carried signatures against the pinned keys, and verifies every inclusion proof against its checkpoint’s root, with no access to either kernel.
chio trust pin receipt-kernel ./larkfield.card
chio trust pin receipt-kernel ./halden.card
chio evidence verify --input ./larkfield-evidencepinned larkfield receipt-kernel ed25519:4f1c…a2e9 pinned halden receipt-kernel ed25519:9b07…d31c file ~/.chio/trust.toml verified 61 receipts from kernels larkfield and halden, 2 checkpoints proofs 61 of 61 receipts included in a signed checkpoint trust ~/.chio/trust.toml
Now change one byte. Copying the package, appending a byte to receipts.ndjson, and running the verifier again produces a refusal and exit 1, naming the file whose bytes differ from the manifest. Editing an exported receipt breaks the manifest hash of the file that holds it in the same way.
cp -R larkfield-evidence tampered
printf '\n' >> tampered/receipts.ndjson
chio evidence verify --input ./tamperederror[CHIO-ATTEST-PROVENANCE-MISSING]: evidence package file hash mismatch for receipts.ndjson help: receipts.ndjson changed after the package was exported; verify the package as exported, or export it again code: urn:chio:error:attest:provenance-missing docs: https://chio.computer/docs/reference/errors#error-attest-provenance-missing
The manifest check detects local tampering with the package; the pinned keys decide whose signatures count. A recipient can repeat the carried signature and inclusion checks from the exported bytes, then authorize the signers and authenticate the expected checkpoints separately before using the result as evidence for a cross-operator decision.
Checkpoints commit to batches and prior checkpoints
The kernel batches pending receipts and commits each batch into a Merkle tree, the 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.
The package exported above carries two such checkpoints. The second commits receipts 41 to 61 and names the hash of the first, so the auditor can check the whole history as one chain.
every batch root matches its signed body.
In Rust · checkpoint.rs:10115 lines
pub struct KernelCheckpointBody {
/// First receipt seq in this batch.
pub batch_start_seq: u64,
/// Last receipt seq in this batch.
pub batch_end_seq: u64,
/// Number of leaves in the Merkle tree.
pub tree_size: usize,
/// Root from MerkleTree::from_leaves.
pub merkle_root: Hash,
// … issued_at, kernel_key
/// Hash of the immediately preceding checkpoint body when this checkpoint extends a prior batch.
// … serde attributes
pub previous_checkpoint_sha256: Option<String>,
// … chain_root (absent on v1 checkpoints)
}
merkle.rs; nothing here is signed. A changed receipt conflicts with its batch root, and a re-signed history conflicts only with a commitment retained or authenticated outside the producer.A changed receipt therefore conflicts with its batch root, and through the chained hashes with every checkpoint after it. A producer that re-signs the later checkpoints can make its own chain consistent again. The conflict becomes visible only against a commitment held outside the producer: a recipient detects it by retaining or independently authenticating the expected commitments.
Checkpoint body fields
Checkpoint body
Each field belongs to the signed checkpoint body.
| 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 Merkle |
issued_at | u64 | Unix seconds when the checkpoint was issued |
kernel_key | PublicKey | The kernel signing key that the signature verifies against |
previous_ | 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- |
The kernel can also produce a proof for one receipt. 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 that one receipt was in the tree without shipping the log. Receipts draws that path and covers the fields inside a single receipt.
Choose the verification operation
Use chio evidence verify to check an exported package. A selected export can carry inclusion proofs for only the requested receipts, and verifying those paths does not require exporting or reconstructing every other leaf in the batch. Read the verifier’s coverage report alongside its success result: it identifies receipts that carry no inclusion proof.
Replay and live security exports have different inputs
chio replay also attempts to rederive recorded verdicts. Ordinary nonempty positional receipt logs fail closed at that step when the replay path lacks policy, capability, and guard context. A trusted kernel key by itself does not supply that context. The tee mode uses its separate tenant-signed frame format.
# Signature trust alone is insufficient for verdict rederivation.
# A nonempty ordinary receipt log refuses when verdict context is absent.
chio replay ./receipts --trusted-kernel-pubkey ./kernel.pub
# Tenant-signed tee frames use a separate verification path.
chio replay --from-tee ./tee.ndjson --tenant-pubkey ./tenant.pub| Exit | What it includes |
|---|---|
10 | Verdict drift, or missing rederivation context. |
20 | Signature, trust, or root failures. |
30 | A parse error. |
40 | A schema mismatch. |
50 | A redaction mismatch. |
--expect-root asserts the resulting root and --json selects a structured report. The reported location depends on the failure rather than always including both a byte offset and a JSON pointer.
A live chio-siem export recomputes the receipt ID, verifies its signature, and checks the action parameter hash. Its separate trusted kernel set determines whether that signer is authorized. The same distinction between integrity and authority applies to a portable package.
Retain a commitment outside the producer
An outside commitment provides a reference against which a recipient can detect a re-signed history. A checkpoint retained by an independent party gives later verification that reference. Anchoring can provide it as well, but its assurance depends on what the backend verifies. Carrying a transaction identifier is not confirmation of ledger inclusion or finality.
What the anchor backends verify
| Backend | Verification boundary |
|---|---|
| EVM | Checks the proof and reads the configured registry at the RPC endpoint’s latest block. That read relies on the chosen chain, contract, and endpoint. |
| Rekor | Fetches the entry, compares its hash, and checks the signed entry timestamp against pinned keys and freshness requirements. It checks an inclusion proof when one is supplied. |
| Solana | Checks memo content, root agreement, and a nonempty transaction identifier locally. This verifier does not query ledger inclusion or finality. |
| Bitcoin helper | Checks digest and attestation-height metadata. It does not verify inclusion against trusted block headers. |
| OpenTimestamps witness | Advisory-only. This witness verifier refuses load-bearing inclusion verification; it lacks trusted header or calendar commitment evidence. |
Choose an anchor by its verified assurance, retention, and independent trust source. An external commitment strengthens history verification; it does not change what an individual receipt establishes about a tool’s effects.
A label says how a fact was established
Evidence also carries its own provenance. chio-lineage builds a graph of how information and effects flow through a system, and every LineageNode and LineageEdge carries an evidence_class. The class separates caller-supplied claims from kernel-written rows and from independently checked facts.
| Class | What it means |
|---|---|
Asserted | Caller-supplied or imported attributes that this kernel has not signed or independently verified. |
Observed | Rows in the local store written by the kernel runtime. The label does not establish external truth beyond its observation boundary. |
Verified | Independently signed or proof-checked, within the claim and the verifier’s trust assumptions. |
The classes do not promote one another. The proof manifest registers this separation as property P10, report truthfulness, with proof.report_truthfulness_asserted_not_verified and proof.report_truthfulness_observed_not_verified; Formal assurance describes what such a registration covers.
Receipt semantics make a related distinction between authorization decisions, observations, and advice. The signed BoundaryClass must be compatible with the receipt kind: prevention for a mediated decision, detection for a trace observation, and advice for an advisory evaluation. CannotSee exists in the boundary vocabulary but is rejected on signed runtime receipts. The separate TrustLevel label also needs the record’s verification and deployment context. Assurance boundaries and limits lists the accepted pairings and what each can establish.
Check a bundle before relying on it
A receipt bundle can be inspected offline. Before paying, a buyer checks the included signatures, inclusion proofs, and checkpoint chain against its trust policy. A complete batch lets the buyer reconstruct the root itself. A selected export proves membership only for its checkpointed receipts, so the buyer reads the coverage report before treating the bundle as complete.
The Cognition Market depends on that check: a buyer has to be able to verify the records a seller supplies. Formal assurance covers the formal claims related to policy enforcement.
Follow the evidence further
TrustLevel and BoundaryClass value, and what each can establish.On-chain settlementWhere anchored checkpoints meet on-chain payment.Receipt query APIPull receipts and inclusion proofs programmatically.SIEM exportStream independently re-verified rows into a live security pipeline.