commit 09bb57ed3f3c34fe6da2d13478dcdfbcfc77d3c6
parent 4b0039194d188083b9def3473d99d6ab8410e498
Author: triesap <tyson@radroots.org>
Date: Mon, 7 Sep 2026 02:16:15 +0000
feat(nix): build governed CLI outputs
- Replace checkout wrappers with a real Crane-built radroots package.
- Expose one package, check, and application on the two governed systems.
- Remove development-shell, module, OCI, and excluded-system outputs.
- Lock shared Nix tooling to the qualified Lib input and test the boundary.
Diffstat:
| M | README | | | 6 | +++++- |
| M | flake.lock | | | 120 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
| M | flake.nix | | | 216 | +++++++++++++++++++++++++++++-------------------------------------------------- |
| M | tests/package_boundary.rs | | | 34 | ++++++++++++++++++++++++++++++++++ |
4 files changed, 231 insertions(+), 145 deletions(-)
diff --git a/README b/README
@@ -92,7 +92,11 @@ material. The supply-chain command validates the exact locked dependency
graph, license policy, approved registries and immutable Lib source, then
rejects forbidden capsule-local documentation and workflow roots. An
extbuild-enabled checkout routes these commands through `cargo extbuild run --
-...`. Nix and OCI are deferred and unclaimed through RCLD-RSHR-170.
+...`.
+
+The standalone flake exposes exactly one real `radroots` package, check, and
+application for `aarch64-darwin` and `x86_64-linux`. It exposes no checkout
+wrapper, development shell, NixOS module, OCI artifact, or other system.
## Copyright and license
diff --git a/flake.lock b/flake.lock
@@ -1,12 +1,71 @@
{
"nodes": {
+ "crane": {
+ "locked": {
+ "lastModified": 1766774972,
+ "narHash": "sha256-8qxEFpj4dVmIuPn9j9z6NTbU+hrcGjBOvaxTzre5HmM=",
+ "owner": "ipetkov",
+ "repo": "crane",
+ "rev": "01bc1d404a51a0a07e9d8759cd50a7903e218c82",
+ "type": "github"
+ },
+ "original": {
+ "owner": "ipetkov",
+ "repo": "crane",
+ "rev": "01bc1d404a51a0a07e9d8759cd50a7903e218c82",
+ "type": "github"
+ }
+ },
+ "flake-parts": {
+ "inputs": {
+ "nixpkgs-lib": "nixpkgs-lib"
+ },
+ "locked": {
+ "lastModified": 1772408722,
+ "narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "type": "github"
+ }
+ },
+ "lib": {
+ "inputs": {
+ "crane": [
+ "crane"
+ ],
+ "flake-parts": "flake-parts",
+ "nixpkgs": "nixpkgs",
+ "rust-overlay": "rust-overlay",
+ "treefmt-nix": "treefmt-nix"
+ },
+ "locked": {
+ "lastModified": 1788739124,
+ "narHash": "sha256-Aw8qbU1DrtxSYJKg0js6kexnKgVGFCjR34bgq+ZVAVo=",
+ "owner": "radrootslabs",
+ "repo": "lib",
+ "rev": "055096853fca95e15d0f813d33a14aca13be3881",
+ "type": "github"
+ },
+ "original": {
+ "owner": "radrootslabs",
+ "repo": "lib",
+ "rev": "055096853fca95e15d0f813d33a14aca13be3881",
+ "type": "github"
+ }
+ },
"nixpkgs": {
"locked": {
- "lastModified": 1775305101,
- "narHash": "sha256-/74n1oQPtKG52Yw41cbToxspxHbYz6O3vi+XEw16Qe8=",
+ "lastModified": 1773222311,
+ "narHash": "sha256-BHoB/XpbqoZkVYZCfXJXfkR+GXFqwb/4zbWnOr2cRcU=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "36a601196c4ebf49e035270e10b2d103fe39076b",
+ "rev": "0590cd39f728e129122770c029970378a79d076a",
"type": "github"
},
"original": {
@@ -16,24 +75,48 @@
"type": "github"
}
},
+ "nixpkgs-lib": {
+ "locked": {
+ "lastModified": 1772328832,
+ "narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=",
+ "owner": "nix-community",
+ "repo": "nixpkgs.lib",
+ "rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "nixpkgs.lib",
+ "type": "github"
+ }
+ },
"root": {
"inputs": {
- "nixpkgs": "nixpkgs",
- "rust-overlay": "rust-overlay"
+ "crane": "crane",
+ "lib": "lib",
+ "nixpkgs": [
+ "lib",
+ "nixpkgs"
+ ],
+ "rust-overlay": [
+ "lib",
+ "rust-overlay"
+ ]
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
+ "lib",
"nixpkgs"
]
},
"locked": {
- "lastModified": 1784350408,
- "narHash": "sha256-OstzLWL5t7Xe14xEC6GIMJCp0PrYNTSA0El7GG2av88=",
+ "lastModified": 1785131767,
+ "narHash": "sha256-VNbQv2P0zgaNh96mT4LrnX7hdXgiC5nBH+uvyrrVX7U=",
"owner": "oxalica",
"repo": "rust-overlay",
- "rev": "3c38e1e1ba9c8d7030f7b5a801398ea7d8a6fdc0",
+ "rev": "c67ce00525464a710971351c183ce67acb6ca827",
"type": "github"
},
"original": {
@@ -41,6 +124,27 @@
"repo": "rust-overlay",
"type": "github"
}
+ },
+ "treefmt-nix": {
+ "inputs": {
+ "nixpkgs": [
+ "lib",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1773297127,
+ "narHash": "sha256-6E/yhXP7Oy/NbXtf1ktzmU8SdVqJQ09HC/48ebEGBpk=",
+ "owner": "numtide",
+ "repo": "treefmt-nix",
+ "rev": "71b125cd05fbfd78cab3e070b73544abe24c5016",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "treefmt-nix",
+ "type": "github"
+ }
}
},
"root": "root",
diff --git a/flake.nix b/flake.nix
@@ -1,153 +1,97 @@
{
- description = "Command-line interface for Radroots";
+ description = "Radroots command-line interface";
inputs = {
- nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
- rust-overlay = {
- url = "github:oxalica/rust-overlay";
- inputs.nixpkgs.follows = "nixpkgs";
+ crane.url = "github:ipetkov/crane/01bc1d404a51a0a07e9d8759cd50a7903e218c82";
+ lib = {
+ url = "github:radrootslabs/lib/055096853fca95e15d0f813d33a14aca13be3881";
+ inputs.crane.follows = "crane";
};
+ nixpkgs.follows = "lib/nixpkgs";
+ rust-overlay.follows = "lib/rust-overlay";
};
outputs =
- { nixpkgs, rust-overlay, ... }:
+ {
+ crane,
+ lib,
+ nixpkgs,
+ rust-overlay,
+ ...
+ }:
let
- systems = [
- "aarch64-darwin"
- "aarch64-linux"
- "x86_64-darwin"
- "x86_64-linux"
- ];
+ systems = lib.lib.supportedSystems;
forAllSystems =
- f:
- nixpkgs.lib.genAttrs systems (
- system:
- let
- pkgs = import nixpkgs {
- inherit system;
- overlays = [ rust-overlay.overlays.default ];
- };
- rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
- basePackages =
- [
- pkgs.git
- pkgs.rustup
- rustToolchain
- pkgs.clang
- pkgs.llvmPackages.libclang
- pkgs.pkg-config
- ]
- ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [
- pkgs.darwin.libiconv
- ];
- libraryPath = pkgs.lib.makeLibraryPath basePackages;
- includePath = pkgs.lib.makeSearchPathOutput "dev" "include" basePackages;
- darwinLdFlags = pkgs.lib.optionalString pkgs.stdenv.isDarwin "-L${pkgs.darwin.libiconv}/lib";
- darwinRustFlags = pkgs.lib.optionalString pkgs.stdenv.isDarwin "-L native=${pkgs.darwin.libiconv}/lib";
- mkApp =
- name:
- {
- runtimeInputs ? basePackages,
- text,
- }:
- let
- script = pkgs.writeShellApplication {
- inherit name;
- inherit runtimeInputs;
- text = ''
- set -euo pipefail
- repo_root="$(git rev-parse --show-toplevel)"
- cd "$repo_root"
- ./tools/verify-repository-boundary.sh
- export LIBCLANG_PATH="${pkgs.llvmPackages.libclang.lib}/lib"
- export LIBRARY_PATH="${libraryPath}:''${LIBRARY_PATH:-}"
- export DYLD_FALLBACK_LIBRARY_PATH="${libraryPath}:''${DYLD_FALLBACK_LIBRARY_PATH:-}"
- export LDFLAGS="${darwinLdFlags} ''${LDFLAGS:-}"
- export NIX_LDFLAGS="${darwinLdFlags} ''${NIX_LDFLAGS:-}"
- export RUSTFLAGS="${darwinRustFlags} ''${RUSTFLAGS:-}"
- export CPATH="${includePath}:''${CPATH:-}"
- ${text}
- '';
- };
- in
- {
- type = "app";
- program = "${script}/bin/${name}";
- };
- in
- f {
- inherit
- basePackages
- darwinLdFlags
- darwinRustFlags
- includePath
- libraryPath
- mkApp
- pkgs
- rustToolchain
- ;
- }
+ function:
+ builtins.listToAttrs (
+ map (system: {
+ name = system;
+ value = function system;
+ }) systems
);
- in
- {
- apps = forAllSystems (
- {
- mkApp,
- ...
- }:
- rec {
- default = check;
- check = mkApp "check" {
- text = ''
- cargo metadata --format-version 1 --no-deps
- cargo check
- '';
+ cliOutputs =
+ system:
+ let
+ pkgs = import nixpkgs {
+ inherit system;
+ overlays = [ rust-overlay.overlays.default ];
};
- fmt = mkApp "fmt" {
- text = ''
- cargo fmt --package radroots_cli --check
- '';
+ toolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
+ craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
+ source = pkgs.lib.cleanSourceWith {
+ src = ./.;
+ filter =
+ path: type:
+ craneLib.filterCargoSources path type
+ || baseNameOf path == "README";
+ name = "radroots-cli-source";
};
- release-acceptance = mkApp "release-acceptance" {
- text = ''
- cargo fmt --package radroots_cli --check
- cargo metadata --format-version 1 --no-deps
- cargo check
- cargo test -j1 -- --test-threads=1
- '';
+ commonArgs = {
+ src = source;
+ cargoLock = ./Cargo.lock;
+ strictDeps = true;
+ doCheck = false;
};
- test = mkApp "test" {
- text = ''
- cargo test -j1 -- --test-threads=1
- '';
+ cargoArtifacts = craneLib.buildDepsOnly commonArgs;
+ package = craneLib.buildPackage (
+ commonArgs
+ // {
+ inherit cargoArtifacts;
+ pname = "radroots_cli";
+ version = "0.1.0";
+ CARGO_PROFILE = "release";
+ cargoExtraArgs = "--locked --package radroots_cli --bin radroots";
+ }
+ );
+ check = craneLib.mkCargoDerivation (
+ commonArgs
+ // {
+ inherit cargoArtifacts;
+ pname = "radroots-cli-check";
+ version = "1";
+ buildPhaseCargoCommand = "cargo check --locked --package radroots_cli --all-targets";
+ installPhaseCommand = "mkdir -p $out";
+ }
+ );
+ app = {
+ type = "app";
+ program = "${package}/bin/radroots";
+ meta.description = "Run the built radroots CLI";
};
- }
- );
-
- devShells = forAllSystems (
+ in
{
- basePackages,
- darwinLdFlags,
- darwinRustFlags,
- includePath,
- libraryPath,
- pkgs,
- ...
- }:
- {
- default = pkgs.mkShell {
- packages = basePackages;
- shellHook = ''
- export LIBCLANG_PATH="${pkgs.llvmPackages.libclang.lib}/lib"
- export LIBRARY_PATH="${libraryPath}:''${LIBRARY_PATH:-}"
- export DYLD_FALLBACK_LIBRARY_PATH="${libraryPath}:''${DYLD_FALLBACK_LIBRARY_PATH:-}"
- export LDFLAGS="${darwinLdFlags} ''${LDFLAGS:-}"
- export NIX_LDFLAGS="${darwinLdFlags} ''${NIX_LDFLAGS:-}"
- export RUSTFLAGS="${darwinRustFlags} ''${RUSTFLAGS:-}"
- export CPATH="${includePath}:''${CPATH:-}"
- '';
- };
- }
- );
+ inherit app check package;
+ };
+ in
+ {
+ packages = forAllSystems (system: {
+ default = (cliOutputs system).package;
+ });
+ checks = forAllSystems (system: {
+ default = (cliOutputs system).check;
+ });
+ apps = forAllSystems (system: {
+ default = (cliOutputs system).app;
+ });
};
}
diff --git a/tests/package_boundary.rs b/tests/package_boundary.rs
@@ -3,6 +3,7 @@
const ROOT: &str = include_str!("../src/lib.rs");
const CLI_ROOT: &str = include_str!("../src/cli/mod.rs");
const PUBLIC_API: &str = include_str!("../contracts/api_baselines/radroots_cli.txt");
+const FLAKE: &str = include_str!("../flake.nix");
#[test]
fn implementation_modules_are_private_and_api_is_root_only() {
@@ -39,3 +40,36 @@ fn implementation_modules_are_private_and_api_is_root_only() {
assert!(!PUBLIC_API.contains(dependency), "leaked {dependency}");
}
}
+
+#[test]
+fn nix_outputs_are_real_owned_and_exactly_bounded() {
+ for required in [
+ "github:radrootslabs/lib/055096853fca95e15d0f813d33a14aca13be3881",
+ "systems = lib.lib.supportedSystems",
+ "craneLib.buildPackage",
+ "craneLib.mkCargoDerivation",
+ "program = \"${package}/bin/radroots\"",
+ "default = (cliOutputs system).package",
+ "default = (cliOutputs system).check",
+ "default = (cliOutputs system).app",
+ ] {
+ assert!(
+ FLAKE.contains(required),
+ "missing governed Nix source: {required}"
+ );
+ }
+ for forbidden in [
+ "writeShellApplication",
+ "git rev-parse",
+ "repo_root",
+ "devShells",
+ "nixosModules",
+ "aarch64-linux",
+ "x86_64-darwin",
+ ] {
+ assert!(
+ !FLAKE.contains(forbidden),
+ "forbidden Nix surface is present: {forbidden}"
+ );
+ }
+}