services_hardening_reconciliation_reducer_contract.rs (4638B)
1 #![forbid(unsafe_code)] 2 3 use rhi::RHI_RECONCILIATION_REDUCER_CONTRACT_VERSION; 4 use serde_json::json; 5 6 const CONTRACT: &str = 7 include_str!("../contracts/services_hardening/reconciliation_reducer.v1.json"); 8 const ROOT: &str = include_str!("../src/lib.rs"); 9 const SOURCE: &str = include_str!("../src/reconciliation_reducer.rs"); 10 const MANIFEST: &str = include_str!("../src/reconciliation_manifest.rs"); 11 const README: &str = include_str!("../README"); 12 13 #[test] 14 fn machine_contract_freezes_the_complete_step_193_boundary() { 15 let contract: serde_json::Value = serde_json::from_str(CONTRACT).expect("contract"); 16 assert_eq!(contract["schema"], "radroots.rhi.reconciliation-reducer"); 17 assert_eq!(contract["schema_version"], 1); 18 assert_eq!( 19 contract["contract_version"], 20 RHI_RECONCILIATION_REDUCER_CONTRACT_VERSION 21 ); 22 assert_eq!( 23 contract["input"]["authority"], 24 "sealed_confirmed_reconciliation_manifest_only" 25 ); 26 assert_eq!(contract["input"]["maximum_mutations"], 65_536); 27 assert_eq!( 28 contract["input"]["maximum_canonical_content_bytes"], 29 134_217_728 30 ); 31 assert_eq!( 32 contract["input"]["evidence_state"], 33 json!({ 34 "missing": "missing", 35 "partial": "query_partial", 36 "scope_satisfied": "complete", 37 "unsupported": "unsupported_version" 38 }) 39 ); 40 assert_eq!( 41 contract["shared_reducer"]["contract_id"], 42 "radroots.trade.reducer.v1" 43 ); 44 assert_eq!( 45 contract["projection_digest"]["ordered_fields"], 46 json!([ 47 "rhi_reducer_contract_version_u32_be", 48 "shared_reducer_contract_id_length_u64_be", 49 "shared_reducer_contract_id_utf8", 50 "shared_reducer_contract_version_u16_be", 51 "evidence_manifest_digest", 52 "evidence_policy_digest", 53 "shared_projection_digest" 54 ]) 55 ); 56 assert_eq!(contract["effects"]["sqlite"], false); 57 assert_eq!(contract["effects"]["source_or_relay"], false); 58 assert_eq!(contract["effects"]["ambient_clock"], false); 59 assert_eq!(contract["effects"]["ambient_entropy"], false); 60 assert_eq!( 61 contract["result"]["shared_projection_digest_available"], 62 "optional_fail_closed_for_outcome" 63 ); 64 assert_eq!( 65 contract["result"]["rhi_projection_digest_available"], 66 "optional_fail_closed_for_outcome" 67 ); 68 assert_eq!( 69 contract["result"]["outcome_owner"], 70 "reconciliation_outcome.v1.json" 71 ); 72 } 73 74 #[test] 75 fn reducer_boundary_is_sealed_redacted_and_effect_free() { 76 assert!(ROOT.contains("mod reconciliation_reducer;")); 77 assert!(!ROOT.contains("pub mod reconciliation_reducer;")); 78 for required in [ 79 "RhiReconciliationProjection", 80 "RhiReconciliationReducerError", 81 "RhiReconciliationReducerErrorKind", 82 "RHI_RECONCILIATION_REDUCER_CONTRACT_VERSION", 83 "reduce_rhi_reconciliation_manifest", 84 ] { 85 assert!(ROOT.contains(required), "root API is missing {required}"); 86 } 87 for required in [ 88 "trade_mutation_from_canonical_content", 89 "reduce_trade_records(input)", 90 "PROJECTION_DIGEST_DOMAIN", 91 "manifest.digest()", 92 "inner.evidence_policy_digest()", 93 "decode_lower_hex_32(shared.projection_digest())", 94 "RHI_REDUCER_MAXIMUM_MUTATION_MATERIAL_BYTES", 95 ] { 96 assert!(SOURCE.contains(required), "reducer is missing {required}"); 97 } 98 assert!(!SOURCE.contains("fn shared_projection(&self)")); 99 for required in [ 100 "reducer_mutations: Box<[RhiReducerMutationMaterial]>", 101 "BTreeMap::<[u8; 32], RhiReducerMutationMaterial>::new()", 102 "RHI_REDUCER_MAXIMUM_MUTATION_MATERIAL_BYTES: usize = 134_217_728", 103 "canonical_content: Arc<[u8]>", 104 "canonical_content: fact.record.canonical_content.clone()", 105 ] { 106 assert!( 107 MANIFEST.contains(required), 108 "manifest reducer material is missing {required}" 109 ); 110 } 111 for forbidden in [ 112 "sqlx::", 113 "std::fs", 114 "std::net", 115 "tokio::", 116 "SystemTime", 117 "thread_rng", 118 "OsRng", 119 "pub fn new(", 120 "pub const fn new(", 121 "pub fn persist", 122 ] { 123 assert!( 124 !SOURCE.contains(forbidden), 125 "reducer gained forbidden authority {forbidden}" 126 ); 127 } 128 assert!(README.contains("## Pure reconciliation reducer")); 129 assert!(README.contains( 130 "[`reconciliation_reducer.v1.json`](contracts/services_hardening/reconciliation_reducer.v1.json)" 131 )); 132 }