Formal Assurance Overview
Chio takes a layered approach to assurance. A small pure decision core is proven by hand in Lean 4, refined against Aeneas-extracted Rust, and bounded-model-checked with Kani. A TLA+ specification covers the cross-process revocation propagation protocol that the Lean model cannot reach. Everything outside that proof boundary is held to softer bars: differential property tests, libFuzzer coverage-guided harnesses, dudect timing analysis, and ordinary unit and integration tests. This page is the honest map of which guarantees are which.
Read the manifests, not the marketing
formal/proof-manifest.toml, formal/theorem-inventory.json, formal/assumptions.toml, and formal/MAPPING.md. If the docs and the manifests disagree, the manifests are the source of truth.Reading Paths by Role
The formal-assurance section is sized for four readers. Pick the path that matches your role; each path is a 30-second scan of which pages to open and what each one gives you.
I operate the kernel in production (SRE / platform)
- Quickstart · run every gate locally and see green.
- Failure Modes · what each gate failure looks like in CI output.
- Assumptions and TCB · what is trusted vs verified, and what to do if an assumption breaks in production.
- Constant-Time Tests · timing-leak detection on the verdict hot path.
I'm auditing or certifying chio (security auditor / compliance)
- Theorem Inventory · the per-theorem catalog: ID, statement, tool, file, status.
- P1 Tour · a worked example tracing capability attenuation through every layer.
- Assumptions and TCB · the explicit trust boundary and the ten audited assumptions the proofs are conditioned on.
- Differential Tests · production-vs-spec equivalence on scope subsumption, canonical JSON, anchored roots, receipts.
I'm an academic or formal-methods researcher (Lean / TLA+)
- Lean 4 Proofs · the canonical theorem statements and the project layout.
- Aeneas Pipeline · the Rust-to-Lean extraction pipeline (a Lean-targeted adaptation of Aeneas, paired with explicit equivalence theorems).
- TLA+ Specs · the temporal-logic spec for cross-authority revocation propagation.
- Theorem Inventory · the catalog you cite when comparing to your own work.
I'm contributing a proof or harness (chio contributor)
- P1 Tour · how a property flows through Lean, Aeneas, Kani, and the differential lane.
- Lean 4 Proofs · Lean conventions, naming, and the proof-file layout.
- Kani Harnesses · how to write a new bounded-model-checking harness.
- Fuzz Infrastructure · adding a new libFuzzer target, owners table, and corpus.
- Failure Modes · debugging a gate that fails on your PR.
The Assurance Pyramid
Chio's assurance is layered. The narrowest, strongest layer at the top is hand-written formal proof; the broadest, weakest layer at the bottom is manual review. Each layer is honest about what it can and cannot say.
| Layer | Tool | Surface | Strength |
|---|---|---|---|
| Mechanized proof | Lean 4 | Bounded models of the capability algebra, revocation, evaluation, receipts, protocol | Strongest. Sorry-free, root-imported, machine-checked. |
| Refinement extraction | Aeneas (via Charon) | Pure numeric and boolean helpers in formal_aeneas.rs | Strong. Lean equivalence theorems link extracted models to handwritten ones. |
| Bounded model checking | Kani (CBMC backend) | Public Rust entrypoints: verify_capability, evaluate, sign_receipt, NormalizedScope::is_subset_of, resolve_matching_grants | Strong within bounds. Symbolic execution exhausts inputs up to a configured size. |
| Refinement contracts | Creusot | Same five public symbols plus the formal_core helpers | Strong. SMT-discharged contracts on the production Rust. |
| Temporal model checking | TLA+ (TLC and Apalache) | Cross-authority revocation propagation | Strong within bounds. Three named safety invariants plus one liveness property. |
| Differential property tests | proptest in chio-formal-diff-tests | Reference spec vs production for scope subsumption, anchored roots, receipt encoding, canonical JSON | Medium. Catches drift between two implementations of the same surface. |
| Coverage-guided fuzz | libFuzzer plus ClusterFuzzLite | All trust-boundary parsers, decoders, and verifiers | Medium. Random and mutation-driven inputs over many CPU-hours. |
| Timing analysis | dudect | Signature byte-equality, scope subset checks | Limited. Statistical detection of data-dependent timing, not a proof. |
| Integration tests | cargo test | End-to-end protocol behavior | Lower. Sanity, not exhaustive. |
| Manual review | Humans | Everything outside the proof boundary | Lowest. Necessary but fallible. |
The general rule: the higher up the table a guarantee lives, the narrower the surface it covers. Mechanized proof reaches the smallest fraction of the codebase but says the strongest things. The bottom layers reach far more code but with weaker guarantees.
The Tools Chio Uses
- Lean 4 · Proof assistant for the capability algebra, revocation snapshots, evaluation totality, receipt coupling, and protocol-level closure theorems. Source under
formal/lean4/Chio/. See Lean 4 Proofs. - Aeneas · Extracts a functional model from Rust source for proving in Lean (the original Aeneas pipeline targets F*; chio extracts to Lean instead, paired with explicit equivalence theorems). Two lanes: a pilot at
formal/aeneas/verified_core.rsand the production extraction fromcrates/chio-kernel-core/src/formal_aeneas.rs. See Aeneas Pipeline. - Kani · Bounded model checker for Rust via CBMC. Symbolically executes proof harnesses on every PR. Public harnesses are at
crates/chio-kernel-core/src/kani_public_harnesses.rs. See Kani Harnesses. - Creusot · SMT-backed refinement-type prover that pins contracts to production Rust symbols. Configured in
formal/rust-verification/creusot-contracts.toml. - TLA+ · Temporal-logic spec language. The model checker TLC and the bounded type checker Apalache run
formal/tla/RevocationPropagation.tlaon the PR lane and the nightly liveness lane respectively. See TLA+ Specs. - proptest · Property-based generator for differential tests in
formal/diff-tests/. See Differential Tests. - dudect · Statistical detector for data-dependent timing in tight inner loops. Lives in
crates/chio-kernel-core/tests/dudect/. See Constant-Time Tests. - libFuzzer + ClusterFuzzLite · Coverage-guided fuzzing across every trust-boundary parser. Targets are in
fuzz/fuzz_targets/with corpora atfuzz/corpus/. See Fuzz Infrastructure.
What Is Formally Verified Today
The proof manifest declares ten required property identifiers, P1 through P10. Each is mapped to a list of Lean theorems plus, in most cases, a Kani harness, an Aeneas equivalence proof, or a Creusot contract.
| ID | Property | Lanes |
|---|---|---|
| P1 | Capability attenuation: a child capability is a subset of its parent | Lean root, differential test, Rust projection, Aeneas equivalence, public Kani |
| P2 | Presented revocation coverage: revoked tokens and revoked ancestors deny | Lean root, audited storage assumption, SQLite projection, Aeneas equivalence |
| P3 | Fail-closed evaluation: deny dominates, allow requires every check to pass | Lean root, Rust core, audited subprocess assumption, public Kani, adapter no-bypass |
| P4 | Receipt integrity: sign-then-verify, immutability, field coupling | Lean root, symbolic crypto, audited crypto assumption, receipt totality, Aeneas equivalence |
| P5 | Presented delegation-chain semantic validity | Lean root, SQLite projection |
| P6 | Local parent-link soundness within an authenticated session | Lean root, audited storage assumption |
| P7 | Receipt-lineage soundness across two signed receipts | Lean root, symbolic crypto, audited crypto assumption |
| P8 | Session continuity: anchor and continuation evidence required | Lean root, audited transport assumption, DPoP binding tests |
| P9 | Delegation and provenance consistency in call-chain references | Lean root, audited registry assumption |
| P10 | Report truthfulness: asserted and observed lineage cannot be relabeled as verified | Lean root, claim gate |
For the full per-theorem table, see the Theorem Inventory.
The Proof Boundary
The manifest names the boundary explicitly: implementation_linked_protocol_core. The verification target is security_critical_protocol_semantics. That phrase is doing a lot of work; here is what it means.
The boundary covers the pure security decision surface inside chio-kernel-core plus bounded models of adjacent state transitions (revocation snapshots, budget commits, DPoP nonce admission, guard pipeline composition, receipt coupling). The covered Rust modules listed in the manifest are:
covered_rust_modules = [
"crates/chio-kernel-core/src/capability_verify.rs",
"crates/chio-kernel-core/src/scope.rs",
"crates/chio-kernel-core/src/evaluate.rs",
"crates/chio-kernel-core/src/formal_aeneas.rs",
"crates/chio-kernel-core/src/formal_core.rs",
"crates/chio-kernel-core/src/normalized.rs",
"crates/chio-kernel-core/src/receipts.rs",
]Everything outside that list is excluded from the proof boundary. The manifest also names the excluded surfaces verbatim so a reader does not have to infer them: concrete Ed25519, SHA-256, canonical JSON, TLS, OS clock, SQLite, chain, and hosted-registry implementations beyond their audited assumptions; async scheduling, network delivery, subprocess effects, and tool-server behavior after the verified decision core allows a call; cluster consensus, external settlement rails, and third-party registry availability beyond fail-closed handling; Aeneas extraction from async, IO, SQLite, crypto, and string-heavy production modules outside formal_aeneas.rs; and symlink resolution and OS filesystem root enforcement beyond chio's normalized path-prefix fail-closed checks.
The boundary moves with PRs
audited assumption to discharged by named theorem, the manifest's discharged_assumptions list grows and required_assumption_ids shrinks. The retired RETIRED-SQLITE-CROSS-ROW entry is a worked example: prior cross-row SQLite atomicity is no longer assumed; the conjunction of the TLA+ MonotoneLog invariant and the per-row budget invariant in crates/chio-kernel/src/budget_store.rs does the work the assumption used to do.What Is in the Trust Base
Ten audited assumptions remain in formal/assumptions.toml as load-bearing. They are listed by ID; each one names the properties it discharges.
ASSUME-ED25519· Ed25519 unforgeability for trusted public keys.ASSUME-SHA256· SHA-256 and Merkle hash collision resistance.ASSUME-CANONICAL-JSON· RFC 8785 canonical JSON is deterministic and byte-stable.ASSUME-OS-CLOCK· The injected clock reports operator-accepted Unix time within tolerance.ASSUME-SQLITE-ATOMICITY· SQLite per-row writes are atomic. Cross-row atomicity is not assumed; that prior assumption is retired.ASSUME-TLS· TLS endpoint authentication and channel confidentiality.ASSUME-NETWORK-TRANSPORT· Authenticated messages received by chio are not silently rewritten below TLS or signature checks.ASSUME-EXTERNAL-REGISTRIES· Hosted package, certification, DID, and registry services return durably accepted state or fail closed.ASSUME-SUBPROCESS-ISOLATION· Tool-server subprocess and OS process boundaries hold for effects outside the kernel.ASSUME-CHAIN-FINALITY· External chain or oracle finality after the configured confirmation policy accepts the evidence.
See the Assumptions and TCB page for the rationale and mitigation per assumption.
How to Read a Proof Manifest
The manifest at formal/proof-manifest.toml is the canonical proof inventory. Every release-facing formal claim must cite it, the theorem inventory, and the audited assumptions. Here is the shape of the relevant fields.
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"
primary_toolchain = ["lean4", "creusot", "kani", "aeneas"]
# Root Lean modules. Theorems must be reachable from these to count.
root_modules = [
"formal/lean4/Chio/Chio.lean",
"formal/lean4/Chio/Chio/Spec/Properties.lean",
"formal/lean4/Chio/Chio/Proofs/Monotonicity.lean",
# ... eight more entries
]
# Gate commands. Run all of these to reproduce the assurance posture.
gate_commands = [
"./scripts/check-formal-proofs.sh",
"./scripts/check-aeneas-pilot.sh",
"./scripts/check-aeneas-production.sh",
"./scripts/check-aeneas-equivalence.sh",
"./scripts/check-rust-verification-gates.sh",
"./scripts/check-kani-public-core.sh",
"./scripts/check-adapter-no-bypass.sh",
"cargo test -p chio-formal-diff-tests",
"./scripts/check-portable-kernel.sh",
"./scripts/check-proof-report.sh",
]
# Property matrix. Each entry has the form:
# ID|description|lanes|theorem-ids
# A property is "covered" only when every named lane runs and every
# theorem ID exists in theorem-inventory.json.
property_matrix = [
"P1|capability attenuation|lean_root_imported,differential_test,...|spec.capability_monotonicity,...",
# ... nine more rows
]Three rules govern the manifest:
- A theorem only counts as evidence if it is root-imported from the modules in
root_modulesand contains nosorry. - A property only counts as covered if every lane in its property matrix entry runs green in CI.
- Excluded surfaces and audited assumptions must be cited explicitly. Silent assumptions are forbidden.
Reproducing the Proofs Locally
Every gate command in the manifest is a shell script that any contributor can run. The full set of commands reproduces the assurance posture:
# Lean root proofs (sorry-free, root-imported)
./scripts/check-formal-proofs.sh
# Aeneas pilot extraction (formal/aeneas/verified_core.rs)
./scripts/check-aeneas-pilot.sh
# Aeneas production extraction (chio-kernel-core/src/formal_aeneas.rs)
./scripts/check-aeneas-production.sh
# Aeneas-Lean equivalence theorems
./scripts/check-aeneas-equivalence.sh
# Creusot and Kani required-lane verification
./scripts/check-rust-verification-gates.sh
# Public Kani harnesses on chio-kernel-core
./scripts/check-kani-public-core.sh
# Adapter no-bypass: every protocol adapter must call evaluate()
./scripts/check-adapter-no-bypass.sh
# Differential tests: reference spec vs production
cargo test -p chio-formal-diff-tests
# Portable-kernel parity (the same verdict on every target)
./scripts/check-portable-kernel.sh
# Proof report: the final aggregator that all gates fed into
./scripts/check-proof-report.shThe TLA+ lane is separate, since Apalache is not a Cargo dep. The PR job runs the safety invariants:
# Install Apalache via the pinned tool installer
./tools/install-apalache.sh
# Safety invariants (NoAllowAfterRevoke, MonotoneLog, AttenuationPreserving)
apalache check \
--inv=SafetyInv \
--config=formal/tla/MCRevocationPropagation.cfg \
formal/tla/RevocationPropagation.tlaPASS #11: BoundedChecker
Checker reports no error up to computation length 16
It took me 0 days 3 hours 12 min 47 sec
Total time: 11567.881 sec
EXITCODE: OKThe nightly liveness lane is broader: PROCS=6, CAPS=16, with --temporal=RevocationEventuallySeen gated on the WF_vars(PropagateAny) weak-fairness conjunct in the spec.
Lean toolchain pin
formal/lean4/Chio/lean-toolchain: leanprover/lean4:v4.28.0-rc1. lake build picks it up automatically. Kani, Creusot, and Aeneas pin in their own installer scripts under tools/.What the Proofs Do Not Say
It is worth being explicit about what the assurance layer does not establish.
- The Lean theorems are over bounded models. They do not witness the Rust binary running on a real CPU; they witness mathematical functions written in Lean. The Aeneas equivalence theorems and the Kani and Creusot lanes are what tie the bounded models to executable code.
- Crypto primitives are assumed, not proven. The receipt sign-then-verify theorem is over a symbolic crypto model, not over the Ed25519 implementation in
ed25519-dalek. - Side channels other than timing are out of scope. dudect detects data-dependent timing variation; it does not address power analysis, electromagnetic emanations, or microarchitectural attacks. See the Constant-Time Tests page for what is and is not covered.
- Behavior of tool servers after chio allows a call is out of scope. The receipt records the verdict; what the tool server does next is the operator's concern.
- External chain finality is gated on the configured policy. If your settlement layer reorgs deeper than your finality threshold, the assumption breaks and the receipt evidence does too.
Next Steps
- Theorem Inventory · the full table of theorems by ID, statement, tool, file, and status.
- Assumptions and TCB · what chio trusts, why, and what would mitigate each assumption breaking.
- Aeneas Pipeline · how the production extraction is wired to the Lean equivalence theorems.
- Lean 4 Proofs · the proof structure, file by file.
- Kani Harnesses · the public harness inventory plus per-harness wall clocks.
- TLA+ Specs · the revocation-propagation spec and its three named safety invariants.
- Differential Tests · reference spec vs production for the surfaces that proofs do not cover.
- Constant-Time Tests · dudect harnesses and how to read their output.
- Fuzz Infrastructure · the trust-boundary fuzz target inventory.
For the broader trust framing, the Trust Model page explains where formal assurance sits inside chio's zero-ambient-authority design.