Skip to content

Nixify the toolchain: flake devShell (pinned Verus + Microkit SDK + aarch64 cross), supersede the Dockerfile plan (ADR-0002) #1

Description

@quinn-dougherty

Summary

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.lock is 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)

  1. Writing + maintaining the two blob derivations; autoPatchelf on prebuilt ELFs can need iteration.
  2. 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.
  3. Onboarding curve for the convened experts (seL4 / Verus / TLA+ reviewers, §6) who may not use Nix — mitigated by nix develop being a single command.

Proposed scope (devShell-first)

  • flake.nix providing a nix develop shell pinning: Verus 0.2026.07.05.49b8806, Microkit SDK 2.2.0, aarch64 cross-GCC (or aarch64-none-elf), qemu, z3, uv, TLA+/TLC, make/dtc/pdftotext.
  • 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).
  • NixOS-as-host or CI runner migration.

References

Context: discussed during Phase-0 wrap-up after Gate G0 (kv-alloc proofs green, invariants v1, Microkit hello-world booting in QEMU). Filed per request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions