Chio/Docs
LOGIN · JOIN

PlatformInventory & Assumptions

Formal Assurance

Assumptions & TCB

Every formal claim holds only where its assumptions hold. This is the registry of them and where the trusted computing base ends.

Assumptions bound each claim

A proof holds only where its listed assumptions hold. Reducing that set is the only thing that narrows the trusted computing base, and the registry records no reduction so far: every entry in it is live.

The trusted computing base

Chio's TCB is the set of components whose failure can invalidate a formal claim.

The audited assumption registry: audited_crypto, ASSUME-ED25519, ASSUME-SHA256; audited_external, ASSUME-CHAIN-FINALITY; audited_observability, ASSUME-TRACE-OBSERVER; audited_platform, ASSUME-OS-CLOCK, ASSUME-SUBPROCESS-ISOLATION, ASSUME-WASM-ENGINE; audited_serialization, ASSUME-CANONICAL-JSON; audited_service, ASSUME-EXTERNAL-REGISTRIES, ASSUME-FINDING-STATUS-OPERATOR-COMPLETENESS, ASSUME-FINDING-SELLER-TOOL-SERVER; audited_storage, ASSUME-SQLITE-ATOMICITY; audited_transport, ASSUME-TLS, ASSUME-NETWORK-TRANSPORT, ASSUME-GOSSIP-FAIRNESS-PARTITION-BOUNDaudited_crypto · 2ASSUME-ED25519: Ed25519 verification and signing are assumed to satisfy standard unforgeability for trusted public keys.ED25519properties P2 P3 P4ASSUME-SHA256: SHA-256 and Merkle hash collision resistance are assumed for concrete receipt and checkpoint evidence.SHA256properties P4 P7audited_external · 1ASSUME-CHAIN-FINALITY: External chain and oracle finality are assumed only after the configured confirmation/finality policy accepts the evidence.CHAIN-FINALITYproperties P4 P7audited_observability · 1ASSUME-TRACE-OBSERVER: An installed synchronous runtime trace observer is assumed to receive exactly once before finalization every successful revocation commit, completed tool-call revocation admission, and receipt append. Kernel-assigned source sequences, checked revocation subject identities, exact revocation-source identities, and other callback fields are not rewritten before recording, and the recorder runs without calibration mutations. Delivery reordering is reconciled from source sequences; detectable omissions, duplicates, inconsistent kernel depth limits, ambiguous admission-to-receipt joins, unmatched revocation sources, and relevant revocations between admission and receipt append fail closed. This assumption does not assert that any observed kernel decision is safe.TRACE-OBSERVERproperties P2 P4 P10audited_platform · 3ASSUME-OS-CLOCK: The injected clock is assumed to report operator-accepted Unix time within the deployment tolerance.OS-CLOCKproperties P2 P3 P8ASSUME-SUBPROCESS-ISOLATION: Tool-server subprocess isolation and OS process boundaries are assumed for effects outside the pure kernel decision core.SUBPROCESS-ISOLATIONproperties P3 P6ASSUME-WASM-ENGINE: Wasmtime is assumed to enforce its documented i32 return, trap, fuel-metering, memory-limiter, and in-process sandbox semantics for untrusted guest code.WASM-ENGINEproperties P3audited_serialization · 1ASSUME-CANONICAL-JSON: The production canonicalizer is assumed to agree byte-for-byte with the mechanized UTF-8 renderer on Unicode scalar strings, normalized bounded integers, arbitrary finite arrays, and UTF-16-ordered objects. Float rendering and float-bearing compound receipt fields outside that domain remain assumed deterministic and byte-stable.CANONICAL-JSONproperties P4 P7 P10audited_service · 3ASSUME-EXTERNAL-REGISTRIES: Hosted package, certification, DID, and registry services are assumed to return state they have durably accepted or else fail closed.EXTERNAL-REGISTRIESproperties P9 P10ASSUME-FINDING-STATUS-OPERATOR-COMPLETENESS: The qualified cognition-market profile verifies authentic fresh status-feed state but assumes the external status operator inserts every required retraction into that feed.FINDING-STATUS-OPERATOR-COMPLETENESSproperties P4 P7 P10ASSUME-FINDING-SELLER-TOOL-SERVER: The qualified cognition-market profile binds kernel-observed seller output bytes and receipts but assumes the seller tool server performs any claimed effect outside Chio's observation boundary.FINDING-SELLER-TOOL-SERVERproperties P3 P6 P10audited_storage · 1ASSUME-SQLITE-ATOMICITY: SQLite transactions are assumed to provide atomic committed updates for revocation, budget, receipt, and registry state per single-row write. Cross-row crash recovery, ordering, and conservation are not assumed or discharged and remain outside the current formal claim boundary.SQLITE-ATOMICITYproperties P2 P4 P6 P7audited_transport · 3ASSUME-TLS: TLS endpoint authentication and channel confidentiality are assumed for configured remote control and hosted HTTP surfaces.TLSproperties P8 P9ASSUME-NETWORK-TRANSPORT: Network delivery is not assumed reliable, but authenticated messages received by Chio are assumed not to be silently rewritten below TLS or signature checks.NETWORK-TRANSPORTproperties P2 P8 P9ASSUME-GOSSIP-FAIRNESS-PARTITION-BOUND: For a configured bilateral revocation peer set, correct connected peers are assumed to have recurring push or catch-up opportunities governed by weak fairness, local clocks remain within the declared skew bound, and declared partitions heal within the operator-declared partition bound. Loss, duplication, reordering, and invalid frames are modeled rather than assumed away. No finite delivery-step or raw-evaluation bound is assumed.GOSSIP-FAIRNESS-PARTITION-BOUNDproperties P215 assumptions in 8 classes, every id prefixed ASSUME- and every class prefixed audited_a class names what kind of thing is assumed, not how far it is trusted, so the classes carry no order and the figure draws no edges
The audited assumption registry, banded by the class it assigns each entry. The classes name what kind of thing is assumed, so they carry no order and the figure draws no edges between them.
sourceformal/assumptions.toml:23-39at fe56570

The registry and the list below are not the same set. The registry records what the proofs assume and names an id for each, which is what lets a property cite one. The list is wider: rustc and the hardware under it are trusted without a registry entry, because no proof in the tree is stated in terms of them.

  • Cryptographic primitives · The implementations behind ed25519-dalek, sha2, the ecdsa stack for P-256 and P-384, and the canonical-JSON serializer. The proofs treat these symbolically; Chio assumes they satisfy standard unforgeability and collision resistance.
  • Rust compiler · The rustc toolchain is trusted to lower the Rust source faithfully. Aeneas extracts a Lean model from the source-level Rust; the binary that actually runs is what rustc produces.
  • Operating-system primitives · The OS clock is trusted to deliver operator-accepted Unix time within tolerance. Subprocess isolation and OS process boundaries are trusted for effects outside the kernel. SQLite is trusted for per-row write atomicity.
  • Hardware · CPU, memory, and storage are assumed to behave correctly. Chio does not attempt to reason about Rowhammer, voltage glitching, or microarchitectural side channels. The TEE-mode lane (when enabled) reduces the hardware trust set to a specific enclave.
  • TLS stack · Endpoint authentication and channel confidentiality on configured remote control and hosted HTTP surfaces.

The assumptions table

required_assumption_ids in formal/assumptions.toml lists 15 ids, and every one of them has a matching row in the assumptions array. scripts/check-formal-proofs.sh compares the two sets and rejects the tree on any difference in either direction, so an id without a statement stops the gate and so does a statement without an id.

formal/assumptions.toml5-21toml
required_assumption_ids = [
  "ASSUME-ED25519",
  "ASSUME-SHA256",
  "ASSUME-CANONICAL-JSON",
  "ASSUME-OS-CLOCK",
  "ASSUME-SQLITE-ATOMICITY",
  "ASSUME-TLS",
  "ASSUME-NETWORK-TRANSPORT",
  "ASSUME-GOSSIP-FAIRNESS-PARTITION-BOUND",
  "ASSUME-EXTERNAL-REGISTRIES",
  "ASSUME-SUBPROCESS-ISOLATION",
  "ASSUME-CHAIN-FINALITY",
  "ASSUME-TRACE-OBSERVER",
  "ASSUME-WASM-ENGINE",
  "ASSUME-FINDING-STATUS-OPERATOR-COMPLETENESS",
  "ASSUME-FINDING-SELLER-TOOL-SERVER",
]

Each row below carries the id, the statement verbatim from the registry, the property identifiers the row maps to, and a note on what would mitigate the assumption breaking in production. The property column is the row's fourth field: the properties whose evidence rests on the assumption, not properties the assumption discharges. Only the mitigation column is editorial; the other three are rendered from the registry.

AssumptionStatementPropertiesMitigation if violated
ASSUME-ED25519Ed25519 verification and signing are assumed to satisfy standard unforgeability for trusted public keys.P2, P3, P4Rotate the trusted-key set immediately, revoke affected lineages, and move the lane to ECDSA P-384 through SigningAlgorithm.
ASSUME-SHA256SHA-256 and Merkle hash collision resistance are assumed for concrete receipt and checkpoint evidence.P4, P7Re-anchor the affected receipt log under a different hash and treat every post-compromise receipt as unverified.
ASSUME-CANONICAL-JSONThe production canonicalizer is assumed to agree byte-for-byte with the mechanized UTF-8 renderer on Unicode scalar strings, normalized bounded integers, arbitrary finite arrays, and UTF-16-ordered objects. Float rendering and float-bearing compound receipt fields outside that domain remain assumed deterministic and byte-stable.P4, P7, P10The differential tests in formal/diff-tests/tests/canonical_json_diff.rs compare the production canonicalizer against a separately derived implementation, so a divergence inside the mechanized domain shows up there. Outside that domain, pin the canonicalizer version and re-sign.
ASSUME-OS-CLOCKThe injected clock is assumed to report operator-accepted Unix time within the deployment tolerance.P2, P3, P8Sidecar to a trusted time source, lower the deployment tolerance, or fail closed when the injected clock disagrees with the configured oracle.
ASSUME-SQLITE-ATOMICITYSQLite transactions are assumed to provide atomic committed updates for revocation, budget, receipt, and registry state per single-row write. Cross-row crash recovery, ordering, and conservation are not assumed or discharged and remain outside the current formal claim boundary.P2, P4, P6, P7Move to a stronger storage backend. Cross-row behavior is already outside the claim: the manifest states that ReceiptBeforeAllow does not discharge concrete cross-row crash recovery, which remains excluded until implementation trace validation and crash-reopen conservation gates establish refinement.
ASSUME-TLSTLS endpoint authentication and channel confidentiality are assumed for configured remote control and hosted HTTP surfaces.P8, P9Pin trust roots, require mTLS, or run the surface on a network you control.
ASSUME-NETWORK-TRANSPORTNetwork delivery is not assumed reliable, but authenticated messages received by Chio are assumed not to be silently rewritten below TLS or signature checks.P2, P8, P9Every Chio message is signed, so a rewrite below TLS is caught by the signature check rather than by the transport. The assumption covers what TLS and the signature check together already reject.
ASSUME-GOSSIP-FAIRNESS-PARTITION-BOUNDFor a configured bilateral revocation peer set, correct connected peers are assumed to have recurring push or catch-up opportunities governed by weak fairness, local clocks remain within the declared skew bound, and declared partitions heal within the operator-declared partition bound. Loss, duplication, reordering, and invalid frames are modeled rather than assumed away. No finite delivery-step or raw-evaluation bound is assumed.P2Tighten the declared skew and partition-heal bounds so a peer that misses its catch-up window falls outside the configured set. Observed-epoch freshness fails closed at the RevocationFreshness surface, so a stale peer denies rather than allows.
ASSUME-EXTERNAL-REGISTRIESHosted package, certification, DID, and registry services are assumed to return state they have durably accepted or else fail closed.P9, P10Mirror the registries locally and treat any hosted-registry response as advisory until it is gated on a Chio-signed receipt.
ASSUME-SUBPROCESS-ISOLATIONTool-server subprocess isolation and OS process boundaries are assumed for effects outside the pure kernel decision core.P3, P6Run tool servers in a stronger sandbox. The kernel verdict bounds what is authorized, not what a tool server does once a call is allowed.
ASSUME-CHAIN-FINALITYExternal chain and oracle finality are assumed only after the configured confirmation/finality policy accepts the evidence.P4, P7Raise the confirmation depth in the finality policy, or anchor to a chain whose finality semantics match the value at risk.
ASSUME-TRACE-OBSERVERAn installed synchronous runtime trace observer is assumed to receive exactly once before finalization every successful revocation commit, completed tool-call revocation admission, and receipt append. Kernel-assigned source sequences, checked revocation subject identities, exact revocation-source identities, and other callback fields are not rewritten before recording, and the recorder runs without calibration mutations. Delivery reordering is reconciled from source sequences; detectable omissions, duplicates, inconsistent kernel depth limits, ambiguous admission-to-receipt joins, unmatched revocation sources, and relevant revocations between admission and receipt append fail closed. This assumption does not assert that any observed kernel decision is safe.P2, P4, P10Detectable omissions, duplicates, ambiguous admission-to-receipt joins and unmatched revocation sources already fail closed, so the residual exposure is a rewrite before delivery that the recorder cannot see. Treat trace-derived evidence as unqualified whenever the recorder is not the installed synchronous observer.
ASSUME-WASM-ENGINEWasmtime is assumed to enforce its documented i32 return, trap, fuel-metering, memory-limiter, and in-process sandbox semantics for untrusted guest code.P3Run the guard in advisory mode or move it out of process. The Lean wasm-boundary theorems cover Chio's verdict and error dispatch, including advisory mode; they do not verify wasmtime and do not establish engine information-flow non-interference.
ASSUME-FINDING-STATUS-OPERATOR-COMPLETENESSThe qualified cognition-market profile verifies authentic fresh status-feed state but assumes the external status operator inserts every required retraction into that feed.P4, P7, P10A retraction the operator never publishes is invisible to the profile. The freshness check establishes that the feed is authentic and current, not that it is complete, so treat a qualified finding as advisory when the status operator sits outside your trust boundary.
ASSUME-FINDING-SELLER-TOOL-SERVERThe qualified cognition-market profile binds kernel-observed seller output bytes and receipts but assumes the seller tool server performs any claimed effect outside Chio's observation boundary.P3, P6, P10Chio binds the seller output bytes and receipts it observed, not the effect those bytes describe. Where the effect is what matters, require evidence that itself lands inside the observation boundary.

Registry metadata

The header of formal/assumptions.toml carries the schema, version, and owner, and the gate scripts/check-formal-proofs.sh rejects any deviation from this shape.

formal/assumptions.tomltoml
schema = "chio.formal-assumptions.v1"
registry_version = 1
owner = "formal-verification"
FieldValuePurpose
schemachio.formal-assumptions.v1Pin so a future v2 schema cannot land without an explicit migration.
registry_version1Bumped every time the required assumption set changes; release-claim diffs cite this number.
ownerformal-verificationCODEOWNERS-resolved team that approves a change to the required set.
required_assumption_ids15 IDsThe ids a formal claim may cite. Each must have a matching row in assumptions, and the gate compares the two sets in both directions.
retired_assumption_idsEmptyWhere a discharged assumption would be kept for audit-trail resolvability. Nothing has been discharged.

Each row in assumptions is a four-field pipe-delimited tuple, and the gate parses the fields as the id, the class, the statement, and the properties the row maps to. It rejects a row with any other arity and a row with an empty field. ASSUME-SQLITE-ATOMICITY carries class audited_storage, the statement shown verbatim in the table above, and P2,P4,P6,P7. The last field says which properties lean on the assumption. Every class name begins audited_: the class says what kind of thing is assumed, not how much it is trusted, and no class means the assumption is discharged.


How the manifest uses the registry

The proof manifest at formal/proof-manifest.toml names the registry in assumption_registry, spends the assumptions as lanes inside property_matrix, and keeps a discharged_assumptions list for retirements. The gate is scripts/check-formal-proofs.sh, which loads both files and rejects a mismatch between them.

formal/proof-manifest.tomltoml
schema = "chio.proof-manifest.v1"
manifest_version = 1
proof_boundary_status = "implementation_linked_protocol_core"
verification_target = "security_critical_protocol_semantics"
assumption_registry = "formal/assumptions.toml"
claim_registry = "docs/reference/CLAIM_REGISTRY.md"
lean_root_module = "Chio"
boundary_doc = "docs/architecture/CHIO_RUNTIME_BOUNDARIES.md"
spec_anchor = "spec/PROTOCOL.md#55-verified-core-boundary"
primary_toolchain = ["lean4", "creusot", "kani", "aeneas"]

Each row of property_matrix names the lanes that contribute evidence, and an assumption appears there as a lane of the form audited_*_assumption. Six of them occur across the matrix:

Manifest laneProperties naming it
audited_storage_assumptionP2, P6
audited_transport_assumptionP2, P8
audited_subprocess_assumptionP3
audited_wasm_engine_assumptionP3
audited_crypto_assumptionP4, P7
audited_registry_assumptionP9

Read the lane names as a second vocabulary rather than as ids. The registry sorts its 15 entries into 8 classes (audited_crypto, audited_external, audited_observability, audited_platform, audited_serialization, audited_service, audited_storage, audited_transport), and the manifest's six lane names are not those classes: three of the lanes name a subject the registry has no class for, and five classes name no lane. Nothing in formal/proof-manifest.toml, formal/assumptions.toml or the check script joins one to the other, so a lane on a property row does not resolve to a specific assumption id. To find which assumptions a property rests on, read the P identifiers in the fourth field of each registry row rather than the lane names in the matrix.


Discharged assumptions, of which there are none

A discharged assumption is a prior audited assumption that no longer load-bears, because a proof, an invariant or a contract took over the job. The registry keeps a place for them: retired_assumption_ids and retired_assumptions in formal/assumptions.toml, mirrored by discharged_assumptions in formal/proof-manifest.toml.

All three lists are empty. Every one of the 15 assumptions above is live, and the trusted computing base has not narrowed since the registry was written.

What a proof has to do before an assumption can go

The clearest case is storage. An Apalache invariant, ReceiptBeforeAllow, proves that a receipt is persisted before an allow is published, and a production replay exercises that ordering on the native path. It is a real proof of a real property, and it is the obvious candidate for retiring ASSUME-SQLITE-ATOMICITY.

The manifest declines, in its own words:

text
ReceiptBeforeAllow proves the abstract persist-before-publish ordering
and its production replay exercises the native happy path. It does not
discharge concrete cross-row crash recovery, which remains excluded until
implementation trace validation and crash-reopen conservation gates
establish refinement.

That is the bar. An abstract model proving an ordering is not the same as the implementation preserving it across a crash, and the gap between them is exactly what an audited assumption is holding. Closing it needs an implementation-refinement gate over the affected production boundary, which the registry says in its own comment above the empty list: abstract invariants and manual mirror hashes are not sufficient by themselves.

The path out is written down and unused. The manifest fixes the shape a retirement takes in the comment above its empty list: a row of id|discharging_artifacts|rust_call_sites|prose citing the retired id in retired_assumptions, the artifacts that discharge it, and the Rust call sites the discharge constrains. Until such a row exists, an assumption that a proof appears to cover is still an assumption.

Components outside the TCB

The following inputs and services are outside the TCB, subject to the stated boundaries.

  • Agent input · The agent authoring a tool call is treated as fully untrusted. Every field of every request is parsed and validated before it reaches a verified entrypoint. The fuzz lane covers the parsers; see Fuzz Infrastructure.
  • Tool server output · The response from a tool server is treated as untrusted bytes. The kernel decides whether a call is allowed; what the server does with the call, and what it returns, is not part of the proof boundary.
  • The network · Beyond the TLS and message-integrity assumptions noted above, the network is treated as actively adversarial. Replay protection, session continuity, and DPoP nonce binding are all proven in the bounded model; the protocol is designed to deny unsafe sequences on the wire. The TLA+ RevocationFreshness invariant constrains only local single-authority revocation-epoch freshness against the model clock; it does not model cross-peer gossip ordering, so ASSUME-NETWORK-TRANSPORT remains audited rather than discharged.
  • Other tenants in a cluster · Multi-tenant clusters share data through verified interfaces. A misbehaving tenant cannot widen another tenant's capability by virtue of the structural AttenuationPreserving invariant.
  • Hosted registries · Their response is gated on a chio-signed receipt. If a hosted registry lies about state, the receipt log is the source of truth; the registry is advisory.

Side-channel scope

Chio addresses one side channel and explicitly does not address the others.

ChannelIn scope?How
TimingYes (limited)Three dudect harnesses across two crates: the byte-equality compare and NormalizedScope::is_subset_of in chio-kernel-core/tests/dudect/, and JWT verification in chio-credentials/tests/dudect/. See Constant-Time Tests.
Power analysisNoOut of scope. Mitigation belongs to the underlying crypto library and the hardware platform.
Electromagnetic emanationsNoOut of scope. Same answer as power.
Microarchitectural (Spectre, etc.)NoOut of scope. Operators should follow OS and hypervisor mitigations.
Cache timingNo (covered indirectly)The dudect lane catches gross data-dependent variation in the proof-facing surfaces. Cache-level analysis is out of scope.
Speculative executionNoOut of scope. Operators relying on this mitigation should run chio on hardware with the relevant patches.

dudect detects, does not prove

The constant-time lane statistically tests for data-dependent timing in the three harnessed surfaces. A clean dudect run is evidence that the compare is constant-time on the harness machine, not a proof that it is constant-time everywhere. See the constant-time page for the statistical framing.

Why the assumption list stays narrow

A proof that says "capability attenuation holds, assuming ASSUME-ED25519" identifies a smaller dependency set than a proof that assumes the signature stack, storage, canonical-JSON serializer, OS clock, and network together. That is what makes a narrow assumption list worth the bookkeeping.

Two things follow from this principle.

  • New assumptions need a written justification. The gate scripts/check-formal-proofs.sh rejects any new entry in required_assumption_ids that lacks a rationale string in assumptions.
  • Discharged assumptions are tracked, not deleted. A retired entry stays in the file, in retired_assumption_ids and retired_assumptions, so that historical claims, MAPPING rows, and audit trails stay resolvable. The manifest's discharged_assumptions list mirrors it, and its comment names the format each row must carry: the retired id, the discharging artifacts, the Rust call sites the discharge constrains, and prose.

What a release-facing claim must cite

The manifest's claim_gate_inputs list names the documents whose formal claims are checked against the proof state on every release:

formal/proof-manifest.tomltoml
claim_gate_inputs = [
  "README.md",
  "docs/start-here/VISION.md",
  "docs/reference/CLAIM_REGISTRY.md",
  "docs/release/RISK_REGISTER.md",
  "spec/PROTOCOL.md",
]

Each release-facing formal claim in those files must identify its property, model or code, assumptions, boundary, and remaining gap.

  • formal/proof-manifest.toml (the manifest the claim is making against)
  • formal/theorem-inventory.json (the theorem IDs the claim relies on)
  • formal/assumptions.toml (the assumptions the claim is conditioned on)

The script scripts/check-proof-report.sh is the gate that enforces this. A claim that names a theorem which does not appear in the inventory or omits an assumption the theorem requires fails the build.


Next