You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adopt a Nix flake (nix develop devShell first) as the pinned, reproducible toolchain for VIS, superseding the "one hash-pinned Dockerfile" approach currently prescribed in CLAUDE.md §5 (Phase 0) and §8 (CI). Track the decision as ADR-0002 in docs/decisions/.
Why this fits VIS specifically
The project's thesis is reproducibility and an enumerable set of trusted inputs (CLAUDE.md §2.5, §4, §8; docs/tcb-ledger.md). A flake's flake.lockis that manifest: every compiler and every downloaded vendor binary is content-addressed by sha256. That is strictly stronger than a Docker image tag (which pins a tag, not the closure) and directly feeds the TCB-provenance story the Phase-4 spec package is meant to ship. For a formal-methods deliverable, the stronger guarantee is load-bearing, not cosmetic.
It also removes friction we already hit during Phase-0 bring-up:
The Microkit hello-world bring-up had to guess an ARM-toolchain download URL that can 404 over time.
We currently juggle vendor/arm-gnu-toolchain-*/bin on PATH plus a ./verus symlink into gitignored vendor/. nix develop replaces all of that with one hermetic shell.
Feasibility of the toolchain inputs
Already in nixpkgs (one line each):qemu, z3, dtc, uv, TLA+/TLC tooling, and pkgsCross.aarch64-* cross-GCC.
Verus (0.2026.07.05.49b8806, currently fetched as a GitHub release zip): not in nixpkgs yet, but there is an upstream in-progress flake.nix (Nix devshell verus-lang/verus#1231) and an open nixpkgs package request (Package request: verus NixOS/nixpkgs#309393). Fallback: fetchurl the pinned release + autoPatchelf (it bundles its own z3) — the same blob we already download.
Microkit SDK (2.2.0, prebuilt tarball): seL4/Microkit's dev env explicitly supports Nix setups; package it as fetchurl + autoPatchelfHook.
Net: the majority is nixpkgs; the two vendor blobs (Verus, Microkit) become pinned fetchurl derivations, which is strictly more honest than the ad-hoc curls we do today.
Costs / risks (honest accounting)
Writing + maintaining the two blob derivations; autoPatchelf on prebuilt ELFs can need iteration.
Supersedes the Dockerfile decision baked into §5/§8 → requires an ADR (irreversible-ish tooling choice per §4). Note it is not either/or: a flake can emit an OCI image via dockerTools, so we keep a Docker artifact for anyone who wants one.
Onboarding curve for the convened experts (seL4 / Verus / TLA+ reviewers, §6) who may not use Nix — mitigated by nix develop being a single command.
Pin the two vendor blobs (Verus, Microkit) via fetchurl + sha256; drop the ./verus symlink and vendor/ PATH juggling.
Wire ci/verify-all.sh and platform/qemu/run-hello.sh to run under nix develop -c ... identically local and in CI.
Acceptance:nix develop -c ./ci/verify-all.sh reproduces the kv-alloc Verus proof green (7 verified, 0 errors) AND nix develop -c bash platform/qemu/run-hello.sh boots Microkit to the hello, world banner — both from a clean checkout.
Write ADR-0002 (supersede the "one Dockerfile" line in §5/§8; record the dockerTools image as the optional Docker output).
Defer full hermetic package builds of the crates/image to a follow-up; devShell is the MVP.
Out of scope (for this issue)
Full hermetic Nix builds of every crate / the seL4 image (follow-up).
Summary
Adopt a Nix flake (
nix developdevShell first) as the pinned, reproducible toolchain for VIS, superseding the "one hash-pinned Dockerfile" approach currently prescribed inCLAUDE.md§5 (Phase 0) and §8 (CI). Track the decision as ADR-0002 indocs/decisions/.Why this fits VIS specifically
The project's thesis is reproducibility and an enumerable set of trusted inputs (
CLAUDE.md§2.5, §4, §8;docs/tcb-ledger.md). A flake'sflake.lockis that manifest: every compiler and every downloaded vendor binary is content-addressed by sha256. That is strictly stronger than a Docker image tag (which pins a tag, not the closure) and directly feeds the TCB-provenance story the Phase-4 spec package is meant to ship. For a formal-methods deliverable, the stronger guarantee is load-bearing, not cosmetic.It also removes friction we already hit during Phase-0 bring-up:
vendor/arm-gnu-toolchain-*/binonPATHplus a./verussymlink into gitignoredvendor/.nix developreplaces all of that with one hermetic shell.Feasibility of the toolchain inputs
qemu,z3,dtc,uv, TLA+/TLC tooling, andpkgsCross.aarch64-*cross-GCC.flake.nix(Nix devshell verus-lang/verus#1231) and an open nixpkgs package request (Package request: verus NixOS/nixpkgs#309393). Fallback:fetchurlthe pinned release +autoPatchelf(it bundles its own z3) — the same blob we already download.fetchurl+autoPatchelfHook.Net: the majority is nixpkgs; the two vendor blobs (Verus, Microkit) become pinned
fetchurlderivations, which is strictly more honest than the ad-hoccurls we do today.Costs / risks (honest accounting)
autoPatchelfon prebuilt ELFs can need iteration.dockerTools, so we keep a Docker artifact for anyone who wants one.nix developbeing a single command.Proposed scope (devShell-first)
flake.nixproviding anix developshell pinning: Verus 0.2026.07.05.49b8806, Microkit SDK 2.2.0, aarch64 cross-GCC (oraarch64-none-elf), qemu, z3,uv, TLA+/TLC,make/dtc/pdftotext.fetchurl+ sha256; drop the./verussymlink andvendor/PATH juggling.ci/verify-all.shandplatform/qemu/run-hello.shto run undernix develop -c ...identically local and in CI.nix develop -c ./ci/verify-all.shreproduces the kv-alloc Verus proof green (7 verified, 0 errors) ANDnix develop -c bash platform/qemu/run-hello.shboots Microkit to thehello, worldbanner — both from a clean checkout.dockerToolsimage as the optional Docker output).Out of scope (for this issue)
References
pkgsCross.aarch64-*for the cross toolchainContext: discussed during Phase-0 wrap-up after Gate G0 (kv-alloc proofs green, invariants v1, Microkit hello-world booting in QEMU). Filed per request.