services_hardening_host_decision.rs (10604B)
1 #![forbid(unsafe_code)] 2 3 use serde_json::Value; 4 5 const HOST_DECISION: &str = 6 include_str!("../../../contracts/architecture/decisions/services_hardening_host.v1.json"); 7 8 fn decision() -> Value { 9 serde_json::from_str(HOST_DECISION).expect("host decision must be valid JSON") 10 } 11 12 #[test] 13 fn admin_routes_envelopes_and_exit_codes_are_unique_and_exact() { 14 let value = decision(); 15 assert_eq!( 16 value["schema"], 17 "radroots.services-hardening.host-decisions.v1" 18 ); 19 assert_eq!(value["decision_state"], "reserved_preimplementation"); 20 assert_eq!( 21 value["local_admin"]["transport"], 22 "http_1_1_over_unix_domain_socket" 23 ); 24 assert_eq!(value["local_admin"]["base_path"], "/v1"); 25 assert_eq!(value["local_admin"]["tcp_admin"], false); 26 27 assert_eq!( 28 value["local_admin"]["mutation_request_envelope"], 29 serde_json::json!({ 30 "required_fields": ["contract_version", "operation_id", "request"], 31 "optional_fields": ["correlation_id"], 32 "contract_version": 1, 33 "operation_id_semantics": "caller_stable_idempotency_identity", 34 "correlation_id_semantics": "caller_safe_trace_identity_or_daemon_generated_when_absent", 35 "identical_operation_id_reuse": "return_original_committed_result", 36 "different_request_operation_id_reuse": { 37 "admin_error_code": "operation_id_conflict", 38 "cli_exit": 5 39 } 40 }) 41 ); 42 assert_eq!(value["local_admin"]["cors"], false); 43 assert_eq!(value["local_admin"]["browser_authentication"], false); 44 assert_eq!( 45 value["local_admin"]["unknown_major_version"], 46 "unsupported_contract_version" 47 ); 48 assert_eq!(value["local_admin"]["unknown_route"], "route_not_found"); 49 assert_eq!(value["local_admin"]["duplicate_json_fields_rejected"], true); 50 assert_eq!(value["local_admin"]["unknown_json_fields_rejected"], true); 51 assert_eq!( 52 value["local_admin"]["success_response_envelope"], 53 serde_json::json!({ 54 "required_fields": ["contract_version", "ok", "correlation_id", "result"], 55 "contract_version": 1, 56 "ok": true 57 }) 58 ); 59 assert_eq!( 60 value["local_admin"]["failure_response_envelope"], 61 serde_json::json!({ 62 "required_fields": ["contract_version", "ok", "correlation_id", "error"], 63 "error_required_fields": ["code", "message"], 64 "contract_version": 1, 65 "ok": false 66 }) 67 ); 68 assert_eq!( 69 value["local_admin"]["output_safety"], 70 serde_json::json!({ 71 "request_body_max_utf8_bytes": 65_536, 72 "response_body_max_utf8_bytes": 1_048_576, 73 "operation_id_max_utf8_bytes": 128, 74 "correlation_id_max_utf8_bytes": 128, 75 "error_code_max_utf8_bytes": 64, 76 "error_message_max_utf8_bytes": 256, 77 "redaction_required": true, 78 "forbidden_material": [ 79 "secret_or_credential_material", 80 "private_identity_material", 81 "decrypted_payload", 82 "raw_absolute_or_resolved_path", 83 "raw_sql_or_database_error", 84 "raw_provider_error", 85 "raw_relay_or_network_error", 86 "source_error_chain" 87 ] 88 }) 89 ); 90 91 let routes = value["local_admin"]["common_route_suffixes"] 92 .as_array() 93 .expect("common routes"); 94 assert_eq!( 95 routes, 96 serde_json::json!([ 97 { "method": "GET", "path": "/status", "operation_suffix": "status.get", "request_model": "empty", "response_model": "service_status_v1" }, 98 { "method": "GET", "path": "/config/effective", "operation_suffix": "config.effective.get", "request_model": "empty", "response_model": "effective_config_v1" }, 99 { "method": "GET", "path": "/identity/status", "operation_suffix": "identity.status.get", "request_model": "identity_status_query_v1", "response_model": "identity_status_v1" }, 100 { "method": "POST", "path": "/identity/rekey", "operation_suffix": "identity.rekey", "request_model": "identity_rekey_request_v1", "response_model": "identity_mutation_receipt_v1" }, 101 { "method": "POST", "path": "/identity/replace", "operation_suffix": "identity.replace", "request_model": "identity_replace_request_v1", "response_model": "identity_mutation_receipt_v1" }, 102 { "method": "GET", "path": "/state/status", "operation_suffix": "state.status.get", "request_model": "empty", "response_model": "state_status_v1" }, 103 { "method": "POST", "path": "/state/backup", "operation_suffix": "state.backup.create", "request_model": "state_backup_request_v1", "response_model": "state_backup_receipt_v1" }, 104 { "method": "GET", "path": "/metrics/snapshot", "operation_suffix": "metrics.snapshot.get", "request_model": "empty", "response_model": "metrics_snapshot_v1" } 105 ]) 106 .as_array() 107 .unwrap() 108 ); 109 110 assert_eq!( 111 value["exit_codes"], 112 serde_json::json!([ 113 { "code": 0, "name": "success", "meaning": "successful command or completed graceful first-signal shutdown" }, 114 { "code": 1, "name": "unexpected_internal", "meaning": "unexpected invariant, critical task, or internal failure" }, 115 { "code": 2, "name": "input_or_configuration", "meaning": "CLI, config, validation, or unsupported contract input" }, 116 { "code": 3, "name": "service_or_dependency_unavailable", "meaning": "daemon, required provider, relay, source, or local dependency unavailable" }, 117 { "code": 4, "name": "state_or_identity_unavailable", "meaning": "state, schema, lock, credential, or identity unavailable" }, 118 { "code": 5, "name": "operation_rejected_or_conflict", "meaning": "authorization rejection, idempotency conflict, stale generation, or domain conflict" }, 119 { "code": 6, "name": "doctor_required_check_failed", "meaning": "one or more required doctor checks failed or timed out" } 120 ]) 121 ); 122 } 123 124 #[test] 125 fn readiness_peer_authorization_and_native_support_fail_closed() { 126 let value = decision(); 127 assert_eq!( 128 value["tcp_operations"]["routes"], 129 serde_json::json!([ 130 { "method": "GET", "path": "/livez", "source": "cached_supervisor_state" }, 131 { "method": "GET", "path": "/readyz", "source": "cached_readiness_state" }, 132 { "method": "GET", "path": "/metrics", "source": "cached_bounded_metrics_snapshot" } 133 ]) 134 ); 135 assert_eq!(value["tcp_operations"]["active_probe_per_request"], false); 136 assert_eq!(value["tcp_operations"]["additional_routes"], false); 137 assert_eq!(value["systemd"]["sd_notify_v1"], false); 138 assert_eq!(value["systemd"]["service_type"], "simple"); 139 assert_eq!( 140 value["systemd"]["readiness_authority"], 141 "cached_http_readyz" 142 ); 143 assert_eq!( 144 value["systemd"]["process_running_does_not_imply_ready"], 145 true 146 ); 147 assert_eq!( 148 value["peer_authorization"]["linux_service_host"], 149 serde_json::json!({ 150 "credential_api": "SO_PEERCRED", 151 "required": true, 152 "allow": ["peer_uid_equals_daemon_euid", "peer_primary_gid_equals_configured_admin_gid"], 153 "credential_unavailable": "deny", 154 "parent_mode_without_admin_gid": "0700", 155 "socket_mode_without_admin_gid": "0600", 156 "parent_mode_with_admin_gid": "0750", 157 "socket_mode_with_admin_gid": "0660" 158 }) 159 ); 160 assert_eq!( 161 value["peer_authorization"]["macos_interactive"], 162 serde_json::json!({ 163 "credential_api": "none_v1", 164 "required": false, 165 "authority": "filesystem_owner_permissions_only", 166 "parent_mode": "0700", 167 "socket_mode": "0600", 168 "peer_credential_equivalence_claim": false 169 }) 170 ); 171 assert_eq!( 172 value["peer_authorization"]["other_platforms"], 173 serde_json::json!({ "admin_support": "unsupported_v1" }) 174 ); 175 assert_eq!( 176 value["doctor"], 177 serde_json::json!({ 178 "schema": "radroots.service.doctor.v1", 179 "contract_version": 1, 180 "required_fields": ["contract_version", "service", "instance", "status", "checks"], 181 "check_required_fields": ["id", "status", "required", "deadline_ms", "summary", "remediation_code"], 182 "statuses": ["pass", "fail", "timeout", "skipped"], 183 "required_skipped": "forbidden", 184 "aggregate_statuses": ["pass", "degraded", "fail"], 185 "aggregation": { 186 "required_fail_or_timeout": "fail", 187 "optional_fail_timeout_or_skipped": "degraded", 188 "otherwise": "pass" 189 }, 190 "optional_nonpass_exit": 0, 191 "summary_max_utf8_bytes": 256, 192 "raw_error_or_path_allowed": false, 193 "required_fail_or_timeout_exit": 6 194 }) 195 ); 196 assert_eq!( 197 value["forced_signal_exit"], 198 "operating_system_128_plus_signal_not_remapped" 199 ); 200 assert_eq!( 201 value["bare_rust_linux"]["qualification_base"], 202 "debian_bookworm_slim_digest_pinned_per_receipt" 203 ); 204 assert_eq!( 205 value["bare_rust_linux"]["architectures"], 206 serde_json::json!(["x86_64", "aarch64"]) 207 ); 208 assert_eq!( 209 value["bare_rust_linux"]["rust_install"], 210 "rustup_profile_minimal_exact_repository_toolchain" 211 ); 212 assert_eq!( 213 value["bare_rust_linux"]["apt_packages"], 214 serde_json::json!(["build-essential", "ca-certificates", "git"]) 215 ); 216 assert_eq!( 217 value["bare_rust_linux"]["not_required_by_final_graph"], 218 serde_json::json!([ 219 "clang", 220 "libclang-dev", 221 "libsodium-dev", 222 "libsqlite3-dev", 223 "libssl-dev", 224 "pkg-config" 225 ]) 226 ); 227 assert_eq!(value["bare_rust_linux"]["sqlite"], "bundled"); 228 assert_eq!(value["bare_rust_linux"]["tls"], "rustls"); 229 assert_eq!( 230 value["bare_rust_linux"]["proof"], 231 serde_json::json!([ 232 "fresh_digest_pinned_base_for_each_architecture", 233 "install_only_declared_apt_packages_and_exact_rust_toolchain", 234 "locked_format_check_test_clippy_rustdoc_release_build", 235 "repeat_with_network_disabled_from_governed_vendor_bundle", 236 "fail_if_undeclared_native_package_is_installed_or_linked" 237 ]) 238 ); 239 }