Release v2.0.0
CI / Windows baseline (push) Canceled after 0s

This commit is contained in:
2026-09-10 20:59:52 +03:00
parent 9c987df6e9
commit efda8eb98f
142 changed files with 68308 additions and 9333 deletions
@@ -0,0 +1,921 @@
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<Call>,
fail_on: Option<Call>,
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<ServiceRestoreSnapshot, ProxifyreNativeHostError> {
self.record(Call::CaptureLegacy)?;
Ok(self.before.clone())
}
fn query_legacy_service(&mut self) -> Result<ServicePolicySnapshot, ProxifyreNativeHostError> {
self.record(Call::QueryLegacy)?;
Ok(Self::missing_policy())
}
fn query_current_service(&mut self) -> Result<ServicePolicySnapshot, ProxifyreNativeHostError> {
self.record(Call::QueryCurrent)?;
Ok(Self::missing_policy())
}
fn query_complete_service(
&mut self,
) -> Result<CompleteServiceObservation, ProxifyreNativeHostError> {
self.record(Call::QueryComplete)?;
Ok(self.complete.clone())
}
fn expected_current_service_base(
&self,
) -> Result<ServiceBaseConfigSnapshot, ProxifyreNativeHostError> {
Ok(self.current_base.clone())
}
fn query_legacy_service_policy(
&mut self,
kind: ServiceConfig2Kind,
) -> Result<Option<ServiceConfig2Snapshot>, ProxifyreNativeHostError> {
self.record(Call::QueryLegacyPolicy(kind))?;
Ok(self.before.config2(kind).cloned())
}
fn query_current_service_policy(
&mut self,
kind: ServiceConfig2Kind,
) -> Result<Option<ServiceConfig2Snapshot>, ProxifyreNativeHostError> {
self.record(Call::QueryCurrentPolicy(kind))?;
Ok(None)
}
fn current_service_security_matches(&mut self) -> Result<bool, ProxifyreNativeHostError> {
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<CandidateCall>,
fail_on: Option<CandidateCall>,
fail_after_effect: Option<CandidateCall>,
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<ProxifyreCutoverCandidateObservation, ProxifyreNativeHostError> {
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<u8>,
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<u8>,
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)
}