lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit b917293748074783dc6202aa0553536bde8247a1
parent 90eaea3b890e0c6d54a19810b14e1feafc882186
Author: triesap <tyson@radroots.org>
Date:   Sun,  6 Sep 2026 22:48:57 +0000

build: define exact unsigned artifact targets

- Add the frozen service source-lock v3 schema.
- Bind the Lib unsigned artifact contract.
- Narrow native and Nix systems to the supported pair.
- Reject excluded target and contract mutations.

Diffstat:
Mbuild/nix/service/systems.nix | 2--
Acontracts/architecture/decisions/services_hardening_build_qualification.v3.json | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acontracts/architecture/decisions/services_hardening_source_lock.v3.json | 258+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acontracts/release/lib-artifact-contract.v3.json | 1+
Mcontracts/releases/target_matrix.toml | 5-----
Mtools/xtask/src/service_build_qualification.rs | 90++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mtools/xtask/src/target_qualification.rs | 61++++++++++++++++++++++++++++++++++++++++++++++++++++---------
7 files changed, 455 insertions(+), 30 deletions(-)

diff --git a/build/nix/service/systems.nix b/build/nix/service/systems.nix @@ -1,6 +1,4 @@ [ "aarch64-darwin" - "aarch64-linux" - "x86_64-darwin" "x86_64-linux" ] diff --git a/contracts/architecture/decisions/services_hardening_build_qualification.v3.json b/contracts/architecture/decisions/services_hardening_build_qualification.v3.json @@ -0,0 +1,68 @@ +{ + "schema": "radroots.services-hardening.build-qualification-decisions.v3", + "contract_version": 3, + "decision_state": "active", + "predecessor": { + "schema": "radroots.services-hardening.build-qualification-decisions.v2", + "filename": "services_hardening_build_qualification.v2.json", + "transition": "forward_only_replace" + }, + "qualification_scope": "native_and_nix_release_foundation", + "fixture_root": "tools/xtask/fixtures/service-build-qualification", + "supported_rust_targets": [ + "aarch64-apple-darwin", + "x86_64-unknown-linux-gnu" + ], + "supported_nix_systems": [ + "aarch64-darwin", + "x86_64-linux" + ], + "excluded_nix_systems": [ + "x86_64-darwin", + "aarch64-linux" + ], + "required_native_commands": [ + "cargo build --locked --release", + "cargo fmt --all --check", + "cargo check --workspace --all-targets --locked", + "cargo test --workspace --all-targets --locked", + "cargo clippy --workspace --all-targets --locked -- -D warnings", + "RUSTDOCFLAGS=-D warnings cargo doc --workspace --no-deps --locked" + ], + "required_xtask_commands": [ + "cargo test --locked -p xtask service_source_lock::tests", + "cargo test --locked -p xtask service_release_artifacts::tests", + "cargo test --locked -p xtask service_build_qualification::tests", + "cargo run --locked -q -p xtask -- contract validate", + "cargo run --locked -q -p xtask -- release preflight" + ], + "required_evidence": [ + "cargo_lock", + "source_lock", + "package_metadata", + "release_metadata", + "binary_archive", + "oci_source_artifact", + "cyclonedx_sbom", + "notices", + "artifact_manifest", + "unsigned_provenance_input", + "checksums" + ], + "fixture_source_lock": "tools/xtask/fixtures/service-build-qualification/radroots.service.source-lock.v2.toml", + "fixture_contract": "historical_v2_fixture_until_v3_service_instances_are_owned", + "release_artifact_command": "cargo xtask service-release-artifacts", + "source_lock_command": "cargo xtask service-source-lock", + "source_lock_v3_definition": "contracts/architecture/decisions/services_hardening_source_lock.v3.json", + "artifact_contract_v3": "contracts/release/lib-artifact-contract.v3.json", + "nix_output_implementation_owner_step": 299, + "signing_authority": "external_only", + "deferred_outputs": [ + "nix_packages", + "nix_apps", + "nix_checks", + "nix_development_shells", + "nixos_modules", + "nix_produced_oci" + ] +} diff --git a/contracts/architecture/decisions/services_hardening_source_lock.v3.json b/contracts/architecture/decisions/services_hardening_source_lock.v3.json @@ -0,0 +1,258 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "radroots.services-hardening.rshr-200-service-source-lock.v3", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "contract_version", + "service", + "repository", + "revision", + "architecture", + "workspace_catalog_sha256", + "version", + "source_archive_sha256", + "source_archive_contract", + "cargo_lock_sha256", + "rust_version", + "host_feature_profile", + "nix", + "artifact_contract", + "sqlite", + "contract_versions" + ], + "properties": { + "schema": { + "const": "radroots.service.source-lock.v3" + }, + "contract_version": { + "const": 3 + }, + "service": { + "enum": [ + "myc", + "rhi" + ] + }, + "repository": { + "const": "https://github.com/radrootslabs/lib" + }, + "revision": { + "$ref": "#/$defs/oid" + }, + "architecture": { + "const": "radroots.crates.release.v2" + }, + "workspace_catalog_sha256": { + "$ref": "#/$defs/sha256" + }, + "version": { + "const": "0.1.0-alpha" + }, + "source_archive_sha256": { + "$ref": "#/$defs/sha256" + }, + "source_archive_contract": { + "const": { + "binding": "sha256_of_canonical_exact_lib_revision_tree_archive", + "format": "ustar", + "compression": "none", + "compression_timestamp": "not_applicable", + "entry_order": "bytewise_git_path", + "path_prefix": "none", + "file_mode": "git_index_100644_or_100755", + "uid": 0, + "gid": 0, + "uname": "", + "gname": "", + "mtime": "lib_revision_commit_timestamp", + "pax_headers": "forbidden", + "directory_entries": "omitted", + "symlinks": "forbidden", + "hardlinks": "forbidden", + "submodules": "forbidden", + "trailer": "two_zero_blocks" + } + }, + "cargo_lock_sha256": { + "$ref": "#/$defs/sha256" + }, + "rust_version": { + "const": "1.97.1" + }, + "host_feature_profile": { + "const": "service-host" + }, + "nix": { + "type": "object", + "additionalProperties": false, + "required": [ + "material", + "lib_revision", + "public_input_lock", + "parent_result", + "supported_systems" + ], + "properties": { + "material": { + "const": "qualified" + }, + "lib_revision": { + "$ref": "#/$defs/oid" + }, + "public_input_lock": { + "type": "object", + "additionalProperties": false, + "required": [ + "path", + "sha256", + "binding", + "mutable_reference", + "lib_input" + ], + "properties": { + "path": { + "const": "flake.lock" + }, + "sha256": { + "$ref": "#/$defs/sha256" + }, + "binding": { + "const": "exact_regular_file_bytes" + }, + "mutable_reference": { + "const": "forbidden" + }, + "lib_input": { + "const": "lib" + } + } + }, + "parent_result": { + "const": { + "embedded_in_public_input_lock": false, + "embedded_in_source_lock": false, + "storage": "separate_generation_scoped_evidence" + } + }, + "supported_systems": { + "const": [ + "aarch64-darwin", + "x86_64-linux" + ] + } + } + }, + "artifact_contract": { + "type": "object", + "additionalProperties": false, + "required": [ + "path", + "sha256", + "binding" + ], + "properties": { + "path": { + "enum": [ + "contracts/release/myc-artifact-contract.v3.json", + "contracts/release/rhi-artifact-contract.v3.json" + ] + }, + "sha256": { + "$ref": "#/$defs/sha256" + }, + "binding": { + "const": "exact_regular_file_bytes_in_same_source_revision" + } + } + }, + "sqlite": { + "const": { + "high_level_authority": "sqlx_only", + "second_pool_connection_query_transaction_migration_authority": "forbidden", + "incremental_backup_adapter": "sealed_native_sqlx_owned_locked_handle_only", + "native_linkage_count": 1 + } + }, + "contract_versions": { + "type": "object", + "additionalProperties": false, + "required": [ + "config", + "state", + "admin", + "status", + "provider" + ], + "properties": { + "config": { + "$ref": "#/$defs/nonzero_u32" + }, + "state": { + "$ref": "#/$defs/nonzero_u32" + }, + "admin": { + "$ref": "#/$defs/nonzero_u32" + }, + "status": { + "$ref": "#/$defs/nonzero_u32" + }, + "provider": { + "$ref": "#/$defs/nonzero_u32" + } + } + } + }, + "allOf": [ + { + "if": { + "properties": { "service": { "const": "myc" } }, + "required": ["service"] + }, + "then": { + "properties": { + "artifact_contract": { + "properties": { + "path": { + "const": "contracts/release/myc-artifact-contract.v3.json" + } + } + } + } + } + }, + { + "if": { + "properties": { "service": { "const": "rhi" } }, + "required": ["service"] + }, + "then": { + "properties": { + "artifact_contract": { + "properties": { + "path": { + "const": "contracts/release/rhi-artifact-contract.v3.json" + } + } + } + } + } + } + ], + "$defs": { + "oid": { + "type": "string", + "pattern": "^[0-9a-f]{40}$" + }, + "sha256": { + "type": "string", + "pattern": "^[0-9a-f]{64}$" + }, + "nonzero_u32": { + "type": "integer", + "minimum": 1, + "maximum": 4294967295 + } + } +} diff --git a/contracts/release/lib-artifact-contract.v3.json b/contracts/release/lib-artifact-contract.v3.json @@ -0,0 +1 @@ +{"artifact_policy":{"checksums":"required","cyclonedx_version":"1.6","exact_tree_source_archives":"required","fresh_install":"required","git_history_bundles":"forbidden","intoto_statement":"required","notices":"required","reproducibility_build_count":2,"secret_scan":"required","unsigned_packages":"required","unsigned_slsa_provenance":"required"},"contract_version":3,"delivery":{"candidate_class":"unsigned_nonpublishing","developer_id_signing":"forbidden","developer_team_id":"forbidden","distribution_signing":"forbidden","embedded_platform_adhoc_signing":"permitted_non_distribution_only","g2":"unauthorized","notarization":"unauthorized","production_activation":"unauthorized","publication":"unauthorized","signing":"unauthorized"},"implementation_owner_step":298,"output":[{"classification":"production","id":"package","platforms":["macos_aarch64","linux_x86_64"]},{"classification":"production","id":"app","platforms":["macos_aarch64","linux_x86_64"]},{"classification":"production","id":"check","platforms":["macos_aarch64","linux_x86_64"]},{"classification":"production","id":"devshell","platforms":["macos_aarch64","linux_x86_64"]},{"classification":"production","id":"overlay","platforms":["macos_aarch64","linux_x86_64"]},{"classification":"production","id":"shared_helpers","platforms":["macos_aarch64","linux_x86_64"]},{"classification":"fixture_test_only_nondefault","id":"fixture_test_only_nondefault","platforms":["macos_aarch64","linux_x86_64"]}],"package_contract":{"app_role":"installed_release_bundle_inspection","artifact_format":"nix_store_derivation","cargo_package":"radroots","flake_app":"apps.<system>.default","flake_package":"packages.<system>.default","identity":"radroots_lib","package_role":"public_library_workspace_release_bundle","package_version":"0.1.0-alpha","product_version":"0.1.0-alpha"},"platforms":["macos_aarch64","linux_x86_64"],"producer":{"command_authority":"repository_flake","kind":"nix_flake","nix_binding":"required","nix_produced":true,"source_task":"nix_build_repository_outputs"},"repository":"oss/lib","schema":"radroots.release.artifact-contract.v3","source_archive":{"binding":"canonical_exact_source_revision_tree_archive","compression":"none","compression_timestamp":"not_applicable","content":"exact_source_revision_tree","directory_entries":"omitted","entry_order":"bytewise_git_path","file_mode":"git_index_100644_or_100755","format":"ustar","gid":0,"git_history":"forbidden","gname":"","hardlinks":"forbidden","mtime_source":"candidate_source_date_epoch","path_prefix":"none","pax_headers":"forbidden","submodules":"forbidden","symlinks":"forbidden","trailer":"two_zero_blocks","uid":0,"uname":""},"source_binding":{"dirty_tree":"forbidden","kind":"exact_clean_git_commit","revision_location":"aggregate_source_revision"},"sqlite":{"high_level_authority":"sqlx_only","incremental_backup_adapter":"sealed_native_sqlx_owned_locked_handle_only","native_linkage_count":1,"second_pool_connection_query_transaction_migration_authority":"forbidden"}} diff --git a/contracts/releases/target_matrix.toml b/contracts/releases/target_matrix.toml @@ -11,8 +11,3 @@ cross_cflags = "-target x86_64-linux-gnu" [[operating_system]] name = "macos" target = "aarch64-apple-darwin" - -[[operating_system]] -name = "windows" -target = "x86_64-pc-windows-gnu" -cross_compiler = "x86_64-w64-mingw32-gcc" diff --git a/tools/xtask/src/service_build_qualification.rs b/tools/xtask/src/service_build_qualification.rs @@ -8,17 +8,20 @@ use crate::service_source_lock::{ }; const CONTRACT_RELATIVE: &str = - "contracts/architecture/decisions/services_hardening_build_qualification.v2.json"; + "contracts/architecture/decisions/services_hardening_build_qualification.v3.json"; const FIXTURE_RELATIVE: &str = "tools/xtask/fixtures/service-build-qualification"; const MAX_CONTRACT_BYTES: usize = 32_768; const MAX_FIXTURE_FILE_BYTES: usize = 1_048_576; +const SOURCE_LOCK_V3_SHA256: &str = + "3bc32c8ca2cecb06c8f8239ab1fe1fcfba93fe3ef0d60e9b078390347d08f817"; +const ARTIFACT_CONTRACT_V3_SHA256: &str = + "bc352a132dd4c0e6f1d2ae7449998833efe1fdda2ab851e512bc9241c49edbf0"; +const NIX_SYSTEMS_RELATIVE: &str = "build/nix/service/systems.nix"; +const NIX_SYSTEMS_BYTES: &[u8] = b"[\n \"aarch64-darwin\"\n \"x86_64-linux\"\n]\n"; -const SUPPORTED_RUST_TARGETS: [&str; 4] = [ - "aarch64-apple-darwin", - "aarch64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-unknown-linux-gnu", -]; +const SUPPORTED_RUST_TARGETS: [&str; 2] = ["aarch64-apple-darwin", "x86_64-unknown-linux-gnu"]; +const SUPPORTED_NIX_SYSTEMS: [&str; 2] = ["aarch64-darwin", "x86_64-linux"]; +const EXCLUDED_NIX_SYSTEMS: [&str; 2] = ["x86_64-darwin", "aarch64-linux"]; const REQUIRED_XTASK_COMMANDS: [&str; 5] = [ "cargo test --locked -p xtask service_source_lock::tests", "cargo test --locked -p xtask service_release_artifacts::tests", @@ -83,6 +86,8 @@ struct BuildQualificationDecision { qualification_scope: String, fixture_root: String, supported_rust_targets: Vec<String>, + supported_nix_systems: Vec<String>, + excluded_nix_systems: Vec<String>, required_native_commands: Vec<String>, required_xtask_commands: Vec<String>, required_evidence: Vec<String>, @@ -90,6 +95,9 @@ struct BuildQualificationDecision { fixture_contract: String, release_artifact_command: String, source_lock_command: String, + source_lock_v3_definition: String, + artifact_contract_v3: String, + nix_output_implementation_owner_step: u32, signing_authority: String, deferred_outputs: Vec<String>, } @@ -115,28 +123,72 @@ fn validate_contract_inner(workspace_root: &Path) -> Result<(), BuildQualificati let decision = serde_json::from_slice::<BuildQualificationDecision>(&bytes) .map_err(|_| BuildQualificationError::InvalidContract)?; validate_decision(&decision)?; + validate_bound_contract( + workspace_root, + &decision.source_lock_v3_definition, + SOURCE_LOCK_V3_SHA256, + )?; + validate_bound_contract( + workspace_root, + &decision.artifact_contract_v3, + ARTIFACT_CONTRACT_V3_SHA256, + )?; + if read_bounded( + &workspace_root.join(NIX_SYSTEMS_RELATIVE), + 1_024, + BuildQualificationError::InvalidContract, + )? != NIX_SYSTEMS_BYTES + { + return Err(BuildQualificationError::InvalidContract); + } validate_fixture(workspace_root) } +fn validate_bound_contract( + workspace_root: &Path, + relative: &str, + expected_sha256: &str, +) -> Result<(), BuildQualificationError> { + let bytes = read_bounded( + &workspace_root.join(relative), + MAX_CONTRACT_BYTES, + BuildQualificationError::InvalidContract, + )?; + let _: serde_json::Value = + serde_json::from_slice(&bytes).map_err(|_| BuildQualificationError::InvalidContract)?; + if digest(&bytes) == expected_sha256 { + Ok(()) + } else { + Err(BuildQualificationError::InvalidContract) + } +} + fn validate_decision(decision: &BuildQualificationDecision) -> Result<(), BuildQualificationError> { - let exact = decision.schema == "radroots.services-hardening.build-qualification-decisions.v2" - && decision.contract_version == 2 + let exact = decision.schema == "radroots.services-hardening.build-qualification-decisions.v3" + && decision.contract_version == 3 && decision.decision_state == "active" && decision.predecessor.schema - == "radroots.services-hardening.build-qualification-decisions.v1" - && decision.predecessor.filename == "services_hardening_build_qualification.v1.json" + == "radroots.services-hardening.build-qualification-decisions.v2" + && decision.predecessor.filename == "services_hardening_build_qualification.v2.json" && decision.predecessor.transition == "forward_only_replace" - && decision.qualification_scope == "native_release_foundation" + && decision.qualification_scope == "native_and_nix_release_foundation" && decision.fixture_root == FIXTURE_RELATIVE && decision.supported_rust_targets == SUPPORTED_RUST_TARGETS + && decision.supported_nix_systems == SUPPORTED_NIX_SYSTEMS + && decision.excluded_nix_systems == EXCLUDED_NIX_SYSTEMS && decision.required_native_commands == REQUIRED_NATIVE_COMMANDS && decision.required_xtask_commands == REQUIRED_XTASK_COMMANDS && decision.required_evidence == REQUIRED_EVIDENCE && decision.fixture_source_lock == "tools/xtask/fixtures/service-build-qualification/radroots.service.source-lock.v2.toml" - && decision.fixture_contract == "source_lock_package_and_release_metadata_exact_agreement" + && decision.fixture_contract + == "historical_v2_fixture_until_v3_service_instances_are_owned" && decision.release_artifact_command == "cargo xtask service-release-artifacts" && decision.source_lock_command == "cargo xtask service-source-lock" + && decision.source_lock_v3_definition + == "contracts/architecture/decisions/services_hardening_source_lock.v3.json" + && decision.artifact_contract_v3 == "contracts/release/lib-artifact-contract.v3.json" + && decision.nix_output_implementation_owner_step == 299 && decision.signing_authority == "external_only" && decision.deferred_outputs == DEFERRED_OUTPUTS; if exact { @@ -314,6 +366,8 @@ mod tests { ("/qualification_scope", serde_json::json!("other")), ("/fixture_root", serde_json::json!("other")), ("/supported_rust_targets", serde_json::json!([])), + ("/supported_nix_systems", serde_json::json!([])), + ("/excluded_nix_systems", serde_json::json!([])), ("/required_native_commands", serde_json::json!([])), ("/required_xtask_commands", serde_json::json!([])), ("/required_evidence", serde_json::json!([])), @@ -321,6 +375,12 @@ mod tests { ("/fixture_contract", serde_json::json!("other")), ("/release_artifact_command", serde_json::json!("other")), ("/source_lock_command", serde_json::json!("other")), + ("/source_lock_v3_definition", serde_json::json!("other")), + ("/artifact_contract_v3", serde_json::json!("other")), + ( + "/nix_output_implementation_owner_step", + serde_json::json!(1), + ), ("/signing_authority", serde_json::json!("internal")), ("/deferred_outputs", serde_json::json!([])), ] { @@ -500,7 +560,9 @@ mod tests { #[test] fn contract_inventory_is_literal_and_complete() { - assert_eq!(SUPPORTED_RUST_TARGETS.len(), 4); + assert_eq!(SUPPORTED_RUST_TARGETS.len(), 2); + assert_eq!(SUPPORTED_NIX_SYSTEMS.len(), 2); + assert_eq!(EXCLUDED_NIX_SYSTEMS.len(), 2); assert_eq!(REQUIRED_NATIVE_COMMANDS.len(), 6); assert_eq!(REQUIRED_XTASK_COMMANDS.len(), 5); assert_eq!(REQUIRED_EVIDENCE.len(), 11); diff --git a/tools/xtask/src/target_qualification.rs b/tools/xtask/src/target_qualification.rs @@ -116,12 +116,6 @@ fn validate(matrix: &TargetMatrix) -> Result<(), String> { Some("-target x86_64-linux-gnu"), ), ("macos", "aarch64-apple-darwin", None, None), - ( - "windows", - "x86_64-pc-windows-gnu", - Some("x86_64-w64-mingw32-gcc"), - None, - ), ]; if matrix.operating_system.len() != expected.len() || expected.iter().any(|(name, target, compiler, cflags)| { @@ -134,7 +128,8 @@ fn validate(matrix: &TargetMatrix) -> Result<(), String> { }) { return Err( - "target matrix must contain the exact Linux, macOS, and Windows triples".to_owned(), + "target matrix must contain the exact Linux x86_64 and macOS aarch64 triples" + .to_owned(), ); } Ok(()) @@ -187,7 +182,7 @@ fn run_command(workspace_root: &Path, program: &str, args: &[&str]) -> Result<() #[cfg(test)] mod tests { - use super::load; + use super::{OperatingSystem, TargetMatrix, load, validate}; #[test] fn current_contract_selects_exact_toolchains_targets_and_packages() { @@ -198,7 +193,55 @@ mod tests { let (matrix, packages) = load(root).expect("target matrix"); assert_eq!(matrix.msrv_toolchain, "1.97.1"); assert_eq!(matrix.current_toolchain, "stable"); - assert_eq!(matrix.operating_system.len(), 3); + assert_eq!(matrix.operating_system.len(), 2); + assert_eq!( + matrix + .operating_system + .iter() + .map(|entry| (entry.name.as_str(), entry.target.as_str())) + .collect::<Vec<_>>(), + [ + ("linux", "x86_64-unknown-linux-gnu"), + ("macos", "aarch64-apple-darwin"), + ] + ); assert_eq!(packages.len(), 19); } + + #[test] + fn unsupported_production_targets_are_rejected() { + let mut matrix = TargetMatrix { + schema_version: 1, + msrv_toolchain: "1.97.1".to_owned(), + current_toolchain: "stable".to_owned(), + operating_system: vec![ + OperatingSystem { + name: "linux".to_owned(), + target: "x86_64-unknown-linux-gnu".to_owned(), + cross_compiler: Some("zig cc".to_owned()), + cross_cflags: Some("-target x86_64-linux-gnu".to_owned()), + }, + OperatingSystem { + name: "macos".to_owned(), + target: "aarch64-apple-darwin".to_owned(), + cross_compiler: None, + cross_cflags: None, + }, + ], + }; + for (name, target) in [ + ("windows", "x86_64-pc-windows-gnu"), + ("macos", "x86_64-apple-darwin"), + ("linux", "aarch64-unknown-linux-gnu"), + ] { + matrix.operating_system.push(OperatingSystem { + name: name.to_owned(), + target: target.to_owned(), + cross_compiler: None, + cross_cflags: None, + }); + assert!(validate(&matrix).is_err(), "accepted {target}"); + matrix.operating_system.pop(); + } + } }