Design packet · for review
How a compartmentalized, nix-built OS ships fast security fixes and feature bumps to new and existing users — without rebuilding everything, and without breaking running compartments.
Status: DESIGN — under review by the design agent, implementation by the build agents · source: notes/update-system-design.md
The baseline lane is the whole-OS bump — fresh nixpkgs pin, full gauntlet, channel-promoted, cadenced. The security lane overrides just the vulnerable package on the current baseline (the cosmic-comp override technique), rebuilds only that sub-closure, re-signs, and ships as 0.0.5 → 0.0.5.1+sec. Nix means patching one CVE never requires a full pin bump.
Shippable artifacts = the core OS image + each catalog VM (firefox, OSE, …), each its own closure. The trigger graph is computed from closures, not guessed:
Coalesce changes per window; a rebuilt path (patched openssl) is built once and substituted everywhere. No blanket rebuilds, ever.
Tier 0 (TCB): kernel, VMM (cloud-hypervisor/crosvm), bond broker, verity/crypto, signing, compositor surface → always fast-track. Tier 1 (parsers/crypto/edge): openssl, image/font/media parsers → fast-track on high severity. Tier 2 (compartmentalized apps): FreeCAD, editors → batch; a bug is trapped in its VM behind the IOMMU. The isolation boundary earns the right to hold Tier 2.
Store paths are content-addressed and immutable: an update creates a new path; the old one persists until GC. A VM is a pinned closure — lean (shares present paths) and stable (its exact paths never move). Updating a VM = a new generation (atomic switch, roll back to the prior one whose paths still exist); each generation is a gcroot that keeps its paths. A host security overlay just makes a patched path available; each VM adopts it on its own schedule, with rollback — never force-broken.
No artifact ships until its test suite passes (never narrow the check). Core OS gauntlet: compile, headless boot, compartment-role checks, presence socket, trust rings, scene_fails=0, PLUS bond-grant flow and apply-then-rollback. Per-VM smoke test: its own done-criterion (firefox launches + renders; FreeCAD/KiCad open). Channel soak IS the extended test: chaos → alpha → … catches what the gauntlet misses before stable users see it.
Delivery to existing users is the A/B verity image: a security point release lands on the inactive partition, atomic switch, one reboot rolls back. The client polls latest.json for its channel and marks +sec vs feature. New users always pull the latest image with all overlays folded in — patched on first boot.
Where does this break? Especially: the coalescing-window vs security-urgency tension; whether per-VM generations + rollback is the right UX or too much machinery; failure modes of the closure-computed trigger graph; and any update-experience angles we're missing for a non-expert user.
Hammer out: (1) the closure→artifacts trigger-graph query (given a store path, which shippable artifacts contain it); (2) the security-watch lane (pin diff + CVE feed → candidates); (3) the security-overlay builder + gauntlet gate; (4) per-artifact smoke-test harness. Reuse the existing release-bom / latest.json / gauntlet tooling.