services_hardening_failure_qualification.rs (9674B)
1 #![forbid(unsafe_code)] 2 3 use std::collections::BTreeSet; 4 5 use serde_json::Value; 6 7 const CONTRACT: &str = 8 include_str!("../contracts/services_hardening/failure_qualification.v1.json"); 9 const MANIFEST: &str = include_str!("../Cargo.toml"); 10 const README: &str = include_str!("../README"); 11 const AGENTS: &str = include_str!("../AGENTS.md"); 12 const COMPONENT_TESTS: &[&str] = &[ 13 include_str!("services_hardening_config_contract.rs"), 14 include_str!("services_hardening_config_lifecycle.rs"), 15 include_str!("services_hardening_state_resilience.rs"), 16 include_str!("services_hardening_state_host.rs"), 17 include_str!("services_hardening_reconciliation_jobs.rs"), 18 include_str!("services_hardening_presence_publication.rs"), 19 include_str!("services_hardening_source_ingest.rs"), 20 include_str!("services_hardening_runtime_foundation.rs"), 21 include_str!("services_hardening_doctor.rs"), 22 include_str!("package_boundary.rs"), 23 ]; 24 25 #[test] 26 fn contract_freezes_the_exact_failure_qualification_corpus() { 27 let contract: Value = serde_json::from_str(CONTRACT).expect("failure qualification contract"); 28 assert_eq!( 29 contract 30 .as_object() 31 .expect("qualification object") 32 .keys() 33 .map(String::as_str) 34 .collect::<BTreeSet<_>>(), 35 BTreeSet::from([ 36 "component_corpus", 37 "contract_version", 38 "deferred", 39 "invariants", 40 "resource_bounds", 41 "schema", 42 "schema_version", 43 "service", 44 "source_lock", 45 "source_locked_shared_sqlite_corpus", 46 "step", 47 ]) 48 ); 49 assert_eq!(contract["schema"], "radroots.rhi.failure-qualification.v1"); 50 assert_eq!(contract["schema_version"], 1); 51 assert_eq!(contract["contract_version"], 1); 52 assert_eq!(contract["step"], 214); 53 assert_eq!(contract["service"], "rhi"); 54 assert_eq!( 55 contract["source_lock"], 56 serde_json::json!({ 57 "schema": "radroots.service.source-lock.v2", 58 "lib_revision": "053d0c750bf9cd683c6ea37cefe7e79617ba629f" 59 }) 60 ); 61 assert_eq!( 62 contract["resource_bounds"], 63 serde_json::json!({ 64 "configuration_document_utf8_bytes": 1_048_576, 65 "source_result_events": 4_096, 66 "source_result_bytes": 8_388_608, 67 "reconciliation_queue": 65_536, 68 "publication_queue": 65_536, 69 "doctor_checks": 15 70 }) 71 ); 72 assert_eq!( 73 contract["component_corpus"], 74 serde_json::json!({ 75 "resource_and_backlog": [ 76 "exact_resource_boundaries_and_safe_defaults_are_frozen", 77 "source_results_enforce_deadline_outcome_and_exact_resource_bounds", 78 "commit_inventory_bounds_infinite_iterators_before_any_mutation", 79 "publication_queue_capacity_is_checked_before_finalization_mutation", 80 "configured_result_bound_retains_admitted_evidence_without_checkpoint", 81 "public_inputs_have_exact_bounds_and_diagnostics_are_redacted" 82 ], 83 "disk_and_durable_state": [ 84 "backup_integrity_and_offline_restore_obey_one_exact_rhi_authority", 85 "maintenance_boundary_is_sealed_source_free_and_sqlx_owned", 86 "initialize_is_create_new_and_both_existing_open_modes_close_explicitly" 87 ], 88 "corruption_and_malformed_history": [ 89 "semantically_conflicting_but_structurally_valid_history_fails_closed", 90 "exact_open_rejects_unexpected_migration_history_without_repair", 91 "publication_schema_rejects_null_state_holes_and_accepted_target_mutation", 92 "schema_v8_scans_historical_nullable_job_state_and_installs_permanent_guards" 93 ], 94 "cancellation_outage_and_recovery": [ 95 "cancelled_blocked_commit_has_no_effect_and_exact_retry_succeeds", 96 "cancelled_submitted_attempt_recovers_unknown_and_retries_exact_bytes_after_reopen", 97 "exact_bytes_are_durable_before_io_and_unknown_recovery_retries_unchanged", 98 "incomplete_and_unsupported_results_never_advance_checkpoint_or_dirty_generation", 99 "missing_state_fails_before_identity_or_transport_access", 100 "identity_failure_after_state_open_releases_authority_without_transport_access", 101 "failures_schedule_exact_jitter_and_the_final_attempt_exhausts", 102 "signed_attestation_fails_closed_when_injected_entropy_is_unavailable", 103 "required_timeout_drops_work_and_remaining_checks_continue_in_order" 104 ], 105 "safe_error_posture": [ 106 "configuration_lifecycle_surface_is_sealed_and_redacted", 107 "attempt_and_public_diagnostics_are_bounded_and_redacted", 108 "report_debug_and_public_errors_retain_no_sensitive_values", 109 "public_errors_are_crate_owned_redacted_and_source_free" 110 ] 111 }) 112 ); 113 assert_eq!( 114 contract["invariants"], 115 serde_json::json!({ 116 "bounded_ingestion_before_mutation": true, 117 "atomic_commit_or_no_effect": true, 118 "cancellation_retry_safe": true, 119 "durable_unknown_recovered_before_retry": true, 120 "malformed_history_repaired": false, 121 "corruption_fails_closed": true, 122 "sqlx_is_only_high_level_sqlite_authority": true, 123 "production_failpoint_surface": false, 124 "test_environment_selector": false, 125 "public_errors_source_free": true, 126 "diagnostics_path_secret_free": true 127 }) 128 ); 129 assert_eq!( 130 contract["deferred"], 131 serde_json::json!([ 132 "actual_process_and_bounded_soak_step_215", 133 "native_release_artifacts_step_216", 134 "rcld_promotion_step_217", 135 "parent_pin_alignment_step_217", 136 "nix", 137 "oci", 138 "signing", 139 "publication", 140 "deployment" 141 ]) 142 ); 143 } 144 145 #[test] 146 fn every_component_contract_entry_names_an_executable_test() { 147 let contract: Value = serde_json::from_str(CONTRACT).expect("failure qualification contract"); 148 let sources = COMPONENT_TESTS.join("\n"); 149 let corpus = contract["component_corpus"] 150 .as_object() 151 .expect("component corpus"); 152 assert_eq!( 153 corpus.keys().map(String::as_str).collect::<BTreeSet<_>>(), 154 BTreeSet::from([ 155 "cancellation_outage_and_recovery", 156 "corruption_and_malformed_history", 157 "disk_and_durable_state", 158 "resource_and_backlog", 159 "safe_error_posture", 160 ]) 161 ); 162 for (category, tests) in corpus { 163 let tests = tests.as_array().expect("test-name array"); 164 assert!(!tests.is_empty(), "empty qualification category {category}"); 165 for test in tests { 166 let test = test.as_str().expect("test name"); 167 assert!( 168 sources.contains(&format!("fn {test}(")), 169 "qualification entry {category}/{test} has no executable test" 170 ); 171 } 172 } 173 } 174 175 #[test] 176 fn historical_source_lock_binds_the_shared_sqlite_failure_corpus() { 177 let contract: Value = serde_json::from_str(CONTRACT).expect("failure qualification contract"); 178 let revision = contract["source_lock"]["lib_revision"] 179 .as_str() 180 .expect("Lib revision"); 181 assert_eq!(revision, "053d0c750bf9cd683c6ea37cefe7e79617ba629f"); 182 assert!(MANIFEST.contains( 183 "radroots_service_sqlite = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\"" 184 )); 185 assert_eq!( 186 contract["source_locked_shared_sqlite_corpus"], 187 serde_json::json!([ 188 "minimum_policy_and_strict_numeric_serde_are_bounded", 189 "injected_values_classify_exact_boundary_and_propagate_failure", 190 "physical_corruption_and_query_failure_remain_redacted_and_typed", 191 "missing_extra_reordered_newer_and_corrupt_history_fail_closed", 192 "oversized_corrupt_history_is_bounded_before_decode", 193 "every_initialization_durability_edge_fails_once_and_rolls_back", 194 "transaction_durability_edges_preserve_exact_commit_semantics", 195 "backup_durability_edges_fail_once_clean_exact_stage_and_recover", 196 "close_durability_edges_are_once_only_retryable_or_terminal", 197 "every_marker_and_restore_durability_edge_is_wired_once", 198 "sigkill_restore_boundaries_recover_exact_topologies_and_preserve_permissions" 199 ]) 200 ); 201 assert!(!MANIFEST.contains("rusqlite")); 202 } 203 204 #[test] 205 fn human_boundary_is_explicit_and_does_not_preclaim_later_steps() { 206 for required in [ 207 "## Failure-resilience qualification", 208 "[`failure_qualification.v1.json`](contracts/services_hardening/failure_qualification.v1.json)", 209 "actual-process and\nbounded-soak qualification remains Step 215 ownership", 210 "native release\nartifacts remain Step 216 ownership", 211 "promotion and parent-pin alignment\nremain Step 217 ownership", 212 ] { 213 assert!(README.contains(required), "README is missing {required}"); 214 } 215 for required in [ 216 "Step 214 freezes the failure-resilience qualification corpus", 217 "Do not add a second SQLite authority", 218 "Step 215\n alone owns actual-process and bounded-soak qualification", 219 ] { 220 assert!(AGENTS.contains(required), "AGENTS is missing {required}"); 221 } 222 }