services_hardening_bounded_process_decision.rs (3954B)
1 #![forbid(unsafe_code)] 2 3 use serde_json::Value; 4 5 const DECISION: &str = include_str!( 6 "../../../contracts/architecture/decisions/services_hardening_bounded_process.v1.json" 7 ); 8 9 fn decision() -> Value { 10 serde_json::from_str(DECISION).expect("bounded-process decision must be valid JSON") 11 } 12 13 #[test] 14 fn process_and_resource_bounds_are_exact() { 15 let value = decision(); 16 assert_eq!( 17 value["schema"], 18 "radroots.services-hardening.bounded-process-decisions.v1" 19 ); 20 assert_eq!(value["contract_version"], 1); 21 assert_eq!(value["decision_state"], "active"); 22 assert_eq!(value["owner"], "tools/xtask"); 23 assert_eq!( 24 value["self_test_command"], 25 "cargo xtask bounded-process-self-test" 26 ); 27 assert_eq!( 28 value["platform_scope"], 29 serde_json::json!({ 30 "implementation": ["macos_aarch64", "linux_x86_64"], 31 "source_gate": ["macos_aarch64"], 32 "cross_platform_promotion_owner": "step-297" 33 }) 34 ); 35 assert_eq!( 36 value["process_model"], 37 serde_json::json!({ 38 "child_process_group": "new_group_with_child_as_leader", 39 "stdin": "closed_devnull", 40 "stdout": "concurrently_drained_live_byte_cap", 41 "stderr": "concurrently_drained_live_byte_cap", 42 "deadline_clock": "monotonic", 43 "normal_leader_exit": "clean_remaining_process_group", 44 "failure_cleanup": "term_group_bounded_grace_then_kill_group_and_bounded_reap", 45 "unsupported_platform": "fail_closed" 46 }) 47 ); 48 assert_eq!( 49 value["hard_maximums"], 50 serde_json::json!({ 51 "deadline_seconds": 86_400, 52 "termination_grace_seconds": 5, 53 "stdout_bytes": 67_108_864, 54 "stderr_bytes": 67_108_864, 55 "environment_entries": 64, 56 "environment_name_bytes": 128, 57 "environment_value_bytes": 65_536 58 }) 59 ); 60 } 61 62 #[test] 63 fn environment_and_diagnostics_fail_closed() { 64 let value = decision(); 65 assert_eq!( 66 value["environment"], 67 serde_json::json!({ 68 "inheritance": "replace_with_explicit_allowlist", 69 "ambient_snapshot": false, 70 "duplicate_name": "reject", 71 "invalid_name_or_nul": "reject", 72 "forbidden_names": [ 73 "CARGO_ENCODED_RUSTFLAGS", 74 "DYLD_INSERT_LIBRARIES", 75 "DYLD_LIBRARY_PATH", 76 "LD_LIBRARY_PATH", 77 "LD_PRELOAD", 78 "NIX_CONFIG", 79 "NIX_PATH", 80 "NIXPKGS_ALLOW_BROKEN", 81 "NIXPKGS_ALLOW_UNFREE", 82 "RUSTFLAGS" 83 ], 84 "forbidden_name_patterns": [ 85 "*CREDENTIAL*", 86 "*KEY*", 87 "*PASSWORD*", 88 "*SECRET*", 89 "*TOKEN*" 90 ], 91 "equivalent_build_controls": [ 92 "CARGO_BUILD_RUSTFLAGS", 93 "CARGO_TARGET_*_RUSTFLAGS", 94 "DYLD_*", 95 "LD_AUDIT", 96 "LD_DEBUG", 97 "LD_PROFILE", 98 "RUSTC_WRAPPER", 99 "RUSTC_WORKSPACE_WRAPPER", 100 "RUSTDOCFLAGS" 101 ] 102 }) 103 ); 104 assert_eq!( 105 value["diagnostic_safety"], 106 serde_json::json!({ 107 "program_argv_cwd": "redacted", 108 "environment_values": "redacted", 109 "captured_stream_bytes": "redacted", 110 "operating_system_error_text": "redacted", 111 "source_error_chain": "absent" 112 }) 113 ); 114 assert_eq!( 115 value["required_vectors"], 116 serde_json::json!([ 117 "timeout", 118 "orphan_child", 119 "stdout_cap", 120 "stderr_cap", 121 "closed_stdin", 122 "inherited_build_environment", 123 "loader_injection", 124 "redaction" 125 ]) 126 ); 127 }