cli

Command-line interface for Radroots
git clone https://radroots.dev/git/cli.git
Log | Files | Refs | README | LICENSE

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:
MREADME | 6+++++-
Mflake.lock | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mflake.nix | 216+++++++++++++++++++++++++++++--------------------------------------------------
Mtests/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}" + ); + } +}