Engineering standard
Trace each rule Chio's security code follows to the type, checked transition, or gate that fails when it breaks.
On this page
A new connector, adapter, or recovery path in Chio inherits the security rules of the code it joins. The engineering standard writes each rule into a type, a checked transition, or a gate, and records any rule without a gate as debt whose cap can only fall.
The standard covers crates/security/*, crates/kernel/chio-kernel*, chio-control-plane, chio-store-sqlite, the security types in chio-core-types, and the cage, broker, keyring, and quarantine trust boundaries. Every rule names how it is checked, so a reviewer can find the gate that would fail if the rule broke.
A renewal can keep the cap where it is
Each existing site is pinned by identity. Renewing with --ratchet records the same cap, and the gate still refuses any tree that adds a site.
A rule lives where a violation can be detected
The first principle puts each invariant where breaking it is caught, and documents the assumption beside the mechanism that enforces it:
- A type keeps an unverified object away from an interface that requires verified authority.
- A runtime check enforces a fact that changes over time, such as revocation or remaining capacity.
- A structural gate flags a newly introduced dispatch site that needs classification.
- A behavioral test observes the protected effect under the selected adversary and failure, including release builds and recovery.
The second principle comes from a review finding: a safety net present only in the build profile the tests run under is absent from the release build that serves work. Release builds therefore keep the overflow checks the tests rely on.
Four constructions make whole classes of defect unrepresentable
- Evidence tokens. Private fields and one checked constructor; a protected operation takes the token as an argument.
- Constrained values. Construction and deserialization validate the value, with at most one named exit to its raw representation.
- Structured rejection. One discriminant per rule, with source errors preserved, so tests, receipts, and operators can name the check that failed.
- Escape-hatch gate. Allowed unchecked paths are listed by name and location, and a new path fails the gate.
The first three use the type system. The escape-hatch gate is an automated source check, which covers what a type cannot see: a path that exists because someone wrote it.
Fourteen areas each give one concern its rules
Each numbered area states the rules for one concern, and a rule names the gate or debt entry that backs it where the standard records one:
- Module and boundary design. A module owns exactly one of an authorization decision, a pure state transition, a durable journal, effect I/O, or signed evidence.
- Type design. An invalid value is unconstructible, which is stronger than rejected.
- Errors and rejection provenance. One rejection reason, one discriminant, so a caller can tell which rule fired.
- Arithmetic, accounting, and build-profile parity. Release builds keep the overflow checks the tests rely on.
- Concurrency, durability, and recovery. Durable intent precedes external effect; an unknown outcome stays unknown.
- Time. The clock is part of the trusted computing base and is injected, never ambient.
- Secrets. Secret material zeroizes on drop and implements
Debug,Display,Serialize, orCloneonly with a named reason. - Cryptographic domain separation. Every signed or hashed payload type has one domain string, declared exactly once.
- Confinement. Deny by default, and constrain arguments as well as syscall names.
- Testing. Each test layer proves what the layer below it cannot.
- What "no AI slop" means concretely. Remove process narration and volume that only simulates thoroughness.
- Review process. Self-review is not review; the newest code is audited first.
- Performance and measurement. Measure before optimizing; an unmeasured optimization and an unmeasured cost are the same mistake.
- State recovery, serialization boundaries, and tenant isolation. Lock-poison recovery is decided by durable phase, verified, and fenced when it cannot be verified.
Eight checks in the required job hold the rules on every merge
The required Build, lint, test job runs on every push to main and every pull request to main. Its "Workspace structural gates" step runs three of the standard's own gates, a fourth runs in its own step, and four more hardening checks run in the same job:
- Domain separation. Every byte-string domain constant under
crates/named for a domain or signature is declared exactly once. - Accounting arithmetic. Counts unchecked-arithmetic sites in the kernel's and the SQLite store's budget, quota, lease, and exposure modules, and refuses a count above each module's recorded baseline.
- Negative assertions. Bars a new weak negative assertion in
crates/security,chio-kernel, orchio-control-plane, with existing sites pinned one by one by identity. - Rust file hygiene. Caps a new production or test module at 2,000 assembled lines, 1,000 for a library root; existing oversized modules are allowlisted as expiring debt at their recorded size.
- Lint parity. Compares every member crate's lint tables with the workspace policy and refuses a manifest that lacks a workspace lint or carries it differently.
- Wire schemas. Compares every hand-written identifier constant under
crates/with a committed lock file and refuses a tree where one side changes without the other. - Dependency budget. Caps the package graph of the cage-init helper's and the secret broker's release feature sets at a measured ceiling and refuses a denied package anywhere in that graph.
- Miri crate list. Validates the committed list of crates that Miri interprets for undefined behavior.
Outside the required job, a nightly workflow interprets that Miri list, and AddressSanitizer and ThreadSanitizer run the unit tests of four committed security crates; both nightly workflows are advisory. A separate job runs the security crates under cargo-nextest, giving each test its own process, a per-test deadline, and leak detection.
Read more in Behavioral gates, which shows how the domain-separation and negative-assertions gates are self-tested.
A ratchet can hold or lower its cap, and its exemptions expire
Renewal through --ratchet holds or lowers a ratchet's cap or baseline and refuses to raise one, as the debt ratchet draws. The negative-assertions baseline also expires, on 2027-01-31, so its exemption has a date on which the gate fails closed. A rule with no wired gate stays recorded as debt, in the standard's own words, until one exists.
Read more in Formal verification, for the proofs and model checks that cover what a gate cannot reach.
A connector that writes before it checks fails the byte oracle
A proposed repository connector returns Deny for a protected path, and the verdict proves nothing if the file was written before the check. This comparison runs Chio's resolve_matching_grants against fixture files: check_then_write gates its effect first, and the deliberately bad write_then_check writes first. Both return a genuine scope Deny; an independent read of the protected bytes tells them apart.
The complete good and bad connector comparison
use std::fs;
use std::path::Path;
use chio_core::capability::scope::{ChioScope, Constraint, Operation, ToolGrant};
use chio_kernel_core::scope::resolve_matching_grants;
use serde_json::{json, Value};
#[derive(Debug, PartialEq)]
pub enum WriteVerdict { Allow, Deny }
fn may_write(scope: &ChioScope, original: &Value) -> bool {
!resolve_matching_grants(scope, "write_file", "workspace", original)
.expect("reviewed matcher inputs").is_empty()
}
/// A connector ordering comparison, not the kernel's complete admission path.
fn check_then_write(scope: &ChioScope, original: &Value) -> WriteVerdict {
if !may_write(scope, original) { return WriteVerdict::Deny; }
fs::write(original["path"].as_str().unwrap(), b"reviewed update\n").unwrap();
WriteVerdict::Allow
}
/// Deliberately bad candidate: a genuine Deny arrives after the file changed.
fn write_then_check(scope: &ChioScope, original: &Value) -> WriteVerdict {
fs::write(original["path"].as_str().unwrap(), b"unauthorized update\n").unwrap();
if may_write(scope, original) { WriteVerdict::Allow } else { WriteVerdict::Deny }
}
pub fn review_connector_order(fresh: &Path) {
fs::create_dir(fresh).unwrap();
let admitted = fresh.join("reviewed");
fs::create_dir(&admitted).unwrap();
let allowed_file = admitted.join("report.txt");
let protected_file = fresh.join("credentials.txt");
let original_bytes = b"protected fixture, not an actual credential\n";
fs::write(&protected_file, original_bytes).unwrap();
let scope = ChioScope {
grants: vec![ToolGrant {
server_id: "workspace".into(), tool_name: "write_file".into(),
operations: vec![Operation::Invoke],
constraints: vec![Constraint::PathPrefix(admitted.to_str().unwrap().into())],
max_invocations: None, max_cost_per_invocation: None,
max_total_cost: None, dpop_required: None,
}], ..ChioScope::default()
};
let allowed_request = json!({"path": allowed_file});
assert_eq!(check_then_write(&scope, &allowed_request), WriteVerdict::Allow);
assert_eq!(fs::read(&allowed_file).unwrap(), b"reviewed update\n");
let frozen_request = json!({"path": protected_file});
assert_eq!(check_then_write(&scope, &frozen_request), WriteVerdict::Deny);
assert_eq!(fs::read(&protected_file).unwrap(), original_bytes);
println!("ALLOW reviewed file; DENY protected file before its bytes change");
assert_eq!(write_then_check(&scope, &frozen_request), WriteVerdict::Deny);
let oracle_passed = fs::read(&protected_file).unwrap() == original_bytes;
assert!(!oracle_passed, "the resource assertion must catch this bad candidate");
println!("CATCH bad candidate: Deny returned after unauthorized bytes were written");
println!("SCOPE real matcher and filesystem ordering; no process-confinement claim");
}connector_order::review_connector_order(&fresh);ALLOW reviewed file; DENY protected file before its bytes change CATCH bad candidate: Deny returned after unauthorized bytes were written SCOPE real matcher and filesystem ordering; no process-confinement claim
You should see the admitted write land, the protected file refused with its bytes intact, and the bad candidate caught after a Deny that a verdict-only assertion would accept. The comparison exposes ordering; process confinement and secure path-descriptor handling are reviewed at their own boundaries. Pass a new disposable directory as fresh; the protected file is a labeled fixture. Download the complete source.
The matcher is one component of admission; a production host also checks issuer and proof, live lineage, budget, manifests and topology, labels, and the retained operation before dispatch, and guards the return path. Likewise, changing the production matcher to always allow breaks the tool and server pivot test in threat coverage. Name the layer each oracle observes: adapter counters see dispatch into a connection, a file oracle sees bytes, and a Linux cage gate sees the kernel resource boundary.
A connector review follows the original operation through restart and withdrawal
| Stage | Same change to test | Independent observation |
|---|---|---|
| Construction and decoding | Invalid scope or identity yields no dispatch authority | Typed failure, no executor call |
| Original admission | Only the frozen request and destination consume the grant | Permitted effect lands; alternate target refused |
| Crash and restart | A lost acknowledgement resumes the original operation | Original custody kept; no second callback |
| Return | A response failure keeps a possible committed effect | Original response and evidence survive; labels enforced |
| Withdrawal | New admission stops; original work stays inspectable | Operation retained under its original authority |
Carry the original operation key, arguments, destination, and evidence through the restart case. A connector that catches a timeout and submits a fresh key can duplicate a committed effect, and one that converts an unknown outcome into a refund reopens a consumed budget. Extend the review to descriptors, syscall arguments, network destinations, and tenant partitions when the connector crosses them.
Read more in Recover an operation and execution nonce custody, which run these cases against durable stores.