Portable Kernel
Chio's trust kernel is not a server. It is a pure, portable, verdict-producing library that compiles to three shapes: a full server-side sidecar for data centers, a mobile binding for iOS and Android, and a WebAssembly module for the browser. All three share the same compiled decision logic, the same capability rules, the same receipt format, the same signature scheme. The only things that change between targets are entropy source, clock source, and how emitted receipts find their way into storage.
Why this matters
One Core, Three Targets
The core is chio-kernel-core: a no_std + alloc Rust crate with no async runtime, no HTTP client, no database. It depends only on cryptography (ed25519-dalek, sha2) and serialization (serde). All verdict logic — capability verification, scope matching, DPoP binding, guard evaluation, receipt canonicalisation and signing, Merkle checkpoint construction — lives here and nowhere else.
Three thin adapter crates wrap the core for each deployment shape:
chio-kernel· the production sidecar. Adds tokio, an HTTP server, a SQLite-backed receipt store, a price oracle, and a guard plugin interface. This is what you run in Kubernetes.chio-kernel-mobile· UniFFI wrapper that exposes the core to Swift and Kotlin through a JSON-in, JSON-out FFI. Ships as an.xcframeworkfor iOS and a.soplus Kotlin module for Android.chio-kernel-browser· wasm-bindgen wrapper that compiles the core to WebAssembly for direct use from JavaScript and TypeScript. Ships as an npm package with typed bindings.
Feature Parity
Verdict and receipt semantics are identical across all three targets. The differences are in the surrounding machinery, and they are deliberate.
| Feature | Sidecar | Mobile | Browser |
|---|---|---|---|
| Capability verification | Yes | Yes | Yes |
| Scope matching and DPoP binding | Yes | Yes | Yes |
| Signed receipts (Ed25519) | Yes | Yes | Yes |
| Guard pipeline (sync) | Yes | Yes | Yes |
| Portable passport verification | Yes | Yes | Roadmap |
| Merkle checkpoint construction | Yes | Yes | Yes |
| Custom guards at runtime | Yes (dyn Guard) | Compile-time only | Compile-time only |
| Async runtime | Yes (tokio) | No | No |
| Persistent receipt store | SQLite | Ring buffer + platform drain | Ring buffer + platform drain |
| HTTP fetch (price oracle, siem) | Yes | Host supplies | Host supplies |
| Entropy source | OS getrandom | SecRandom / /dev/urandom | Web Crypto |
| Clock source | SystemTime | CFAbsoluteTime / SystemClock | Injectable (default Date.now) |
Native (Sidecar)
This is the default deployment: run chio-kernel as a sidecar next to your agent, your Prefect worker, your Temporal activity worker, or your Next.js server. It holds the policy, signs receipts, persists them to SQLite or whatever durable store you plug in, and exposes an HTTP interface for callers. The Installation and Quick Start guides are written against this shape.
Mobile (iOS and Android)
The mobile binding is a thin FFI over the core. Four functions, all JSON-in and JSON-out: evaluate, signReceipt, verifyCapability, and verifyPassport. iOS consumers link an .xcframework; Android consumers link a shared library and a generated Kotlin module.
Swift
import chio_kernel_mobile
// Evaluate a tool call locally — no network, no server round trip.
let request: [String: Any] = [
"capability": cachedCapabilityJson,
"trusted_issuers": [issuerHex],
"request": [
"request_id": UUID().uuidString,
"tool_name": "read_medical_record",
"server_id": "clinical-srv",
"agent_id": agentPubHex,
"arguments": ["patient_id": patientId],
],
"now_secs": 0, // 0 = use the on-device clock
]
let verdictJson = try evaluate(
requestJson: JSONSerialization.string(from: request)
)
// On allow, sign a receipt and queue it for later upload.
if verdict.verdict == "allow" {
let receiptJson = try signReceipt(
bodyJson: canonicalReceiptBody,
signingSeedHex: deviceSigningSeedHex
)
receiptQueue.enqueue(receiptJson)
}Kotlin
import uniffi.chio_kernel_mobile.*
val verdictJson = evaluate(
requestJson = buildString {
append("""{"capability": """)
append(cachedCapabilityJson)
append(""", "trusted_issuers": [""")
append(""$issuerHex"")
append("""], "request": {"request_id": "$requestId", """)
append(""""tool_name": "read_medical_record", """)
append(""""server_id": "clinical-srv", """)
append(""""agent_id": "$agentPubHex", """)
append(""""arguments": $argsJson}, "now_secs": 0}""")
}
)
val receipt = signReceipt(
bodyJson = canonicalReceiptBody,
signingSeedHex = deviceSigningSeedHex
)Offline-first is the point
Browser (WebAssembly)
The browser binding compiles the core to WebAssembly and exposes the same four functions as small, typed JavaScript exports. Entropy comes from the Web Crypto API; clock from Date.now (with an optional override for deterministic tests). The compiled artifact is 552 KB uncompressed and drops to roughly 45 KB after wasm-opt, with <5 ms evaluation latency in Chrome.
Install
npm install chio-kernel-browserUse
import init, {
evaluate,
sign_receipt,
verify_capability,
mint_signing_seed_hex,
} from "chio-kernel-browser";
// Load the wasm module once at app start.
await init();
const verdictJson = evaluate(JSON.stringify({
request: {
request_id: crypto.randomUUID(),
tool_name: "read_medical_record",
server_id: "clinical-srv",
agent_id: agentPubHex,
arguments: { patient_id: patientId },
},
capability: cachedCapability,
trusted_issuers_hex: [issuerHex],
// clock_override_unix_secs: 1_717_200_000, // optional, for tests
}));
const verdict = JSON.parse(verdictJson) as EvaluationVerdict;
if (verdict.verdict !== "allow") {
throw new PermissionError(verdict.reason);
}
const seedHex = mint_signing_seed_hex();
const receiptJson = sign_receipt(
JSON.stringify(receiptBody),
seedHex,
);Integration in Next.js
The module loads fine in both the Node and Edge runtimes. A common shape is a single server-side gating helper, shared by the app routes that need it:
// lib/chio-gate.ts
import init, { evaluate } from "chio-kernel-browser";
let ready: Promise<unknown> | null = null;
function ensure() {
return (ready ??= init());
}
export async function gate(request: EvaluateRequest) {
await ensure();
const verdict = JSON.parse(evaluate(JSON.stringify(request)));
if (verdict.verdict !== "allow") {
throw Object.assign(new Error(verdict.reason), { code: "chio_deny" });
}
return verdict;
}Design Decisions
- JSON at the FFI boundary. Rather than project the entire Chio type graph into UDL or TypeScript, the mobile and browser bindings speak JSON. The FFI surface stays small (four functions), the type graph stays versionable, and language binding impedance is avoided. This is the same tradeoff gRPC and protobuf make against native struct marshalling.
- Fail-closed entropy. If a platform's RNG cannot produce high-quality randomness at signing time, the kernel refuses with a
weak_entropyerror rather than producing a signature over predictable bytes. Silent degradation is the worst possible outcome for a trust kernel; we would rather fail loudly. - Ring-buffer receipts, platform drains. The core buffers emitted receipts in memory. Platform adapters call
drain_receiptson a cadence they choose and persist to whatever storage they have (Keychain-backed SQLite on iOS, Room on Android, IndexedDB in the browser). The core stays deterministic and ignorant of storage. - No custom guards at runtime on mobile or browser. Guards are compiled into the adapter library at build time. Runtime guard registration requires a plugin loader that mobile and WASM cannot practically support. Most mobile and browser deployments need only the built-in guards; custom guards still run server-side on the sidecar for more complex policies.
- Same receipt format, everywhere. A receipt signed offline on a phone three days ago verifies against the same canonicalisation rules and the same signature scheme as one produced this second by a server in a data center. There is no "mobile receipt format" or "browser receipt format".
Status and Roadmap
| Crate | Status | Distribution |
|---|---|---|
chio-kernel-core | Production · CI-gated for no_std and wasm32 | Internal crate, not separately versioned |
chio-kernel (sidecar) | Production | Container image, Homebrew, release binaries |
chio-kernel-mobile | Alpha · iOS device and simulator builds verified; Android builds verified on configured NDK | .xcframework and .aar produced; CocoaPods and Maven Central not yet published |
chio-kernel-browser | Alpha · headless Chrome qualification passing; 552 KB / <5 ms evaluate | wasm-pack output ready; not yet published to npm |
Alpha contract
Next Steps
- Architecture · how the kernel fits into the broader Chio deployment topology
- Capabilities · the token format the portable kernel verifies on every call
- Receipts · the canonical form the kernel signs, identical across all three targets
- Trust Model · what it means for a verdict to be identical across server, mobile, and browser