Chio/Docs

Receipt Format Reference

Every tool invocation, whether allowed or denied, produces a signed receipt. Receipts are the immutable audit trail of the chio protocol. This page documents the complete receipt structure, signing process, and verification procedure.


ChioReceipt

The ChioReceipt is the top-level signed structure. Every field is present in the canonical JSON serialization.

FieldTypeDescription
idstringUnique receipt ID. UUIDv7 (timestamp-prefixed) for temporal ordering
timestampu64Unix timestamp (seconds) when the receipt was created
capability_idstringID of the capability token that was exercised or presented
tool_serverstringTool server that handled the invocation
tool_namestringTool that was invoked or attempted
actionToolCallActionThe tool call action that was evaluated (parameters + hash)
decisionDecisionThe kernel's verdict on this tool call
content_hashstringSHA-256 hash of the evaluated content
policy_hashstringSHA-256 hash of the policy that was applied
evidenceGuardEvidence[]Per-guard evidence collected during evaluation (omitted when empty)
metadataJSON (optional)Optional receipt metadata for financial, governed-transaction, or runtime-assurance details
trust_levelTrustLevelStrength of kernel mediation that produced this receipt. Defaults to Mediated; older receipts omitting this field deserialize to Mediated for backward compatibility
tenant_idstring (optional)Tenant identifier for multi-tenant deployments, derived from the authenticated session (never from caller-provided fields). Omitted from the wire when unset. Part of the signed body, so verifiers computing canonical bytes without this field will fail on multi-tenant deployments
kernel_keyPublicKey (hex)The kernel's Ed25519 public key (for verification without out-of-band lookup)
algorithmSigningAlgorithm (optional)Signing algorithm used for signature. Absent means Ed25519 (backward compatibility). Informational only: verification dispatches off the self-describing signature encoding
signatureSignature (hex)Ed25519 signature over canonical JSON of all fields above

Receipt body vs. signed receipt

The receipt body contains every field except signature. The body is serialized to canonical JSON (RFC 8785), and those bytes are signed directly with the kernel's Ed25519 private key to produce the signature field. Ed25519 hashes internally as part of EdDSA; there is no separate SHA-256 pre-hash.

Decision

The Decision enum represents the kernel's verdict. It is serialized as a tagged union with a verdict discriminator field.

VariantPayloadDescription
allownoneThe tool call was allowed and executed
denyreason (string), guard (string)The tool call was denied. Includes the human-readable reason and the guard that triggered the denial
cancelledreason (string)The tool call was interrupted by explicit cancellation
incompletereason (string)The tool call did not reach a complete terminal result

JSON Serialization

allow
{
  "verdict": "allow"
}
deny
{
  "verdict": "deny",
  "reason": "path matches forbidden pattern **/.env",
  "guard": "forbidden-path"
}
cancelled
{
  "verdict": "cancelled",
  "reason": "user cancelled the operation"
}
incomplete
{
  "verdict": "incomplete",
  "reason": "tool server did not respond within timeout"
}

ToolCallAction

Describes the tool call that was evaluated. Contains the raw parameters and their canonical hash for integrity verification.

FieldTypeDescription
parametersJSON valueThe parameters that were passed to the tool (or attempted)
parameter_hashstringSHA-256 hash of the canonical JSON of parameters

The parameter_hash is computed by serializing parameters to canonical JSON (RFC 8785), then computing the SHA-256 hex digest. This allows verifiers to confirm that parameters were not modified after receipt creation.

json
{
  "parameters": {
    "path": "./workspace/README.md"
  },
  "parameter_hash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
}

GuardEvidence

Evidence from a single guard's evaluation. The evidence array contains one entry per guard that was evaluated.

FieldTypeDescription
guard_namestringName of the guard (e.g. forbidden-path)
verdictbooltrue if the guard passed, false if it denied
detailsstring (optional)Optional details about the guard's decision
json
[
  { "guard_name": "forbidden-path", "verdict": true },
  { "guard_name": "path-allowlist", "verdict": true },
  { "guard_name": "shell-command", "verdict": true },
  { "guard_name": "egress-allowlist", "verdict": true },
  { "guard_name": "mcp-tool", "verdict": true },
  { "guard_name": "secret-leak", "verdict": true },
  { "guard_name": "patch-integrity", "verdict": true },
  {
    "guard_name": "forbidden-path",
    "verdict": false,
    "details": "path matches forbidden pattern **/.env"
  }
]

Financial Metadata

For tool calls governed by monetary grants, the metadata field includes a financial key with detailed cost and budget information.

FieldTypeDescription
grant_indexu32Index of the matching grant in the capability token's scope
cost_chargedu64Cost charged in currency minor units (e.g. cents for USD)
currencystringISO 4217 currency code (e.g. USD)
budget_remainingu64Remaining budget after this charge, in minor units
budget_totalu64Total budget for this grant, in minor units
delegation_depthu32Depth of the delegation chain at invocation time
root_budget_holderstringIdentifier of the root budget holder in the delegation chain
payment_referencestring (optional)Payment reference for external settlement systems
settlement_statusSettlementStatusNotApplicable, Pending, Settled, or Failed
cost_breakdownJSON (optional)Optional itemized cost decomposition reported by the tool (e.g. input tokens, output tokens, fixed fee)
oracle_evidenceOracleConversionEvidence (optional)Rate evidence for cross-currency conversions
attempted_costu64 (optional)Cost that was attempted but denied (populated on denials that pre-charged)

OracleConversionEvidence

Evidence for FX conversions when cost_charged is settled in a currency different from the grant currency.

FieldTypeDescription
from_currencystringISO 4217 source currency
to_currencystringISO 4217 target currency
rate_numeratoru64Rate numerator (target units per source unit)
rate_denominatoru64Rate denominator
margin_bpsu32Applied margin in basis points
oracle_sourcestringIdentifier of the rate oracle
rate_timestampu64Unix seconds when the rate was observed

Signing Process

The receipt signing process is deterministic and reproducible. Any party with the receipt body can verify the signature.

  1. Construct the receipt body. All fields except signature.
  2. Serialize to canonical JSON. Use RFC 8785 JSON Canonicalization Scheme (JCS): keys sorted lexicographically, no whitespace, deterministic number formatting.
  3. Sign with Ed25519. Sign the canonical JSON bytes directly with the kernel's Ed25519 private key. Ed25519 hashes internally as part of EdDSA; there is no separate SHA-256 pre-hash.
  4. Attach signature. Embed the hex-encoded signature and the kernel's public key in the receipt.
rendering…
Receipt body to canonical JSON to Ed25519 signature over those bytes. Deterministic encoding is what lets any verifier reproduce the exact bytes the kernel signed.

Canonical JSON is required

Standard JSON serialization is not deterministic: key order, whitespace, and number formatting may vary between implementations. chio uses RFC 8785 canonical JSON to ensure all implementations produce identical bytes for the same receipt body.

Verification

Receipt verification can be performed by any party with no additional context. The receipt is self-contained.

  1. Extract the body. Take every field except signature.
  2. Re-serialize to canonical JSON. Apply the same RFC 8785 process used during signing.
  3. Verify Ed25519 signature. Verify the signature against the canonical JSON bytes directly using the kernel_key. Ed25519-verify operates on the bytes, not on a separate SHA-256 pre-hash.
  4. Verify parameter hash. Recompute the SHA-256 over RFC 8785 canonical JSON of action.parameters and compare with action.parameter_hash.
verify-receipt.ts
import {
  verifyReceipt,
  parseReceiptJson,
} from "@chio-protocol/sdk/invariants";

// Parse the receipt from JSON
const receipt = parseReceiptJson(receiptJsonString);

// Verify signature and parameter hash
const result = await verifyReceipt(receipt);

if (result.signatureValid && result.parameterHashValid) {
  console.log("Receipt is valid");
} else {
  console.error("Receipt verification failed", result);
}
verify-with-cli
# Verify using openssl (manual)
# 1. Extract body (all fields except "signature")
# 2. Serialize to canonical JSON
# 3. Verify Ed25519 signature against kernel_key

# Or use the SDK:
$ node -e "
  const { verifyReceiptJson } = require('@chio-protocol/sdk/invariants');
  const fs = require('fs');
  const receipt = fs.readFileSync('receipt.json', 'utf8');
  verifyReceiptJson(receipt).then(r => console.log(r));
"

Complete JSON Example

receipt.json
{
  "id": "019076a3-4b5c-7d8e-9f01-234567890abc",
  "timestamp": 1744537862,
  "capability_id": "cap_7f3a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7de91d",
  "tool_server": "srv-files",
  "tool_name": "read_file",
  "action": {
    "parameters": {
      "path": "./workspace/README.md"
    },
    "parameter_hash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
  },
  "decision": {
    "verdict": "allow"
  },
  "content_hash": "d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8",
  "policy_hash": "b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6",
  "evidence": [
    { "guard_name": "forbidden-path", "verdict": true },
    { "guard_name": "path-allowlist", "verdict": true },
    { "guard_name": "shell-command", "verdict": true },
    { "guard_name": "egress-allowlist", "verdict": true },
    { "guard_name": "mcp-tool", "verdict": true },
    { "guard_name": "secret-leak", "verdict": true },
    { "guard_name": "patch-integrity", "verdict": true }
  ],
  "metadata": {
    "financial": {
      "grant_index": 0,
      "cost_charged": 1,
      "currency": "USD",
      "budget_remaining": 999,
      "budget_total": 1000,
      "delegation_depth": 0,
      "root_budget_holder": "ca-prod-01",
      "settlement_status": "Settled",
      "cost_breakdown": {
        "base": 1
      }
    }
  },
  "kernel_key": "9c7b3f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e",
  "signature": "e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6"
}

Deny Receipt Example

deny-receipt.json
{
  "id": "019076a3-5c6d-7e8f-0a12-345678901bcd",
  "timestamp": 1744537863,
  "capability_id": "cap_7f3a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7de91d",
  "tool_server": "srv-files",
  "tool_name": "read_file",
  "action": {
    "parameters": {
      "path": "./workspace/.env"
    },
    "parameter_hash": "f0e1d2c3b4a5968778695a4b3c2d1e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d"
  },
  "decision": {
    "verdict": "deny",
    "reason": "path matches forbidden pattern **/.env",
    "guard": "forbidden-path"
  },
  "content_hash": "c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5",
  "policy_hash": "b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6",
  "evidence": [
    {
      "guard_name": "forbidden-path",
      "verdict": false,
      "details": "path matches forbidden pattern **/.env"
    }
  ],
  "kernel_key": "9c7b3f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e",
  "signature": "d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6"
}

Receipt Querying

Receipts can be queried from the receipt store using filters. The CLI and SDK both support the same filter set:

FilterTypeDescription
capabilitystringFilter by capability ID
tool_serverstringFilter by tool server ID
tool_namestringFilter by tool name
outcomestringFilter by decision: allow, deny, cancelled, incomplete
sinceu64 (Unix seconds)Receipts with timestamp >= value
untilu64 (Unix seconds)Receipts with timestamp <= value
min_costu64Minimum cost in minor units (financial receipts)
max_costu64Maximum cost in minor units (financial receipts)
limitintegerMaximum results per page (default 50)
cursoru64Pagination cursor (seq value to start after)
cli-query
# All denials in the last hour
$ chio receipt list --outcome deny --since $(date -v-1H +%s)

# Financial receipts over $1.00
$ chio receipt list --min-cost 100

# Receipts for a specific capability
$ chio receipt list --capability cap_7f3a...e91d --limit 100

Storage and Merkle-Committed Log

The local receipt store durably persists every signed receipt along with its sequence number. Beyond durable storage, receipts are periodically batched into checkpoints: each checkpoint commits to a Merkle root over the receipts it contains, letting verifiers check inclusion of any single receipt with an O(log n) proof instead of replaying the entire log.

  • Checkpoint. A signed commitment over a Merkle root of a contiguous window of receipts, plus the window's first and last sequence numbers and timestamp.
  • Inclusion proof. For a given receipt, the set of sibling hashes needed to reconstruct the Merkle root. A verifier recomputes the root from the receipt hash and sibling hashes, then matches it against the checkpoint root.
  • Offline verification. With a checkpoint plus an inclusion proof, a third party can confirm a receipt was part of the committed log without access to the full receipt store.

Child Request Receipts (Receipt DAG)

For nested operations (tool calls that spawn child requests), the kernel also produces ChildRequestReceipt records. These track the session, parent request, child request, operation kind, and terminal state, all signed with the same Ed25519 process. Child receipts form a receipt DAG rooted at the originating tool call, linked via parent_request_id.

parent-and-child
// Parent receipt (tool call that spawned a nested operation)
{
  "id": "019076a3-4b5c-7d8e-9f01-234567890abc",
  "tool_name": "run_task",
  "action": { "parameters": { "task": "analyze" }, "parameter_hash": "..." },
  "decision": { "verdict": "allow" },
  ...
}

// Child request receipt linked via parent_request_id
{
  "id": "019076a3-6d7e-7f01-1234-567890abcdef",
  "session_id": "sess_4b8e",
  "parent_request_id": "019076a3-4b5c-7d8e-9f01-234567890abc",
  "request_id": "req_8f1d",
  "operation_kind": "subtool_call",
  "terminal_state": "completed",
  "outcome_hash": "...",
  "policy_hash": "...",
  "kernel_key": "...",
  "signature": "..."
}
FieldTypeDescription
idstringUnique child request receipt ID
timestampu64Unix timestamp (seconds)
session_idstringParent session identifier
parent_request_idstringID of the parent tool call request
request_idstringID of this child request
operation_kindenumType of operation performed
terminal_stateenumFinal state of the child operation
outcome_hashstringSHA-256 hash of the operation outcome
policy_hashstringSHA-256 hash of the policy applied
kernel_keyPublicKeyKernel's Ed25519 public key
signatureSignatureEd25519 signature over canonical JSON of body