Chio/Docs
LOGIN · JOIN

Verifiable Evidence

Export the kernel’s signed records so another operator can check them from the bytes, and know what each check proves.

Concept chio@5f63e6e

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.

Evidence flowChoose a stage.
ProducerRecipientProducerRecipient

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.

In Rust · 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,
}
The stages in one deployment: one kernel key signs receipts and checkpoints, both stay in the receipt store, and the export reads them from there. The outside commitment is optional. The verifier computes integrity and inclusion from bytes, and the recipient pins its trusted signers independently of the package.

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.

Terminal · youbash
chio receipt checkpoint create
chio evidence export --admin-all --require-proofs --output ./larkfield-evidence
Output
checkpoint 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.

Terminal · auditorbash
chio trust pin receipt-kernel ./larkfield.card
chio trust pin receipt-kernel ./halden.card
chio evidence verify --input ./larkfield-evidence
Output
pinned     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.

Terminal · auditorbash
cp -R larkfield-evidence tampered
printf '\n' >> tampered/receipts.ndjson
chio evidence verify --input ./tampered
Output
error[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.

Three checkpoints, each committing to its batch root and to the previous checkpoint bodycheckpoint 1retainprev noneroot a67ca293H 94772e85MTHr1r2r3r4checkpoint 2retainprev 94772e85root 7121bcc3H bd6bc28fMTHr5r6r7r8checkpoint 3retainedprev bd6bc28froot 3259a428H 26aef010= c3MTHr9r10r11r12click a receipt to alter it; mark which checkpoint a verifier retainedthe producer re-signs the later checkpoints
rootk=MTH(batchk),prevk+1=H(bodyk)\htmlClass{role-seal}{\mathrm{root}_k} = \mathrm{MTH}(\htmlClass{role-call}{\mathrm{batch}_k}),\quad \htmlClass{role-seal}{\mathrm{prev}_{k+1}} = H(\mathrm{body}_k)
MTH(batchk)=rootk  for every k\mathrm{MTH}(\htmlClass{role-call}{\mathrm{batch}_k}) = \htmlClass{role-seal}{\mathrm{root}_k}\ \ \text{for every } k
every batch root matches its signed body
Three checkpoints, each committing to its batch root and to the previous checkpoint bodycheckpoint 1retainprev noneroot a67ca293H 94772e85r1r2r3r4checkpoint 2retainprev 94772e85root 7121bcc3H bd6bc28fr5r6r7r8checkpoint 3retainedprev bd6bc28froot 3259a428H 26aef010= c3r9r10r11r12click a receipt; mark a retained checkpointthe producer re-signs the later checkpointsevery batch root matches its signed body

every batch root matches its signed body.

rootk=MTH(batchk)prevk+1=H(bodyk)MTH(batchk)=rootk  for every k\begin{array}{l} \htmlClass{role-seal}{\mathrm{root}_k} = \mathrm{MTH}(\htmlClass{role-call}{\mathrm{batch}_k}) \\ \htmlClass{role-seal}{\mathrm{prev}_{k+1}} = H(\mathrm{body}_k) \\[8pt] \mathrm{MTH}(\htmlClass{role-call}{\mathrm{batch}_k}) = \htmlClass{role-seal}{\mathrm{root}_k}\ \ \text{for every } k \end{array}
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)
}
Receipts and checkpoint bodies reduced to the chained fields, hashed with SHA-256 as in 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.

FieldTypeWhat 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

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.

replay inputs and limitsbash
# 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
ExitWhat it includes
10Verdict drift, or missing rederivation context.
20Signature, trust, or root failures.
30A parse error.
40A schema mismatch.
50A 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
BackendVerification boundary
EVMChecks the proof and reads the configured registry at the RPC endpoint’s latest block. That read relies on the chosen chain, contract, and endpoint.
RekorFetches 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.
SolanaChecks memo content, root agreement, and a nonempty transaction identifier locally. This verifier does not query ledger inclusion or finality.
Bitcoin helperChecks digest and attestation-height metadata. It does not verify inclusion against trusted block headers.
OpenTimestamps witnessAdvisory-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.

ClassWhat it means
AssertedCaller-supplied or imported attributes that this kernel has not signed or independently verified.
ObservedRows in the local store written by the kernel runtime. The label does not establish external truth beyond its observation boundary.
VerifiedIndependently 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