Chio/Docs

ReferenceSpec

Receipt Format Reference

The ChioReceipt fields, signing process, and verification procedure for mediated tool invocations.


ChioReceipt

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

FieldTypeDescription
idstringContent-addressed receipt ID: the SHA-256 hex digest of the canonical JSON (RFC 8785) of the receipt's identity-defining fields (ChioReceiptIdInput — every field except id, signature, bbs_signature, and algorithm). The digest identifies the receipt; it is neither caller-assigned nor time-ordered.
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)
decisionDecision (optional)The kernel's verdict on this tool call. Present only on mediated_decision receipts (the prevent + mediated case). trace_observation and advisory_evaluation receipts omit it entirely
receipt_kindReceiptKindSigned semantic class of the receipt: mediated_decision, trace_observation, or advisory_evaluation. Determines whether the receipt is authorization or evidence
boundary_classBoundaryClassSigned runtime boundary: prevent, detect_only, advisory_only, or cannot_see. A signed receipt never carries cannot_see
observation_outcomeObservationOutcome (optional)observed, evaluated, or dropped. Carried only on trace_observation and advisory_evaluation receipts; omitted on mediated decisions
tool_originToolOriginWhere the tool effect executed relative to the kernel: caller_executed, host_executed_provider_reported, or host_executed_unmediated
redaction_modeRedactionModeRedaction applied to signed or exported receipt details: none, summary, or redacted
actor_chainActorRef[]Signed actor-attribution chain (each entry an actor_id with optional actor_kind). Omitted from the wire when empty
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: mediated, verified, or advisory. Bound to receipt_kind: mediated_decision receipts require mediated, trace_observation requires verified, and advisory_evaluation requires advisory. Older receipts omitting this field deserialize to mediated
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
bbs_projection_versionstring (optional)Selective-disclosure projection version, fixed at chio.bbs-projection.receipt.v1. Present together with bbs_signature
kernel_keyPublicKey (hex)The kernel's verifying public key, in the same algorithm-aware form used across v1: bare 64-hex for Ed25519, p256:<130-hex> for SEC1 P-256, or p384:<194-hex> for SEC1 P-384. Lets a verifier check the signature without an out-of-band key lookup
bbs_signatureBbsReceiptSignature (optional)BBS selective-disclosure material over this receipt. When present it is covered by the authoritative signature and travels with bbs_projection_version
algorithmSigningAlgorithm (optional)Envelope hint for signature (ed25519, p256, or p384). Absent means Ed25519. Informational only: verification dispatches off the self-describing signature encoding, not this field
signatureSignature (hex)Algorithm-aware signature over the canonical JSON of ChioReceiptSigningBody ({ id, body, bbs_signature? }). The schema regex is ^([0-9a-f]{128}|p256:[0-9a-f]+|p384:[0-9a-f]+)$: bare 128-hex for Ed25519, p256:<DER hex> for P-256, or p384:<DER hex> for P-384

Receipt body vs. signed receipt

The kernel signs the canonical JSON (RFC 8785) of a ChioReceiptSigningBody wrapper: the content-addressed id, the identity-defining ChioReceiptIdInput fields, and the optional bbs_signature. The default algorithm is Ed25519, which hashes internally as part of EdDSA (no separate SHA-256 pre-hash); P-256 and P-384 sign the same canonical bytes and are distinguished by the self-describing signature encoding.

Only mediated decisions authorize

Only a mediated_decision receipt with boundary_class = prevent and an Allow decision may ever be displayed or exported as authorization. trace_observation and advisory_evaluation receipts are evidence, never authorization.

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_statusSettlementStatusSerialized snake_case: not_applicable, 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 at authorization)

OracleConversionEvidence

Evidence for cross-currency conversions when the cost was denominated in a currency different from the grant currency. The struct is deny_unknown_fields: a consumer parsing metadata.financial.oracle_evidence must expect exactly this field set.

FieldTypeDescription
schemastringFixed schema identifier, chio.oracle-conversion-evidence.v1
basestringBase currency of the quoted rate
quotestringQuote currency of the quoted rate
authoritystringRate authority that issued the evidence
rate_numeratoru64Numerator of the conversion rate
rate_denominatoru64Denominator of the conversion rate
sourcestringIdentifier of the rate source
feed_addressstringAddress of the price feed the rate was read from
updated_atu64Unix seconds when the source last published the rate
max_age_secondsu64Maximum accepted age of the rate, in seconds
cache_age_secondsu64Age of the cached rate at conversion time, in seconds
converted_cost_unitsu64Cost after conversion, in minor units of grant_currency
original_cost_unitsu64Cost before conversion, in minor units of original_currency
original_currencystringCurrency the cost was originally denominated in
grant_currencystringCurrency of the grant the cost was converted into
oracle_public_keyPublicKey (optional)Verifying key of the oracle that signed the rate
signatureSignature (optional)Oracle signature over the evidence

Governed Transaction Metadata

The flat financial block above is retained for backward compatibility. Governed receipts also carry a governed_transaction block under metadata, holding the intent identifiers plus optional approval, commerce, metering, runtime-assurance, and call-chain evidence bound into the request.

FieldTypeDescription
intent_idstringGoverned transaction intent identifier
intent_hashstringCanonical intent hash used for approval-token binding
purposestringHuman- or policy-readable purpose of the intent
server_idstringTarget tool server from the intent
tool_namestringTarget tool from the intent
max_amountMonetaryAmount (optional)Explicit spend bound carried on the intent
commerceobject (optional)Seller-scoped commerce approval: seller, shared_payment_token_id
metered_billingobject (optional)Settlement mode, the pre-execution metered quote, and optional post-execution usage evidence
approvalobject (optional)Approval evidence: token_id, approver_key, approved
runtime_assuranceobject (optional)Accepted runtime-assurance tier and the verifier that accepted the upstream attestation evidence, after any configured verifier trust-policy rebinding
call_chainobject (optional)Delegated call-chain provenance bound through the governed intent hash. Records the strongest projection the kernel will sign; an original caller assertion is preserved separately under assertedContext and must not be collapsed into verified truth
autonomyobject (optional)Requested autonomy tier and optional signed delegation-bond id
economic_authorizationEconomicAuthorizationReceiptMetadata (optional)Versioned economic envelope (see below)

economic_authorization

A versioned typed envelope that consolidates budget, meter, rail, and settlement truth into separate sub-blocks. It is additive: the compatibility financial, commerce, metered_billing, approval, runtime_assurance, call_chain, and autonomy fields remain intact beside it.

FieldTypeDescription
versionenumEnvelope version. Serialized v1
economic_modeenumbudget_only, prepaid_fixed, hold_capture, metered_hold_capture, or external_dispatch
payerobjectPayer binding: party_id, funding_source_ref, optional custody_provider, optional obligor_ref
merchantobjectMerchant binding: merchant_id, optional merchant_of_record, optional order_ref
payeeobjectPayee binding: beneficiary_id, settlement_destination_ref
railobjectSettlement rail: kind, asset, optional network, facilitator, contract_or_account_ref
amount_boundsobjectapproved_max, optional hold_amount, and settlement_cap, each a MonetaryAmount
pricing_basisobject (optional)Quote and tariff binding: optional quote_hash, tariff_hash, quote_expiry
meteringobject (optional)Meter binding: provider, meter_profile_hash, optional max_billable_units, billing_unit
liability_refsobject (optional)Optional bond_id, policy_id, indemnity_ref, dispute_policy_ref
budgetobjectBudget truth: grant_index, cost_charged, currency, budget_remaining, budget_total, delegation_depth, root_budget_holder, optional attempted_cost
settlementobjectSettlement truth: settlement_status

Signing Process

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

  1. Validate receipt semantics. Reject any body whose receipt_kind, boundary_class, decision, and trust_level combination is invalid (for example a mediated_decision without a decision).
  2. Bind the signing nonce. Before the id is computed, write the pre-binding id into metadata["chio_receipt_signing_nonce"]. Because metadata is part of ChioReceiptIdInput, the nonce is covered by both the receipt id and the signature. This is a normative step of the receipt-id algorithm, not an incidental detail.
  3. Compute the content-addressed id. id = H(canonical_jcs(ChioReceiptIdInput)) over the now-nonce-bound body.
  4. Sign the signing body. Serialize ChioReceiptSigningBody ({ id, body, bbs_signature? }) to RFC 8785 canonical JSON — keys sorted lexicographically, no whitespace, deterministic number formatting — and sign those bytes with the kernel's signing key (Ed25519 by default; P-256 or P-384 when configured).
  5. Attach signature. Embed the algorithm-aware signature and the kernel's public key in the receipt.
rendering…
Nonce binding, content-addressed id, then a signature over the canonical ChioReceiptSigningBody. Deterministic encoding is what lets any verifier reproduce the exact bytes the kernel signed.

WYSIWYS: the signer recomputes content_hash

chio_kernel_core::receipts::sign_receipt recomputes content_hash from the canonical content preimage inside its own trust boundary and MUST NOT trust a caller-asserted content_hash. The recompute runs before the kernel-key check and before any signing work, so a mismatch fails closed with ContentHashMismatch and can never produce a signature. This closes the render-A / sign-B forgery. The one audited exception is sign_receipt_relaying_trusted_body, a trusted relay reserved for FFI and WASM transport adapters.

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. Re-validate semantics. Confirm the receipt_kind / boundary_class / decision / trust_level combination is well-formed. A malformed combination fails verification.
  2. Re-derive the id. Recompute H(canonical_jcs(ChioReceiptIdInput)) and confirm it equals id. A mismatch means the identity-defining fields were altered.
  3. Verify the signature. Re-serialize ChioReceiptSigningBody to RFC 8785 canonical JSON and verify signature against those bytes using kernel_key. The verifier dispatches off the self-describing signature encoding (Ed25519 / P-256 / P-384), not the algorithm hint.
  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": "7c1e5a2b9d34f60e8a1b4c7d0e3f6a9b2c5d8e1f4a7b0c3d6e9f2a5b8c1d4e70",
  "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"
  },
  "receipt_kind": "mediated_decision",
  "boundary_class": "prevent",
  "tool_origin": "caller_executed",
  "redaction_mode": "none",
  "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
      }
    }
  },
  "trust_level": "mediated",
  "kernel_key": "9c7b3f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e",
  "signature": "e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6"
}

Deny Receipt Example

deny-receipt.json
{
  "id": "b8d2f47a06c19e35d7a0b3c6e9f2a5b8c1d4e70f3a6b9c2d5e8f1a4b7c0d3e69",
  "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"
  },
  "receipt_kind": "mediated_decision",
  "boundary_class": "prevent",
  "tool_origin": "caller_executed",
  "redaction_mode": "none",
  "content_hash": "c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5",
  "policy_hash": "b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6",
  "evidence": [
    {
      "guard_name": "forbidden-path",
      "verdict": false,
      "details": "path matches forbidden pattern **/.env"
    }
  ],
  "trust_level": "mediated",
  "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.

Receipt Lineage (Multi-Parent DAG)

Receipts can declare multi-parent lineage so a verifier can order and connect them across kernels. When present, a receipt carries the following signed lineage fields:

FieldTypeDescription
chainIdstringLineage chain this receipt belongs to. Every parent must share the same chainId
parentReceiptIdsstring[]Parent receipt ids, sorted and deduplicated before signing
parentSetHashstringH(canonical(parentReceiptIds)) over the sorted, deduplicated set
dagOrdinalu64Monotonic ordinal within the chain. A child MUST have dagOrdinal > max(parent.dagOrdinal)
{ wallSeconds, logical, kernelId }ReceiptHybridLogicalClockHybrid logical clock triple used for cross-kernel ordering without a single global clock

The verifier rejects a child unless its parent descriptors match the signed parent set, every parent shares the same chainId, and dagOrdinal strictly exceeds every parent's. This rejects cross-kernel cycles without relying on one global clock. This multi-parent lineage is distinct from the ChildRequestReceipt mechanism below; the two can coexist on the same operation.


Child Request Receipts

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 canonical-JSON process. Child receipts link to the originating tool call via parent_request_id. This is a separate mechanism from the multi-parent receipt lineage described above.

parent-and-child
// Parent receipt (tool call that spawned a nested operation)
{
  "id": "a4f0c9d2e5b81736a0c3d6e9f2b5a8c1d4e70f3a6b9c2d5e8f1a4b7c0d3e692f",
  "tool_name": "run_task",
  "action": { "parameters": { "task": "analyze" }, "parameter_hash": "..." },
  "decision": { "verdict": "allow" },
  "receipt_kind": "mediated_decision",
  ...
}

// Child request receipt linked via parent_request_id
{
  "id": "child-4b8e-8f1d",
  "session_id": "sess_4b8e",
  "parent_request_id": "req_2b8e",
  "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
metadataJSON (optional)Optional child-receipt metadata. Omitted from the wire when unset
kernel_keyPublicKeyKernel's verifying public key, in the same algorithm-aware form used across v1 (bare 64-hex Ed25519, p256:<130-hex>, or p384:<194-hex>)
algorithmSigningAlgorithm (optional)Envelope hint for signature (ed25519, p256, or p384). Absent means Ed25519, matching ChioReceipt
signatureSignatureAlgorithm-aware signature over the canonical JSON of the body