Chio/Docs
LOGIN · JOIN

LearnSystem Architecture

The State a Verdict Depends On

The evaluation core reads no store and no clock of its own, so every input a verdict turns on arrived as an argument.

Overview

chio-kernel-core is the pure-compute part of capability evaluation. Its own architecture notes state the boundary: the crate performs no I/O and holds no state beyond what a caller explicitly supplies. It is built no_std + alloc, so the same verdict-producing code runs in a browser, in a mobile app, behind a C++ FFI host, and inside the hosted sidecar without modification.

That has a consequence worth stating in full. If the function that produces the verdict cannot read a database, cannot open a socket, and cannot ask the operating system what time it is, then everything the verdict depends on arrived as an argument. The list of arguments is therefore the complete list of state a verdict can turn on, and the code that fetched each one runs before the call rather than inside it.


Model

A pure function with no memory

The evaluation entry point takes an EvaluateInput and returns an EvaluationVerdict. Every field of the input is a borrow the caller owns.

crates/kernel/chio-kernel-core/src/evaluate.rs57-71rust
pub struct EvaluateInput<'a> {
    /// Tool call request being evaluated.
    pub request: &'a PortableToolCallRequest,
    /// The capability token authorising this call.
    pub capability: &'a CapabilityToken,
    /// Trusted issuer public keys (typically CA + kernel + authority).
    pub trusted_issuers: &'a [PublicKey],
    /// Clock used for time-bound enforcement.
    pub clock: &'a dyn Clock,
    /// Guard pipeline. Evaluated in order, fail-closed on deny or error.
    pub guards: &'a [&'a dyn Guard],
    /// Optional filesystem roots from the owning session, passed through to
    /// guards that enforce root-based resource protection.
    pub session_filesystem_roots: Option<&'a [String]>,
}

Three more values arrive alongside it on the full path. evaluate_with_full_floor takes a CapabilityCryptoFloor, a CapabilityNegotiation for the peer, a &dyn TrustRootResolver, and a mutable &mut dyn BudgetRegistry. The registry is the only argument the function writes to, and it writes to it last.

The clock and the entropy source are traits

Time and randomness are the two things a pure function cannot compute and cannot do without. Both enter as traits, and both doc comments name the rule directly.

crates/kernel/chio-kernel-core/src/clock.rsrust
//! Abstract clock for capability time-bound enforcement.
//!
//! The kernel core never calls `std::time::SystemTime::now()`. All time
//! enters the pure evaluation surface through a `&dyn Clock` so that
//! browser, WASM, and embedded adapters can inject `Date.now()`,
//! `instant::now()`, or a fuzzed/mock clock for deterministic testing.

/// Abstract monotonic wall-clock exposing Unix seconds.
///
/// Implementations MUST return a value consistent with the signed
/// `issued_at` / `expires_at` fields on capabilities. The verdict path is
/// fail-closed against clock errors: if `now_unix_secs` returns a value in
/// the past of `issued_at` or past `expires_at`, the capability is rejected.
pub trait Clock {
    /// Current Unix timestamp in seconds.
    fn now_unix_secs(&self) -> u64;
}

rng.rs mirrors it. The core never calls OsRng directly; browser adapters route to crypto.getRandomValues() through the getrandom crate's js feature, WASI adapters route to the host random API, and mobile adapters use SecRandomCopyBytes or /dev/urandom. Determinism and Replay covers what a caller owes those two traits.


How it works

Who fetches, and when

chio-kernel is the hosted layer that does the reading. Its architecture notes draw the stores it depends on as consumer-supplied traits, hanging off the stages that use them rather than off the evaluation core. Four groups appear, and each one is a trait a deployment implements.

rendering
The hosted kernel pipeline with the four consumer-supplied trait groups it reads through: capability authority and revocation, budget and payment, tool-server connection, and receipt store. The dotted edges mark the stage that performs each read.
sourcecrates/kernel/chio-kernel/ARCHITECTURE.md:14-63at fe56570

Read that as an answer to the question of provenance. A verdict that turns on revocation turned on a RevocationStore read the hosted layer performed during capability validation. A verdict that turns on remaining budget turned on a BudgetStore read at budget admission. Neither read happens inside the pure function, and neither can happen twice with different answers inside one evaluation.

The reads behind one verdict, in order

evaluate_with_full_floor, the path production kernels use, runs six steps in a fixed order.

  1. Capability base verification: issuer trust, signature under the configured crypto floor, and the time window. Reads trusted_issuers and the clock.
  2. Delegation chain shape, when the token carries one: per-link signatures and the final delegatee against the token subject. An attenuated token additionally binds attenuation_proof.parent_scope_hash to the trust root through the TrustRootResolver, gated by the negotiated DELEGATION_CHAIN_BINDING feature.
  3. Subject binding: request.agent_id must equal the verified capability subject.
  4. Portable scope match: scope::resolve_matching_grants picks the most specific grant covering the server and tool pair. A constraint the portable matcher cannot evaluate fails closed with ConstraintError.
  5. Guard pipeline: every &dyn Guard runs in order, and a Deny, PendingApproval, or Err from any guard fails the whole evaluation.
  6. Sibling-budget admission, last. Only after steps one through five pass does admit_delegated_budget mutate the caller's real BudgetRegistry.

Why admission runs last

Admission is the one step that writes. The source states the reason it is deferred: a forged or out-of-scope token never consumes a sibling's share. During steps one through five the verifier runs against a no-op registry, so a token that fails subject binding or scope matching leaves the real budget untouched.

The verdict that comes back is three-valued in the hosted kernel and two-valued in the core: the core emits only Allow and Deny, and PendingApproval is produced by the layer that can hold a request open.

crates/kernel/chio-kernel/src/runtime.rs30-38rust
pub enum Verdict {
    /// The action is allowed.
    Allow,
    /// The action is denied.
    Deny,
    /// The action is suspended pending a human decision. Look up the
    /// associated `ApprovalRequest` via the HITL API.
    PendingApproval,
}

Guarantees and limits

Status: shipped. chio-kernel-core is a no_std crate with #![deny(unsafe_code)] at its root, and formal/proof-manifest.toml names evaluate.rs, capability_verify.rs, scope.rs, normalized.rs, and receipts.rs as the modules the bounded verified core covers.

  • No module in the core reaches out. The crate's stated invariant is that no module reaches into std, wall-clock globals, the filesystem, the network, async runtimes, stores, or policy engines. Hosted-only code such as revocation_view and the fuzz harnesses is feature-gated.
  • An unknown input denies. Unknown budget parents, unsupported scope constraints, missing chain-binding trust roots, and a clock value outside [issued_at, expires_at) all deny. There is no path where the core proceeds on a value it could not interpret.
  • Freshness is the caller's problem. The core decides against the snapshot it was handed. A revocation that lands after the hosted layer read RevocationStore is not visible to that evaluation, which is why revocation propagation is a store property rather than a verdict property. See Revocation Store.
  • The core cannot hold a request open. PendingApproval never flows out of chio-kernel-core, because suspending a call requires state that outlives the function. That branch belongs to the hosted layer and the approval store.
  • Purity is not the proof. The bounded verified core covers the five modules the proof manifest names. Payment authorization, governed-transaction policy, DPoP nonce replay, and tool dispatch live in chio-kernel and are outside that boundary. See Formal Assurance.

Next steps

The State a Verdict Depends On · Chio Docs