use super::*; use crate::component_cutover::{ CutoverOperation, EffectDisposition, LegacyServiceState, MutationDirection, MutationEffect, MutationRecord, StateFingerprint, }; use crate::process::{ FullServiceSnapshot, ServiceBaseConfigSnapshot, ServiceSecuritySnapshot, ServiceStableState, SERVICE_CONFIG2_KINDS, }; #[derive(Debug, Clone, PartialEq, Eq)] enum Call { CaptureLegacy, QueryLegacy, QueryCurrent, QueryComplete, QueryLegacyPolicy(ServiceConfig2Kind), QueryCurrentPolicy(ServiceConfig2Kind), QueryCurrentSecurity, StopLegacy, DeleteLegacy, CreateCurrent, SetCurrentPolicy(ServiceConfig2Kind), SetCurrentSecurity, StartCurrent, StopCurrent, DeleteCurrent, CreateLegacy, RestoreLegacyPolicy(ServiceConfig2Kind), RestoreLegacySecurity, StartLegacy, } struct FakeScm { calls: Vec, fail_on: Option, before: ServiceRestoreSnapshot, complete: CompleteServiceObservation, current_base: ServiceBaseConfigSnapshot, } impl FakeScm { fn new() -> Self { let current_base = expected_current_proxifyre_service_base( &std::env::temp_dir().join("ProxyWarden-current-ProxiFyre.exe"), ) .expect("current base fixture"); Self { calls: Vec::new(), fail_on: None, before: before_state(), complete: CompleteServiceObservation::Missing, current_base, } } fn record(&mut self, call: Call) -> Result<(), ProxifyreNativeHostError> { self.calls.push(call.clone()); if self.fail_on.as_ref() == Some(&call) { Err(ProxifyreNativeHostError) } else { Ok(()) } } fn missing_policy() -> ServicePolicySnapshot { ServicePolicySnapshot { service: crate::process::ServiceSnapshot { exists: false, state: None, path_name: None, process_id: None, }, path_matches: false, demand_start: false, failure_recovery_disabled: false, dacl_matches: false, } } } impl ProxifyreCutoverScm for FakeScm { fn capture_legacy_service( &mut self, ) -> Result { self.record(Call::CaptureLegacy)?; Ok(self.before.clone()) } fn query_legacy_service(&mut self) -> Result { self.record(Call::QueryLegacy)?; Ok(Self::missing_policy()) } fn query_current_service(&mut self) -> Result { self.record(Call::QueryCurrent)?; Ok(Self::missing_policy()) } fn query_complete_service( &mut self, ) -> Result { self.record(Call::QueryComplete)?; Ok(self.complete.clone()) } fn expected_current_service_base( &self, ) -> Result { Ok(self.current_base.clone()) } fn query_legacy_service_policy( &mut self, kind: ServiceConfig2Kind, ) -> Result, ProxifyreNativeHostError> { self.record(Call::QueryLegacyPolicy(kind))?; Ok(self.before.config2(kind).cloned()) } fn query_current_service_policy( &mut self, kind: ServiceConfig2Kind, ) -> Result, ProxifyreNativeHostError> { self.record(Call::QueryCurrentPolicy(kind))?; Ok(None) } fn current_service_security_matches(&mut self) -> Result { self.record(Call::QueryCurrentSecurity)?; Ok(false) } fn stop_legacy_service(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(Call::StopLegacy) } fn delete_legacy_service(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(Call::DeleteLegacy) } fn create_current_service(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(Call::CreateCurrent) } fn set_current_service_policy( &mut self, kind: ServiceConfig2Kind, ) -> Result<(), ProxifyreNativeHostError> { self.record(Call::SetCurrentPolicy(kind)) } fn set_current_service_security(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(Call::SetCurrentSecurity) } fn start_current_service(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(Call::StartCurrent) } fn stop_current_service(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(Call::StopCurrent) } fn delete_current_service(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(Call::DeleteCurrent) } fn create_legacy_service( &mut self, _before: &ServiceRestoreSnapshot, ) -> Result<(), ProxifyreNativeHostError> { self.record(Call::CreateLegacy) } fn restore_legacy_service_policy( &mut self, snapshot: &ServiceConfig2Snapshot, ) -> Result<(), ProxifyreNativeHostError> { self.record(Call::RestoreLegacyPolicy(snapshot.kind())) } fn restore_legacy_service_security( &mut self, _before: &ServiceRestoreSnapshot, ) -> Result<(), ProxifyreNativeHostError> { self.record(Call::RestoreLegacySecurity) } fn start_legacy_service(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(Call::StartLegacy) } } fn before_state() -> ServiceRestoreSnapshot { FullServiceSnapshot { service_name: PROXIFYRE_MANAGED_SERVICE_NAME.to_owned(), base: ServiceBaseConfigSnapshot { service_type: 0x10, start_type: 2, error_control: 1, binary_path_name: concat!( r#""C:\Tools\ProxiFyre\ProxiFyre.exe" "#, r#"-displayname "ProxiFyre Service" -servicename "ProxiFyreService""# ) .to_owned(), load_order_group: None, tag_id: 0, dependencies: Vec::new(), service_start_name: "LocalSystem".to_owned(), display_name: "ProxiFyre Service".to_owned(), }, config2: SERVICE_CONFIG2_KINDS .iter() .copied() .map(expected_current_proxifyre_service_policy) .collect(), security: ServiceSecuritySnapshot { self_relative_descriptor: vec![1, 2, 3], untrusted_mutation_rights: false, }, original_state: ServiceStableState::Running, } } #[test] fn create_current_is_exactly_one_call_and_never_starts() { let mut host = FakeScm::new(); let before = host.before.clone(); assert!(mutate_proxifyre_cutover_scm( &mut host, &CutoverOperation::CreateCurrentService, &before, ) .expect("SCM mutation dispatch")); assert_eq!(host.calls, vec![Call::CreateCurrent]); } #[test] fn collision_or_failure_stops_after_the_single_selected_mutation() { let mut host = FakeScm::new(); host.fail_on = Some(Call::DeleteLegacy); let before = host.before.clone(); mutate_proxifyre_cutover_scm(&mut host, &CutoverOperation::DeleteLegacyService, &before) .expect_err("collision/failure must surface"); assert_eq!(host.calls, vec![Call::DeleteLegacy]); } #[test] fn restore_policy_selects_only_the_requested_captured_record() { let mut host = FakeScm::new(); let before = host.before.clone(); assert!(mutate_proxifyre_cutover_scm( &mut host, &CutoverOperation::RestoreLegacyServicePolicy(ServiceConfig2Kind::Triggers), &before, ) .expect("restore dispatch")); assert_eq!( host.calls, vec![Call::RestoreLegacyPolicy(ServiceConfig2Kind::Triggers)] ); } #[test] fn read_only_missing_policy_is_typed_absence_and_never_mutates() { let mut host = FakeScm::new(); assert_eq!( host.query_current_service_policy(ServiceConfig2Kind::Description) .expect("read-only query"), None ); assert_eq!( host.calls, vec![Call::QueryCurrentPolicy(ServiceConfig2Kind::Description)] ); } #[test] fn non_scm_operation_is_not_claimed_or_mutated() { let mut host = FakeScm::new(); let before = host.before.clone(); assert!(!mutate_proxifyre_cutover_scm( &mut host, &CutoverOperation::HardenLegacyRootSecurity, &before, ) .expect("non-SCM dispatch")); assert!(host.calls.is_empty()); } #[test] fn expected_current_policy_covers_every_config2_kind() { for kind in SERVICE_CONFIG2_KINDS { assert_eq!(expected_current_proxifyre_service_policy(kind).kind(), kind); } assert!(matches!( expected_current_proxifyre_service_policy(ServiceConfig2Kind::Triggers), ServiceConfig2Snapshot::Triggers(ref triggers) if triggers.is_empty() )); } #[test] fn scm_observer_matches_typed_expected_fingerprint_for_every_scm_operation() { let before = before_state(); let operations = vec![ CutoverOperation::StopLegacyService, CutoverOperation::DeleteLegacyService, CutoverOperation::CreateCurrentService, CutoverOperation::SetCurrentServicePolicy(ServiceConfig2Kind::Description), CutoverOperation::SetCurrentServiceSecurity, CutoverOperation::StartCurrentService, CutoverOperation::StopCurrentService, CutoverOperation::DeleteCurrentService, CutoverOperation::CreateLegacyService, CutoverOperation::RestoreLegacyServicePolicy(ServiceConfig2Kind::Triggers), CutoverOperation::RestoreLegacyServiceSecurity, CutoverOperation::StartLegacyService, ]; for operation in operations { let mut host = FakeScm::new(); host.complete = satisfying_scm_observation(&operation, &before, &host.current_base); assert_eq!( observe_proxifyre_cutover_scm_state(&mut host, &operation, &before) .expect("typed complete SCM observation"), expected_proxifyre_cutover_scm_effect(&operation).expect("typed expected SCM effect"), "operation {operation:?}" ); assert_eq!(host.calls, vec![Call::QueryComplete]); } } #[test] fn scm_unexpected_fingerprint_preserves_complete_drift_instead_of_boolean_bucket() { let before = before_state(); let operation = CutoverOperation::CreateCurrentService; let mut first = FakeScm::new(); let mut first_snapshot = before.clone(); first_snapshot.base.display_name = "foreign-one".to_owned(); first.complete = complete_service(first_snapshot, false); let first_fingerprint = observe_proxifyre_cutover_scm_state(&mut first, &operation, &before) .expect("first exact unexpected state"); let mut repeated = FakeScm::new(); let mut repeated_snapshot = before.clone(); repeated_snapshot.base.display_name = "foreign-one".to_owned(); repeated.complete = complete_service(repeated_snapshot, false); let repeated_fingerprint = observe_proxifyre_cutover_scm_state(&mut repeated, &operation, &before) .expect("repeated exact unexpected state"); let mut second = FakeScm::new(); let mut second_snapshot = before.clone(); second_snapshot.base.display_name = "foreign-two".to_owned(); second.complete = complete_service(second_snapshot, false); let second_fingerprint = observe_proxifyre_cutover_scm_state(&mut second, &operation, &before) .expect("second exact unexpected state"); assert_eq!(first_fingerprint, repeated_fingerprint); assert_ne!(first_fingerprint, second_fingerprint); assert_ne!( first_fingerprint, expected_proxifyre_cutover_scm_effect(&operation).expect("expected effect") ); } #[test] fn scm_expected_effect_rejects_untrusted_mutation_rights() { let before = before_state(); let operation = CutoverOperation::CreateCurrentService; let mut host = FakeScm::new(); let mut live = satisfying_scm_observation(&operation, &before, &host.current_base); let CompleteServiceObservation::Present { snapshot, .. } = &mut live else { panic!("current service fixture must be present"); }; snapshot.security.untrusted_mutation_rights = true; host.complete = live; assert_ne!( observe_proxifyre_cutover_scm_state(&mut host, &operation, &before) .expect("exact unsafe SCM observation"), expected_proxifyre_cutover_scm_effect(&operation).expect("expected effect") ); } #[test] fn create_current_effect_requires_the_complete_fresh_service_default_profile() { let before = before_state(); let operation = CutoverOperation::CreateCurrentService; let mut exact = FakeScm::new(); exact.complete = satisfying_scm_observation(&operation, &before, &exact.current_base); assert_eq!( observe_proxifyre_cutover_scm_state(&mut exact, &operation, &before) .expect("complete fresh-service defaults"), expected_proxifyre_cutover_scm_effect(&operation).expect("expected create effect") ); let mut drifted = FakeScm::new(); let mut live = satisfying_scm_observation(&operation, &before, &drifted.current_base); let CompleteServiceObservation::Present { snapshot, .. } = &mut live else { panic!("current service fixture must be present"); }; let description = snapshot .config2 .iter_mut() .find(|value| value.kind() == ServiceConfig2Kind::Description) .expect("complete default profile"); *description = ServiceConfig2Snapshot::Description(Some("drift".to_owned())); drifted.complete = live; assert_ne!( observe_proxifyre_cutover_scm_state(&mut drifted, &operation, &before) .expect("drifted fresh-service defaults"), expected_proxifyre_cutover_scm_effect(&operation).expect("expected create effect") ); } fn complete_service( snapshot: ServiceRestoreSnapshot, current_dacl_matches: bool, ) -> CompleteServiceObservation { CompleteServiceObservation::Present { snapshot: Box::new(snapshot), current_dacl_matches, } } fn satisfying_scm_observation( operation: &CutoverOperation, before: &ServiceRestoreSnapshot, current_base: &ServiceBaseConfigSnapshot, ) -> CompleteServiceObservation { if matches!( operation, CutoverOperation::DeleteLegacyService | CutoverOperation::DeleteCurrentService ) { return CompleteServiceObservation::Missing; } let current = matches!( operation, CutoverOperation::CreateCurrentService | CutoverOperation::SetCurrentServicePolicy(_) | CutoverOperation::SetCurrentServiceSecurity | CutoverOperation::StartCurrentService | CutoverOperation::StopCurrentService ); let mut snapshot = before.clone(); let mut current_dacl_matches = false; if current { snapshot.base = current_base.clone(); snapshot.config2 = SERVICE_CONFIG2_KINDS .iter() .copied() .map(expected_current_proxifyre_service_policy) .collect(); current_dacl_matches = matches!( operation, CutoverOperation::SetCurrentServiceSecurity | CutoverOperation::StartCurrentService | CutoverOperation::StopCurrentService ); } snapshot.original_state = if matches!( operation, CutoverOperation::StartCurrentService | CutoverOperation::StartLegacyService ) { ServiceStableState::Running } else { ServiceStableState::Stopped }; complete_service(snapshot, current_dacl_matches) } #[cfg(windows)] #[test] fn missing_primary_service_config2_probe_is_live_and_read_only() { let service = crate::process::query_known_service(KnownWindowsService::Proxifyre) .expect("read-only SCM probe"); if service.exists { eprintln!("skipping missing-service assertion because ProxiFyreService exists"); return; } let executable = std::env::current_exe().expect("current test executable"); assert_eq!( query_service_config2_exact( PROXIFYRE_MANAGED_SERVICE_NAME, &executable, ServiceConfig2Kind::Description, ) .expect("missing service query"), None ); } #[derive(Debug, Clone, PartialEq, Eq)] enum CandidateCall { CreateRoot, WritePackage(PathBuf), WriteConfig, WriteMarker, WriteReceipt, } struct FakeCandidateWriter { calls: Vec, fail_on: Option, fail_after_effect: Option, observation: ProxifyreCutoverCandidateObservation, } impl Default for FakeCandidateWriter { fn default() -> Self { Self { calls: Vec::new(), fail_on: None, fail_after_effect: None, observation: ProxifyreCutoverCandidateObservation::Absent, } } } impl FakeCandidateWriter { fn record(&mut self, call: CandidateCall) -> Result<(), ProxifyreNativeHostError> { self.calls.push(call.clone()); if self.fail_on.as_ref() == Some(&call) { Err(ProxifyreNativeHostError) } else if self.fail_after_effect.as_ref() == Some(&call) { self.observation = expected_candidate_observation(); Err(ProxifyreNativeHostError) } else { Ok(()) } } } impl ProxifyreCutoverCandidateWriter for FakeCandidateWriter { fn observe_candidate( &mut self, operation: &CutoverOperation, ) -> Result { if !matches!( operation, CutoverOperation::CreateCurrentCandidateRoot | CutoverOperation::WriteCurrentCandidatePackageEntry(_) | CutoverOperation::WriteCurrentCandidateConfig | CutoverOperation::WriteCurrentCandidateMarker | CutoverOperation::WriteCurrentCandidateReceipt ) { return Err(ProxifyreNativeHostError); } Ok(self.observation.clone()) } fn create_candidate_root(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(CandidateCall::CreateRoot) } fn write_candidate_package_entry( &mut self, relative_path: &Path, ) -> Result<(), ProxifyreNativeHostError> { self.record(CandidateCall::WritePackage(relative_path.to_path_buf())) } fn write_candidate_config(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(CandidateCall::WriteConfig) } fn write_candidate_marker(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(CandidateCall::WriteMarker) } fn write_candidate_receipt(&mut self) -> Result<(), ProxifyreNativeHostError> { self.record(CandidateCall::WriteReceipt) } } fn expected_candidate_observation() -> ProxifyreCutoverCandidateObservation { let snapshot: SealedPathSnapshot = serde_json::from_value(serde_json::json!({ "identity": { "volumeSerialNumber": 7, "fileId": 11, "kind": "regular_file", "size": 3 }, "security": { "selfRelative": [1, 2, 3], "sacl": "present" } })) .expect("sealed candidate fixture"); ProxifyreCutoverCandidateObservation::Expected(snapshot) } #[test] fn candidate_dispatch_selects_exactly_one_create_new_mutation() { let mut writer = FakeCandidateWriter::default(); let relative_path = PathBuf::from("ProxiFyre.exe"); assert!(mutate_proxifyre_cutover_candidate( &mut writer, &CutoverOperation::WriteCurrentCandidatePackageEntry(relative_path.clone()), ) .expect("candidate mutation dispatch")); assert_eq!( writer.calls, vec![CandidateCall::WritePackage(relative_path)] ); } #[test] fn candidate_collision_or_write_failure_is_not_hidden() { let mut writer = FakeCandidateWriter { fail_on: Some(CandidateCall::WriteReceipt), ..FakeCandidateWriter::default() }; mutate_proxifyre_cutover_candidate( &mut writer, &CutoverOperation::WriteCurrentCandidateReceipt, ) .expect_err("collision/failure must surface"); assert_eq!(writer.calls, vec![CandidateCall::WriteReceipt]); } #[test] fn candidate_failed_create_or_write_distinguishes_no_effect_from_reacquired_exact_effect() { for (operation, call) in [ ( CutoverOperation::CreateCurrentCandidateRoot, CandidateCall::CreateRoot, ), ( CutoverOperation::WriteCurrentCandidateReceipt, CandidateCall::WriteReceipt, ), ] { let mut before_effect = FakeCandidateWriter { fail_on: Some(call.clone()), ..FakeCandidateWriter::default() }; mutate_proxifyre_cutover_candidate(&mut before_effect, &operation) .expect_err("failure before external effect"); assert_eq!( before_effect .observe_candidate(&operation) .expect("observe absent target"), ProxifyreCutoverCandidateObservation::Absent ); let mut after_effect = FakeCandidateWriter { fail_after_effect: Some(call), ..FakeCandidateWriter::default() }; mutate_proxifyre_cutover_candidate(&mut after_effect, &operation) .expect_err("failure after external effect"); let observed = after_effect .observe_candidate(&operation) .expect("reacquire exact target"); assert!(matches!( observed, ProxifyreCutoverCandidateObservation::Expected(SealedPathSnapshot { identity: safe_fs::StableObjectIdentity { volume_serial_number: 7, file_id: 11, .. }, .. }) )); } } #[test] fn candidate_observer_keeps_unknown_distinct_from_absent_and_expected() { let operation = CutoverOperation::CreateCurrentCandidateRoot; let mut writer = FakeCandidateWriter { observation: ProxifyreCutoverCandidateObservation::Unknown, ..FakeCandidateWriter::default() }; assert_eq!( writer .observe_candidate(&operation) .expect("typed unknown observation"), ProxifyreCutoverCandidateObservation::Unknown ); assert_ne!( ProxifyreCutoverCandidateObservation::Unknown, ProxifyreCutoverCandidateObservation::Absent ); assert_ne!( ProxifyreCutoverCandidateObservation::Unknown, expected_candidate_observation() ); } #[test] fn candidate_dispatch_does_not_claim_scm_or_legacy_filesystem_operations() { let mut writer = FakeCandidateWriter::default(); assert!(!mutate_proxifyre_cutover_candidate( &mut writer, &CutoverOperation::CreateCurrentService, ) .expect("non-candidate operation")); assert!(writer.calls.is_empty()); } #[test] fn partial_candidate_handoff_accepts_only_unique_durable_forward_identity() { let operation = CutoverOperation::CreateCurrentCandidateRoot; let identity = safe_fs::StableObjectIdentity { volume_serial_number: 7, file_id: 11, kind: safe_fs::StableObjectKind::Directory, size: 0, }; let fingerprint = StateFingerprint::digest("candidate-handoff-test", b"state"); let durable = MutationRecord { sequence: 0, direction: MutationDirection::Forward, operation: operation.clone(), before_state: fingerprint.clone(), expected_effect: fingerprint.clone(), intent_written_at_epoch_seconds: 1, authority_evidence: None, effect: Some(MutationEffect { disposition: EffectDisposition::ExpectedEffect, observed: fingerprint, object_identity: Some(identity.clone()), observed_at_epoch_seconds: 2, }), }; assert_eq!( unique_forward_expected_effect_identity(std::slice::from_ref(&durable), &operation) .expect("unique durable identity"), Some(&identity) ); let mut pending = durable.clone(); pending.effect = None; assert_eq!( unique_forward_expected_effect_identity(&[pending], &operation) .expect("pending intent is not durable effect"), None ); let mut missing_identity = durable.clone(); missing_identity.effect.as_mut().unwrap().object_identity = None; assert!(unique_forward_expected_effect_identity(&[missing_identity], &operation).is_err()); assert!( unique_forward_expected_effect_identity(&[durable.clone(), durable], &operation).is_err() ); } #[test] fn prepared_candidate_freezes_complete_sorted_final_metadata() { let (plan, runtime, config, config_sha256) = candidate_inputs(); let prepared = prepare_proxifyre_cutover_candidate( &plan, runtime, &config, &config_sha256, false, 1_700_000_000, ) .expect("prepare complete cutover candidate"); assert_eq!( prepared.snapshot().files.len(), CURRENT_PROXIFYRE_PACKAGE_FILES.len() + 3 ); assert!(valid_sha256(&prepared.snapshot().manifest_fingerprint)); assert!(prepared.snapshot().files.windows(2).all(|pair| { candidate_relative_label(&pair[0].relative_path) < candidate_relative_label(&pair[1].relative_path) })); let config_spec = prepared .file_spec(Path::new("app-config.json")) .expect("config spec"); assert_eq!(config_spec.role, CurrentCandidateFileRole::Config); assert_eq!(config_spec.sha256, config_sha256); let marker: SystemProxifyreMarker = serde_json::from_slice( prepared .file_bytes(Path::new(PROXIFYRE_MARKER_FILE)) .expect("marker bytes"), ) .expect("marker JSON"); assert!(marker.packet_filter_installed_by_proxy_warden); let receipt: InstallReceipt = serde_json::from_slice( prepared .file_bytes(Path::new(INSTALL_RECEIPT_FILENAME)) .expect("receipt bytes"), ) .expect("receipt JSON"); assert_eq!(receipt.installed_at, 1_700_000_000); assert!(receipt .windows_packet_filter .as_ref() .is_some_and(|ownership| ownership.installed_by_proxy_warden)); let (_, repeated_runtime, _, _) = candidate_inputs_with_plan(&plan); let repeated = prepare_proxifyre_cutover_candidate( &plan, repeated_runtime, &config, &config_sha256, false, 1_700_000_000, ) .expect("repeat identical candidate"); assert_eq!( prepared.snapshot().manifest_fingerprint, repeated.snapshot().manifest_fingerprint ); } #[test] fn captured_timestamp_and_preexisting_packet_filter_change_final_manifest() { let (plan, runtime, config, config_sha256) = candidate_inputs(); let first = prepare_proxifyre_cutover_candidate( &plan, runtime, &config, &config_sha256, false, 1_700_000_000, ) .expect("first candidate"); let (_, runtime, _, _) = candidate_inputs_with_plan(&plan); let second = prepare_proxifyre_cutover_candidate( &plan, runtime, &config, &config_sha256, true, 1_700_000_001, ) .expect("second candidate"); assert_ne!( first.snapshot().manifest_fingerprint, second.snapshot().manifest_fingerprint ); let receipt: InstallReceipt = serde_json::from_slice( second .file_bytes(Path::new(INSTALL_RECEIPT_FILENAME)) .expect("receipt bytes"), ) .expect("receipt JSON"); assert!(receipt.windows_packet_filter.is_none()); } fn candidate_inputs() -> ( ProxifyreCutoverPlan, PreparedProxifyreRuntime, Vec, String, ) { let app_root = std::env::temp_dir().join("proxywarden-cutover-contract"); let config = br#"{"proxies":[],"applications":[]}"#.to_vec(); let config_sha256 = format!("{:x}", Sha256::digest(&config)); let package_sha256 = "a".repeat(64); let plan = ProxifyreCutoverPlan::new( &app_root, PathBuf::from(r"C:\Tools\ProxiFyre"), LegacyServiceState::Stopped, "2.2.1".to_owned(), package_sha256, config_sha256.clone(), "b".repeat(64), uuid::Uuid::new_v4().hyphenated().to_string(), ); let (_, runtime, _, _) = candidate_inputs_with_plan(&plan); (plan, runtime, config, config_sha256) } fn candidate_inputs_with_plan( plan: &ProxifyreCutoverPlan, ) -> ( ProxifyreCutoverPlan, PreparedProxifyreRuntime, Vec, String, ) { let files: Vec<_> = CURRENT_PROXIFYRE_PACKAGE_FILES .iter() .enumerate() .map(|(index, name)| { let bytes = vec![u8::try_from(index + 1).expect("small fixture index")]; ProxifyreStagedFile { relative_path: (*name).to_owned(), sha256: format!("{:x}", Sha256::digest(&bytes)), size: bytes.len() as u64, bytes, } }) .collect(); let runtime = PreparedProxifyreRuntime { proof: PrivilegedPackageProof { component_id: ComponentId::Proxifyre, version: plan.bundled_version.clone(), asset_name: "proxifyre.zip".to_owned(), sha256: plan.package_fingerprint.clone(), size: 123, source: PackageSource::Bundled, independent_proof: None, }, installed_files: installed_file_inventory(&files), files, }; let config = br#"{"proxies":[],"applications":[]}"#.to_vec(); let config_sha256 = format!("{:x}", Sha256::digest(&config)); (plan.clone(), runtime, config, config_sha256) }