build_policy.rs (4827B)
1 #![forbid(unsafe_code)] 2 3 use sha2::{Digest, Sha256}; 4 5 const MANIFEST: &str = include_str!("../Cargo.toml"); 6 const SOURCE_LOCK: &str = include_str!("../radroots.service.source-lock.v3.toml"); 7 const FLAKE_LOCK: &[u8] = include_bytes!("../flake.lock"); 8 9 #[test] 10 fn manifest_freezes_the_native_service_policy() { 11 assert!(MANIFEST.contains( 12 "repository = \"https://github.com/radrootslabs/rhi\"\nreadme = \"README\"\npublish = false" 13 )); 14 assert!(MANIFEST.contains("[workspace]\nresolver = \"3\"")); 15 assert!(MANIFEST.contains("[workspace.lints.rust]\nunsafe_code = \"deny\"")); 16 assert!(MANIFEST.contains("[workspace.lints.rustdoc]\nbroken_intra_doc_links = \"deny\"")); 17 assert!(MANIFEST.contains( 18 "[workspace.lints.clippy]\ndbg_macro = \"deny\"\ntodo = \"deny\"\nunimplemented = \"deny\"" 19 )); 20 assert!(MANIFEST.contains("[lints]\nworkspace = true")); 21 assert!(MANIFEST.contains("[features]\ndefault = [\"service-host\"]\nservice-host = []")); 22 } 23 24 #[test] 25 fn source_lock_metadata_is_exact_and_nix_is_qualified() { 26 assert!(MANIFEST.contains( 27 "[workspace.metadata.radroots.service_source_lock]\nservice = \"rhi\"\nhost_feature_profile = \"service-host\"\nnix_material = \"qualified\"" 28 )); 29 for field in [ 30 "config_contract_version = 1", 31 "state_contract_version = 11", 32 "admin_contract_version = 1", 33 "status_contract_version = 1", 34 "provider_contract_version = 1", 35 ] { 36 assert!( 37 MANIFEST.contains(field), 38 "missing source-lock field {field}" 39 ); 40 } 41 } 42 43 #[test] 44 fn shared_host_packages_are_exactly_source_locked() { 45 for dependency in ["radroots_service_host", "radroots_service_sqlite"] { 46 assert!(MANIFEST.contains(&format!( 47 "{dependency} = {{ git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\" }}" 48 ))); 49 } 50 } 51 52 #[test] 53 fn shared_service_sqlite_is_the_only_catalog_authority() { 54 assert!(MANIFEST.contains( 55 "radroots_service_sqlite = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\" }" 56 )); 57 for forbidden in ["rusqlite", "libsqlite3-sys"] { 58 assert!( 59 !MANIFEST.contains(forbidden), 60 "RHI must not introduce alternate SQLite authority `{forbidden}`" 61 ); 62 } 63 } 64 65 #[test] 66 fn shared_storage_generation_type_is_exactly_source_locked() { 67 assert!(MANIFEST.contains( 68 "radroots_storage = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\", default-features = false }" 69 )); 70 } 71 72 #[test] 73 fn shared_transport_spi_is_exactly_source_locked_without_serde() { 74 assert!(MANIFEST.contains( 75 "radroots_transport = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\", default-features = false, features = [\"std\"] }" 76 )); 77 assert!(MANIFEST.contains( 78 "radroots_transport_nostr = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\" }" 79 )); 80 } 81 82 #[test] 83 fn source_lock_binds_the_current_cargo_lock() { 84 let digest = lower_hex(&Sha256::digest(include_bytes!("../Cargo.lock"))); 85 let flake_digest = lower_hex(&Sha256::digest(FLAKE_LOCK)); 86 assert!(SOURCE_LOCK.starts_with( 87 "schema = \"radroots.service.source-lock.v3\"\ncontract_version = 3\nservice = \"rhi\"\n" 88 )); 89 assert!(SOURCE_LOCK.contains(&format!("cargo_lock_sha256 = \"{digest}\""))); 90 assert!(SOURCE_LOCK.contains(&format!("sha256 = \"{flake_digest}\""))); 91 assert!(SOURCE_LOCK.contains("revision = \"055096853fca95e15d0f813d33a14aca13be3881\"")); 92 assert!(SOURCE_LOCK.contains( 93 "workspace_catalog_sha256 = \"deca0c080deae187ff8186c0708903e42f41ea57f77c5f91581e23aa561164a4\"" 94 )); 95 assert!(SOURCE_LOCK.contains( 96 "source_archive_sha256 = \"89b8ace3f61167df43aca89917405d58b2aaf2ddea8fadfb21d351d76f184e68\"" 97 )); 98 assert!(SOURCE_LOCK.contains( 99 "[nix]\nmaterial = \"qualified\"\nlib_revision = \"055096853fca95e15d0f813d33a14aca13be3881\"\nsupported_systems = [\"aarch64-darwin\", \"x86_64-linux\"]\n" 100 )); 101 assert!(SOURCE_LOCK.ends_with( 102 "[contract_versions]\nconfig = 1\nstate = 11\nadmin = 1\nstatus = 1\nprovider = 1\n" 103 )); 104 } 105 106 fn lower_hex(bytes: &[u8]) -> String { 107 const DIGITS: &[u8; 16] = b"0123456789abcdef"; 108 let mut output = String::with_capacity(bytes.len() * 2); 109 for byte in bytes { 110 output.push(char::from(DIGITS[usize::from(byte >> 4)])); 111 output.push(char::from(DIGITS[usize::from(byte & 0x0f)])); 112 } 113 output 114 }