rhi

Coordinated trade for connected markets
git clone https://radroots.dev/git/rhi.git
Log | Files | Refs | README | LICENSE

commit ddfc4b1719b7dbc0bbd5eec5d6697d10b44a570e
parent 432afc55df83633f43936c95dd5613c45a4e63c2
Author: triesap <tyson@radroots.org>
Date:   Sun, 23 Aug 2026 20:02:38 +0000

build: adopt service source-lock v2

- pin shared service-host and service-SQLite packages to the final Lib revision
- replace the predecessor lock and Nix command surface with native extbuild policy
- add source, package, and public-boundary guards

Diffstat:
MAGENTS.md | 33+++++++++++++++++++--------------
MCargo.lock | 451+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MCargo.toml | 58++++++++++++++++++++++++++++++++++++++--------------------
MREADME | 17+++++++++++------
Dflake.lock | 48------------------------------------------------
Dflake.nix | 174-------------------------------------------------------------------------------
Dradroots.lib.source-lock.v1.toml | 9---------
Aradroots.service.source-lock.v2.toml | 22++++++++++++++++++++++
Atests/build_policy.rs | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/package_boundary.rs | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtests/source_guards.rs | 23++++++++++++++++-------
11 files changed, 700 insertions(+), 278 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md @@ -32,8 +32,8 @@ ## 2. Authority and preflight - Before editing, read this file, `README`, `Cargo.toml`, - `radroots.lib.source-lock.v1.toml`, the relevant implementation and tests, - and `config.toml` or `flake.nix` when they are in scope. + `radroots.service.source-lock.v2.toml`, the relevant implementation and tests, + and `config.toml` when it is in scope. - `.radroots-consumer-root` is the standalone source-lock identity and must remain exactly `rhi`. The reserved pre-implementation evidence authority is `contracts/services_hardening/evidence_policy.v1.json`, and the reserved @@ -264,8 +264,8 @@ ## 9. Rust and test discipline - The final Rust baseline is edition 2024, resolver 3, and Rust/toolchain - 1.97.1. Keep `Cargo.toml`, `rust-toolchain.toml`, Cargo metadata, and Nix - toolchain resolution in exact agreement. + 1.97.1. Keep `Cargo.toml`, `rust-toolchain.toml`, and Cargo metadata in exact + agreement. - Keep `#![forbid(unsafe_code)]` at crate roots; unsafe code is forbidden. Deny broken rustdoc links, `dbg!`, `todo!`, and `unimplemented!` in production. - Prefer pure transformations, explicit state machines, validated newtypes, @@ -286,22 +286,27 @@ ## 10. Canonical verification -Use the repository-owned Nix lanes as standalone command surfaces: +Through RCLD-RSHR-170, run the standalone native command authority through +extbuild. Do not install, repair, invoke, or require Nix, and do not claim Nix, +NixOS-module, or Nix-produced OCI qualification: ```text -nix run .#fmt -nix run .#check -nix run .#test +cargo extbuild doctor +cargo extbuild run -- cargo fmt --all --check +cargo extbuild run -- cargo check --workspace --all-targets --locked +cargo extbuild run -- cargo test --workspace --all-targets --locked +cargo extbuild run -- cargo clippy --workspace --all-targets --locked -- -D warnings +cargo extbuild run -- env RUSTDOCFLAGS=-Dwarnings cargo doc --workspace --no-deps --locked ``` The complete release contract also requires locked all-target check and test with serialized tests, warnings-denied all-target Clippy, warnings-denied -rustdoc, the `source_guards` integration test, and diff hygiene. Run those gates -explicitly until a repository-owned aggregate enforces them; do not describe a -partial Nix lane as complete release acceptance. Run coverage, SQLx freshness, -source-lock, Nix flake, package, OCI, systemd, SBOM, checksum, notice, and -fresh-install gates when their surfaces change. Use narrower commands only for -iteration, and never claim a command passed unless it ran successfully. +rustdoc, the source-lock and package-boundary tests, and diff hygiene. Run +additional coverage, SQLx freshness, source-lock, package, systemd, SBOM, +checksum, notice, and fresh-install gates when their surfaces change. Nix and +OCI remain deferred and unclaimed through RCLD-RSHR-170. Use narrower commands +only for iteration, and never claim a command passed unless it ran +successfully. ## 11. Commits and irreversible actions diff --git a/Cargo.lock b/Cargo.lock @@ -146,12 +146,27 @@ dependencies = [ ] [[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] name = "atomic-destructor" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef49f5882e4b6afaac09ad239a4f8c70a24b8f2b0897edb1f706008efd109cf4" [[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -394,6 +409,21 @@ dependencies = [ ] [[package]] +name = "crc" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" + +[[package]] name = "crossbeam-channel" version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -403,6 +433,15 @@ dependencies = [ ] [[package]] +name = "crossbeam-queue" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" +dependencies = [ + "crossbeam-utils", +] + +[[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -479,10 +518,19 @@ dependencies = [ ] [[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] [[package]] name = "elliptic-curve" @@ -527,6 +575,16 @@ dependencies = [ ] [[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + +[[package]] name = "fancy-regex" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -571,6 +629,17 @@ dependencies = [ ] [[package]] +name = "flume" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + +[[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -602,6 +671,16 @@ dependencies = [ ] [[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] name = "futures" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -609,6 +688,7 @@ checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -643,12 +723,34 @@ dependencies = [ ] [[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] name = "futures-io" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] name = "futures-sink" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -669,6 +771,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -764,6 +867,11 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "hashbrown" @@ -777,6 +885,15 @@ dependencies = [ ] [[package]] +name = "hashlink" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824e001ac4f3012dd16a264bec811403a67ca9deb6c102fc5049b32c4574b35f" +dependencies = [ + "hashbrown 0.16.1", +] + +[[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -817,12 +934,76 @@ dependencies = [ ] [[package]] +name = "http-body" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] name = "httparse" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "bytes", + "http", + "http-body", + "hyper", + "pin-project-lite", + "tokio", +] + +[[package]] name = "icu_collections" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1083,6 +1264,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] +name = "libsqlite3-sys" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] name = "linux-raw-sys" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1356,6 +1548,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" [[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] name = "parking_lot" version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1412,6 +1610,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] +name = "pkg-config" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + +[[package]] name = "poly1305" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1596,6 +1800,58 @@ dependencies = [ ] [[package]] +name = "radroots_service_host" +version = "0.1.0-alpha" +source = "git+https://github.com/radrootslabs/lib?rev=7d7b454b4c9ed86569671993bd03ca868b676665#7d7b454b4c9ed86569671993bd03ca868b676665" +dependencies = [ + "bytes", + "fs2", + "getrandom 0.2.17", + "http", + "http-body-util", + "hyper", + "hyper-util", + "radroots_runtime_paths", + "rustix", + "serde", + "serde_json", + "tokio", + "tokio-util", + "toml", +] + +[[package]] +name = "radroots_service_sqlite" +version = "0.1.0-alpha" +source = "git+https://github.com/radrootslabs/lib?rev=7d7b454b4c9ed86569671993bd03ca868b676665#7d7b454b4c9ed86569671993bd03ca868b676665" +dependencies = [ + "fs2", + "futures", + "libsqlite3-sys", + "radroots_runtime_paths", + "radroots_storage", + "rustix", + "serde", + "serde_json", + "sha2", + "sqlx", + "tokio", +] + +[[package]] +name = "radroots_storage" +version = "0.1.0-alpha" +source = "git+https://github.com/radrootslabs/lib?rev=7d7b454b4c9ed86569671993bd03ca868b676665#7d7b454b4c9ed86569671993bd03ca868b676665" +dependencies = [ + "radroots_event", + "radroots_event_codec", + "radroots_protocol", + "radroots_trade", + "radroots_transport", + "sha2", +] + +[[package]] name = "radroots_trade" version = "0.1.0-alpha" source = "git+https://github.com/radrootslabs/lib?rev=7d7b454b4c9ed86569671993bd03ca868b676665#7d7b454b4c9ed86569671993bd03ca868b676665" @@ -1610,6 +1866,17 @@ dependencies = [ ] [[package]] +name = "radroots_transport" +version = "0.1.0-alpha" +source = "git+https://github.com/radrootslabs/lib?rev=7d7b454b4c9ed86569671993bd03ca868b676665#7d7b454b4c9ed86569671993bd03ca868b676665" +dependencies = [ + "radroots_event", + "radroots_identity", + "radroots_protocol", + "sha2", +] + +[[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1761,6 +2028,8 @@ dependencies = [ "radroots_protocol", "radroots_runtime_paths", "radroots_secrets", + "radroots_service_host", + "radroots_service_sqlite", "radroots_trade", "rand 0.9.2", "serde", @@ -2043,6 +2312,119 @@ dependencies = [ ] [[package]] +name = "spin" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sqlx" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "378620ccc25c62c89d8be1c819e76a88d59bdcc3304733330788948e619bfd71" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b44e85bf579a8eeb4ceaa77a3a523baf2bf0e9bac7e40f405d537b5d2d5ccb" +dependencies = [ + "base64", + "bytes", + "cfg-if", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.16.1", + "hashlink", + "indexmap", + "log", + "memchr", + "percent-encoding", + "serde", + "sha2", + "smallvec", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd2b84f2bc39a5705ef27ec785a11c934a41bbd4a24941e257927cddc26b60bf" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.117", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb8d96de5fdc85a5c4ec813432b523ec637e80ba98f046555f75f7908ddac7c3" +dependencies = [ + "cfg-if", + "dotenvy", + "either", + "heck", + "hex", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-sqlite", + "syn 2.0.117", + "tokio", + "url", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488e99c397a62007e4229aec669a179816339afc6d2620ca6fa420dbee2e982c" +dependencies = [ + "atoi", + "flume", + "form_urlencoded", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "sqlx-core", + "thiserror 2.0.18", + "tracing", + "url", +] + +[[package]] name = "stable_deref_trait" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2283,6 +2665,17 @@ dependencies = [ ] [[package]] +name = "tokio-stream" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] name = "tokio-tungstenite" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2299,6 +2692,20 @@ dependencies = [ ] [[package]] +name = "tokio-util" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] name = "toml" version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2345,6 +2752,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2413,6 +2821,12 @@ dependencies = [ ] [[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] name = "tungstenite" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2546,6 +2960,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2558,6 +2978,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" [[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2703,6 +3132,28 @@ dependencies = [ ] [[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml @@ -6,35 +6,53 @@ authors = ["Radroots Authors"] rust-version = "1.97.1" license = "AGPL-3.0-or-later" description = "Radroots trade agreement attestation worker" +repository = "https://github.com/radrootslabs/rhi" +readme = "README" +publish = false [workspace] resolver = "3" -[workspace.dependencies] -radroots_event = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } -radroots_event_codec = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } -radroots_identity = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } -radroots_nostr = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } -radroots_protocol = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } -radroots_runtime_paths = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } -radroots_secrets = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } -radroots_trade = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } +[workspace.metadata.radroots.service_source_lock] +service = "rhi" +host_feature_profile = "service-host" +nix_material = "absent" +config_contract_version = 1 +state_contract_version = 1 +admin_contract_version = 1 +status_contract_version = 1 +provider_contract_version = 1 + +[workspace.lints.rust] +unsafe_code = "deny" +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] } + +[workspace.lints.rustdoc] +broken_intra_doc_links = "deny" + +[workspace.lints.clippy] +dbg_macro = "deny" +todo = "deny" +unimplemented = "deny" [features] -default = [] +default = ["service-host"] +service-host = [] -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] } +[lints] +workspace = true [dependencies] -radroots_event = { workspace = true, features = ["serde"] } -radroots_event_codec = { workspace = true, features = ["json"] } -radroots_identity = { workspace = true } -radroots_nostr = { workspace = true, features = ["events"] } -radroots_protocol = { workspace = true } -radroots_runtime_paths = { workspace = true } -radroots_secrets = { workspace = true } -radroots_trade = { workspace = true } +radroots_event = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha", features = ["serde"] } +radroots_event_codec = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha", features = ["json"] } +radroots_identity = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } +radroots_nostr = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha", features = ["events"] } +radroots_protocol = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } +radroots_runtime_paths = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } +radroots_service_host = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } +radroots_service_sqlite = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } +radroots_secrets = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } +radroots_trade = { git = "https://github.com/radrootslabs/lib", rev = "7d7b454b4c9ed86569671993bd03ca868b676665", version = "=0.1.0-alpha" } anyhow = { version = "1" } chacha20poly1305 = { version = "0.10" } diff --git a/README b/README @@ -77,16 +77,21 @@ injected host environment defined by `radroots_runtime_paths`; repo-local uses one explicit absolute base and the same `services/rhi/<instance>` namespace. Path resolution performs no directory creation or filesystem I/O. -Use the repository-owned Nix lanes for validation: +Validate the standalone crate through extbuild: ```text -nix run .#fmt -nix run .#check -nix run .#test +cargo extbuild doctor +cargo extbuild run -- cargo fmt --all --check +cargo extbuild run -- cargo check --workspace --all-targets --locked +cargo extbuild run -- cargo test --workspace --all-targets --locked +cargo extbuild run -- cargo clippy --workspace --all-targets --locked -- -D warnings +cargo extbuild run -- env RUSTDOCFLAGS=-Dwarnings cargo doc --workspace --no-deps --locked ``` -Use `nix develop` to enter the repository's development shell before running -narrower ad hoc Cargo commands from this repository root. +Through RCLD-RSHR-170, Nix evaluation, builds, packages, NixOS modules, and +Nix-produced OCI artifacts are deferred and unclaimed. Do not install, repair, +invoke, or require Nix for these checkpoints. Run narrower ad hoc Cargo +commands through `cargo extbuild run --` from this repository root. ## Copyright diff --git a/flake.lock b/flake.lock @@ -1,48 +0,0 @@ -{ - "nodes": { - "nixpkgs": { - "locked": { - "lastModified": 1774799055, - "narHash": "sha256-Tsq9BCz0q47ej1uFF39m4tuhcwru/ls6vCCJzutEpaw=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "107cba9eb4a8d8c9f8e9e61266d78d340867913a", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-25.11", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "nixpkgs": "nixpkgs", - "rust-overlay": "rust-overlay" - } - }, - "rust-overlay": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1786160316, - "narHash": "sha256-oLoc3ZLg1LX/S5Jb3v6MrF415AzDyC4vgeWy9UcYTQk=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "4e1c940c96560ceab7c547f89642231371a66646", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix @@ -1,174 +0,0 @@ -{ - description = "rhi"; - - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; - rust-overlay = { - url = "github:oxalica/rust-overlay"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - }; - - outputs = - { nixpkgs, rust-overlay, ... }: - let - systems = [ - "aarch64-darwin" - "aarch64-linux" - "x86_64-darwin" - "x86_64-linux" - ]; - 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 - rustToolchain - pkgs.clang - pkgs.llvmPackages.libclang - pkgs.libsodium - pkgs.openssl - pkgs.pkg-config - pkgs.sqlite - ] - ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ - pkgs.darwin.libiconv - ]; - libraryPath = pkgs.lib.makeLibraryPath basePackages; - includePath = pkgs.lib.makeSearchPathOutput "dev" "include" basePackages; - llvmToolsBin = "${pkgs.llvmPackages.llvm}/bin"; - 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"; - coveragePackages = basePackages ++ [ - pkgs.llvmPackages.llvm - ]; - 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" - 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 - coveragePackages - darwinLdFlags - darwinRustFlags - includePath - libraryPath - llvmToolsBin - mkApp - pkgs - rustToolchain - ; - } - ); - in - { - apps = forAllSystems ( - { - coveragePackages, - llvmToolsBin, - mkApp, - ... - }: - rec { - default = check; - check = mkApp "check" { - text = '' - cargo metadata --format-version 1 --no-deps - cargo check --workspace --all-targets - ''; - }; - coverage-report = mkApp "coverage-report" { - runtimeInputs = coveragePackages; - text = '' - export PATH="$HOME/.cargo/bin:$PATH" - cargo +nightly llvm-cov --version >/dev/null 2>&1 || { - echo "cargo +nightly llvm-cov must be available to run coverage-report" >&2 - exit 1 - } - export LLVM_COV="${llvmToolsBin}/llvm-cov" - export LLVM_PROFDATA="${llvmToolsBin}/llvm-profdata" - mkdir -p target/coverage - cargo +nightly llvm-cov clean --workspace - cargo +nightly llvm-cov --workspace --all-features --branch --no-report - cargo +nightly llvm-cov report --json --summary-only --output-path target/coverage/summary.json - cargo +nightly llvm-cov report --lcov --output-path target/coverage/lcov.info - cargo +nightly llvm-cov report --summary-only - echo "coverage summary: target/coverage/summary.json" - echo "coverage lcov: target/coverage/lcov.info" - ''; - }; - fmt = mkApp "fmt" { - text = '' - cargo fmt --all --check - ''; - }; - test = mkApp "test" { - text = '' - cargo test -- --test-threads=1 - ''; - }; - } - ); - - devShells = forAllSystems ( - { - 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:-}" - ''; - }; - } - ); - }; -} diff --git a/radroots.lib.source-lock.v1.toml b/radroots.lib.source-lock.v1.toml @@ -1,9 +0,0 @@ -schema = "radroots.lib.source-lock.v1" -repository = "https://github.com/radrootslabs/lib" -revision = "7d7b454b4c9ed86569671993bd03ca868b676665" -architecture = "radroots.crates.release.v2" -workspace_catalog_sha256 = "deca0c080deae187ff8186c0708903e42f41ea57f77c5f91581e23aa561164a4" -version = "0.1.0-alpha" -source_archive_sha256 = "b425371c134be96cce46b37f7035d6212f1efe8cff50bef366631ba5632991b0" -lockfile = "Cargo.lock" -lockfile_sha256 = "42a3f375556257d05db86bbeaa59d3a96f040afaa85b4293f238a7da98d95fde" diff --git a/radroots.service.source-lock.v2.toml b/radroots.service.source-lock.v2.toml @@ -0,0 +1,22 @@ +schema = "radroots.service.source-lock.v2" +contract_version = 2 +service = "rhi" +repository = "https://github.com/radrootslabs/lib" +revision = "7d7b454b4c9ed86569671993bd03ca868b676665" +architecture = "radroots.crates.release.v2" +workspace_catalog_sha256 = "deca0c080deae187ff8186c0708903e42f41ea57f77c5f91581e23aa561164a4" +version = "0.1.0-alpha" +source_archive_sha256 = "b425371c134be96cce46b37f7035d6212f1efe8cff50bef366631ba5632991b0" +cargo_lock_sha256 = "ba1cca624b0b2fbc49e82bc392b4cc1bf80a9ffcb5bd86e15ffed2818075f565" +rust_version = "1.97.1" +host_feature_profile = "service-host" + +[nix] +material = "absent" + +[contract_versions] +config = 1 +state = 1 +admin = 1 +status = 1 +provider = 1 diff --git a/tests/build_policy.rs b/tests/build_policy.rs @@ -0,0 +1,81 @@ +#![forbid(unsafe_code)] + +use sha2::{Digest, Sha256}; + +const MANIFEST: &str = include_str!("../Cargo.toml"); +const SOURCE_LOCK: &str = include_str!("../radroots.service.source-lock.v2.toml"); + +#[test] +fn manifest_freezes_the_native_service_policy() { + assert!(MANIFEST.contains( + "repository = \"https://github.com/radrootslabs/rhi\"\nreadme = \"README\"\npublish = false" + )); + assert!(MANIFEST.contains("[workspace]\nresolver = \"3\"")); + assert!(MANIFEST.contains("[workspace.lints.rust]\nunsafe_code = \"deny\"")); + assert!(MANIFEST.contains("[workspace.lints.rustdoc]\nbroken_intra_doc_links = \"deny\"")); + assert!(MANIFEST.contains( + "[workspace.lints.clippy]\ndbg_macro = \"deny\"\ntodo = \"deny\"\nunimplemented = \"deny\"" + )); + assert!(MANIFEST.contains("[lints]\nworkspace = true")); + assert!(MANIFEST.contains("[features]\ndefault = [\"service-host\"]\nservice-host = []")); +} + +#[test] +fn source_lock_metadata_is_exact_and_nix_is_absent() { + assert!(MANIFEST.contains( + "[workspace.metadata.radroots.service_source_lock]\nservice = \"rhi\"\nhost_feature_profile = \"service-host\"\nnix_material = \"absent\"" + )); + for field in [ + "config_contract_version = 1", + "state_contract_version = 1", + "admin_contract_version = 1", + "status_contract_version = 1", + "provider_contract_version = 1", + ] { + assert!( + MANIFEST.contains(field), + "missing source-lock field {field}" + ); + } +} + +#[test] +fn shared_host_packages_are_exactly_source_locked() { + for dependency in ["radroots_service_host", "radroots_service_sqlite"] { + assert!(MANIFEST.contains(&format!( + "{dependency} = {{ git = \"https://github.com/radrootslabs/lib\", rev = \"7d7b454b4c9ed86569671993bd03ca868b676665\", version = \"=0.1.0-alpha\" }}" + ))); + } +} + +#[test] +fn source_lock_binds_the_current_cargo_lock() { + let digest = lower_hex(&Sha256::digest(include_bytes!("../Cargo.lock"))); + assert!(SOURCE_LOCK.starts_with( + "schema = \"radroots.service.source-lock.v2\"\ncontract_version = 2\nservice = \"rhi\"\n" + )); + assert!(SOURCE_LOCK.contains(&format!("cargo_lock_sha256 = \"{digest}\""))); + assert!(SOURCE_LOCK.contains("revision = \"7d7b454b4c9ed86569671993bd03ca868b676665\"")); + assert!(SOURCE_LOCK.contains( + "workspace_catalog_sha256 = \"deca0c080deae187ff8186c0708903e42f41ea57f77c5f91581e23aa561164a4\"" + )); + assert!(SOURCE_LOCK.contains( + "source_archive_sha256 = \"b425371c134be96cce46b37f7035d6212f1efe8cff50bef366631ba5632991b0\"" + )); + assert!(SOURCE_LOCK.contains("\n[nix]\nmaterial = \"absent\"\n")); + assert!(!SOURCE_LOCK.contains("flake_lock_sha256")); + assert!(!SOURCE_LOCK.contains("lib_revision =")); + assert!(SOURCE_LOCK.ends_with( + "[contract_versions]\nconfig = 1\nstate = 1\nadmin = 1\nstatus = 1\nprovider = 1\n" + )); +} + +fn lower_hex(bytes: &[u8]) -> String { + const DIGITS: &[u8; 16] = b"0123456789abcdef"; + let mut output = String::with_capacity(bytes.len() * 2); + for byte in bytes { + output.push(char::from(DIGITS[usize::from(byte >> 4)])); + output.push(char::from(DIGITS[usize::from(byte & 0x0f)])); + } + output +} diff --git a/tests/package_boundary.rs b/tests/package_boundary.rs @@ -0,0 +1,62 @@ +#![forbid(unsafe_code)] + +const MANIFEST: &str = include_str!("../Cargo.toml"); +const README: &str = include_str!("../README"); +const ROOT: &str = include_str!("../src/lib.rs"); + +#[test] +fn package_identity_is_standalone_and_non_publishable() { + assert!(MANIFEST.contains("name = \"rhi\"")); + assert!(MANIFEST.contains("repository = \"https://github.com/radrootslabs/rhi\"")); + assert!(MANIFEST.contains("readme = \"README\"")); + assert!(MANIFEST.contains("publish = false")); + for forbidden in [ + "path = \"../", + "path = \"../../", + "enterprise/", + "ops/", + "foundation/", + ] { + assert!( + !MANIFEST.contains(forbidden), + "standalone package retains forbidden dependency surface {forbidden}" + ); + } +} + +#[test] +fn shared_host_implementations_do_not_escape_the_public_api() { + for forbidden in [ + "pub use radroots_service_host", + "pub use radroots_service_sqlite", + "pub mod service_host", + "pub mod service_sqlite", + "sqlx::Pool", + "sqlx::SqliteConnection", + ] { + assert!( + !ROOT.contains(forbidden), + "RHI public root exposes private host implementation {forbidden}" + ); + } +} + +#[test] +fn human_verification_contract_is_extbuild_only_through_rcld_170() { + for required in [ + "cargo extbuild doctor", + "cargo extbuild run -- cargo fmt --all --check", + "cargo extbuild run -- cargo check --workspace --all-targets --locked", + "cargo extbuild run -- cargo test --workspace --all-targets --locked", + "cargo extbuild run -- cargo clippy --workspace --all-targets --locked -- -D warnings", + "Nix-produced OCI artifacts are deferred and unclaimed", + ] { + assert!(README.contains(required), "README is missing {required}"); + } + for forbidden in ["nix run", "nix develop", "nix build", "nix flake"] { + assert!( + !README.contains(forbidden), + "README retains forbidden active Nix command {forbidden}" + ); + } +} diff --git a/tests/source_guards.rs b/tests/source_guards.rs @@ -13,7 +13,6 @@ fn rhi_manifest_has_no_sdk_or_legacy_proof_dependency() { "sp1_proving", "sp1_cuda_proving", "reqwest", - "sqlx", "libsqlite3-sys", ] { assert!( @@ -26,19 +25,29 @@ fn rhi_manifest_has_no_sdk_or_legacy_proof_dependency() { #[test] fn rhi_manifest_exact_pins_radroots_contract() { let manifest: toml::Value = toml::from_str(&read_repo_file("Cargo.toml")).expect("manifest"); - let dependencies = manifest["workspace"]["dependencies"] + let dependencies = manifest["dependencies"] .as_table() - .expect("workspace dependencies"); + .expect("package dependencies"); for (name, dependency) in dependencies { if !name.starts_with("radroots_") { continue; } - let version = dependency - .as_str() - .or_else(|| dependency.get("version").and_then(toml::Value::as_str)); + let dependency = dependency + .as_table() + .unwrap_or_else(|| panic!("{name} must use an explicit dependency table")); assert_eq!( - version, + dependency.get("git").and_then(toml::Value::as_str), + Some("https://github.com/radrootslabs/lib"), + "RHI must source {name} from the governed public Lib repository" + ); + assert_eq!( + dependency.get("rev").and_then(toml::Value::as_str), + Some("7d7b454b4c9ed86569671993bd03ca868b676665"), + "RHI must source-lock {name} to the exact promoted Lib revision" + ); + assert_eq!( + dependency.get("version").and_then(toml::Value::as_str), Some("=0.1.0-alpha"), "RHI must exact-pin {name} to the governed event contract release" );