"""Software-only checks for transactional bootstrap target deployment.""" from __future__ import annotations import hashlib import json import os from pathlib import Path import shutil import subprocess import pytest BOOTSTRAP_ID = "rf001-bootstrap-2026.09.29.4" RELEASE_ID = "rf001-agent-2026.09.29.1" AGENT_VERSION = "2026.09.29.1" RELEASE_PREFIX = f"versions/{RELEASE_ID}/" FUNCTIONS = ( "Get-LowerSha256", "Assert-ExactReleasePath", "Get-ReleaseDirectoryState", "Assert-ReleaseMetadata", "New-UniqueQuarantineDestination", "Write-CreateNewUtf8Json", "Move-ConflictingTargetToQuarantine", "Move-FailedReleasePathToQuarantine", "Install-CleanRelease", "Prepare-TargetRelease", ) def _powershell() -> str: executable = shutil.which("powershell.exe") if executable is None: pytest.skip("Windows PowerShell is required for installer transaction tests") return executable def _installer() -> Path: return Path(__file__).parents[1] / "tools" / "install_rf001_rx_autostart.ps1" def _sha256(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as stream: while block := stream.read(1024 * 1024): digest.update(block) return digest.hexdigest() def _release_fixture(tmp_path: Path) -> tuple[Path, Path, Path, Path]: install_root = tmp_path / "install" versions_root = install_root / "versions" target = versions_root / RELEASE_ID source = tmp_path / "signed-bootstrap" / "versions" / RELEASE_ID tools = source / "app" / "tools" tools.mkdir(parents=True) (tools / "rf001_rx_http_agent.py").write_text( f'AGENT_VERSION = "{AGENT_VERSION}"\n', encoding="utf-8" ) (tools / "rf001_agent_update.py").write_text( "# fixed signed updater fixture\n", encoding="utf-8" ) ready = { "agent_version": AGENT_VERSION, "bootstrap_id": BOOTSTRAP_ID, "hardware_accessed": False, "protocol_version": 1, "release_id": RELEASE_ID, "rf_tx": 0, "schema_version": 1, "status": "READY", } (source / "READY.json").write_text( json.dumps(ready, sort_keys=True, separators=(",", ":")) + "\n", encoding="utf-8", ) rows = [] for path in sorted(item for item in source.rglob("*") if item.is_file()): relative = path.relative_to(source).as_posix() rows.append( { "path": RELEASE_PREFIX + relative, "bytes": path.stat().st_size, "sha256": _sha256(path), } ) manifest = tmp_path / "release_rows.json" manifest.write_text(json.dumps(rows), encoding="utf-8") versions_root.mkdir(parents=True) return source, install_root, target, manifest def _function_loader() -> str: names = ",".join(f'"{name}"' for name in FUNCTIONS) return rf""" $ErrorActionPreference = "Stop" $tokens = $null $parseErrors = $null $syntax = [Management.Automation.Language.Parser]::ParseFile( $env:RF001_INSTALLER, [ref]$tokens, [ref]$parseErrors ) if ($parseErrors.Count -ne 0) {{ throw "Installer contains PowerShell parse errors" }} foreach ($name in @({names})) {{ $matches = @($syntax.FindAll({{ param($node) $node -is [Management.Automation.Language.FunctionDefinitionAst] -and $node.Name -eq $name }}, $true)) if ($matches.Count -ne 1) {{ throw "Installer function is absent or ambiguous: $name" }} . ([scriptblock]::Create($matches[0].Extent.Text)) }} $releaseRows = @(Get-Content -LiteralPath $env:RF001_ROWS -Raw -Encoding UTF8 | ConvertFrom-Json) $installRoot = $env:RF001_INSTALL_ROOT $versionsRoot = Join-Path $installRoot "versions" $sourceRelease = $env:RF001_SOURCE_RELEASE $targetRelease = Join-Path $versionsRoot "{RELEASE_ID}" """ def _run_powershell( body: str, *, source: Path, install_root: Path, manifest: Path, check: bool = True, ) -> subprocess.CompletedProcess[str]: environment = os.environ.copy() environment.update( { "RF001_INSTALLER": str(_installer()), "RF001_ROWS": str(manifest), "RF001_INSTALL_ROOT": str(install_root), "RF001_SOURCE_RELEASE": str(source), } ) completed = subprocess.run( [_powershell(), "-NoProfile", "-NonInteractive", "-Command", _function_loader() + body], check=False, capture_output=True, encoding="utf-8", env=environment, ) if check and completed.returncode != 0: raise AssertionError( f"PowerShell transaction harness failed ({completed.returncode}):\n" f"STDOUT:\n{completed.stdout}\nSTDERR:\n{completed.stderr}" ) return completed def _prepare( source: Path, install_root: Path, manifest: Path, ) -> dict[str, object]: body = rf""" $result = Prepare-TargetRelease ` -InstallRoot $installRoot ` -VersionsRoot $versionsRoot ` -SourceRelease $sourceRelease ` -TargetRelease $targetRelease ` -ReleaseId "{RELEASE_ID}" ` -BootstrapId "{BOOTSTRAP_ID}" ` -AgentVersion "{AGENT_VERSION}" ` -ProtocolVersion 1 ` -ReleaseRows $releaseRows ` -ReleasePrefix "{RELEASE_PREFIX}" $final = Get-ReleaseDirectoryState ` -TargetRelease $targetRelease ` -ReleaseRows $releaseRows ` -ReleasePrefix "{RELEASE_PREFIX}" [ordered]@{{ result = $result final_state = $final.state }} | ConvertTo-Json -Depth 10 -Compress """ completed = _run_powershell( body, source=source, install_root=install_root, manifest=manifest, ) value = json.loads(completed.stdout.lstrip("\ufeff")) assert isinstance(value, dict) return value def _snapshot(root: Path) -> dict[str, tuple[int, int, str]]: return { path.relative_to(root).as_posix(): ( path.stat().st_size, path.stat().st_mtime_ns, _sha256(path), ) for path in root.rglob("*") if path.is_file() } def _assert_matches_manifest(target: Path, manifest: Path) -> None: rows = json.loads(manifest.read_text(encoding="utf-8")) expected = { str(row["path"])[len(RELEASE_PREFIX) :]: ( int(row["bytes"]), str(row["sha256"]), ) for row in rows } actual = { path.relative_to(target).as_posix(): (path.stat().st_size, _sha256(path)) for path in target.rglob("*") if path.is_file() } assert actual == expected def test_absent_target_is_deployed_from_signed_manifest(tmp_path: Path) -> None: source, install_root, target, manifest = _release_fixture(tmp_path) report = _prepare(source, install_root, manifest) assert report["result"]["initial_state"] == "TARGET_ABSENT" assert report["result"]["reused"] is False assert report["final_state"] == "TARGET_VERIFIED" _assert_matches_manifest(target, manifest) def test_exact_target_is_reused_without_writing_bytes(tmp_path: Path) -> None: source, install_root, target, manifest = _release_fixture(tmp_path) shutil.copytree(source, target) before = _snapshot(target) report = _prepare(source, install_root, manifest) assert report["result"]["initial_state"] == "TARGET_VERIFIED" assert report["result"]["reused"] is True assert _snapshot(target) == before def test_mixed_release_is_quarantined_before_clean_deployment(tmp_path: Path) -> None: source, install_root, target, manifest = _release_fixture(tmp_path) shutil.copytree(source, target) agent = target / "app" / "tools" / "rf001_rx_http_agent.py" agent.write_text('AGENT_VERSION = "2026.09.29.2"\n', encoding="utf-8") ready = json.loads((target / "READY.json").read_text(encoding="utf-8")) ready["bootstrap_id"] = "rf001-bootstrap-2026.09.29.2" (target / "READY.json").write_text(json.dumps(ready), encoding="utf-8") conflict_hash = _sha256(agent) report = _prepare(source, install_root, manifest) result = report["result"] assert result["initial_state"] == "TARGET_CONFLICT" quarantine = Path(str(result["quarantine_path"])) diagnostic_path = Path(str(result["quarantine_diagnostic"])) assert quarantine.is_dir() assert _sha256(quarantine / "app" / "tools" / agent.name) == conflict_hash diagnostic = json.loads(diagnostic_path.read_text(encoding="utf-8-sig")) assert diagnostic["bootstrap_id"] == BOOTSTRAP_ID assert diagnostic["expected_release_id"] == RELEASE_ID assert {row["kind"] for row in diagnostic["mismatches"]} >= { "SHA256_MISMATCH" } assert any(row["sha256"] == conflict_hash for row in diagnostic["conflicting_files"]) _assert_matches_manifest(target, manifest) @pytest.mark.parametrize( ("case", "expected_kind"), ( ("ready_mismatch", "SHA256_MISMATCH"), ("python_mismatch", "SHA256_MISMATCH"), ("missing", "MISSING"), ("unexpected", "UNEXPECTED"), ), ) def test_each_file_set_conflict_is_quarantined( tmp_path: Path, case: str, expected_kind: str, ) -> None: source, install_root, target, manifest = _release_fixture(tmp_path) shutil.copytree(source, target) if case == "ready_mismatch": (target / "READY.json").write_bytes(b"{}\n") elif case == "python_mismatch": (target / "app" / "tools" / "rf001_agent_update.py").write_bytes(b"changed\n") elif case == "missing": (target / "app" / "tools" / "rf001_agent_update.py").unlink() else: (target / "app" / "tools" / "unexpected.py").write_bytes(b"unexpected\n") result = _prepare(source, install_root, manifest)["result"] diagnostic = json.loads( Path(str(result["quarantine_diagnostic"])).read_text(encoding="utf-8-sig") ) assert expected_kind in {row["kind"] for row in diagnostic["mismatches"]} _assert_matches_manifest(target, manifest) def test_failure_after_quarantine_leaves_canonical_target_absent(tmp_path: Path) -> None: source, install_root, target, manifest = _release_fixture(tmp_path) shutil.copytree(source, target) (target / "READY.json").write_bytes(b"conflict\n") body = rf""" $state = Get-ReleaseDirectoryState ` -TargetRelease $targetRelease ` -ReleaseRows $releaseRows ` -ReleasePrefix "{RELEASE_PREFIX}" $quarantine = Move-ConflictingTargetToQuarantine ` -InstallRoot $installRoot ` -VersionsRoot $versionsRoot ` -TargetRelease $targetRelease ` -ReleaseId "{RELEASE_ID}" ` -BootstrapId "{BOOTSTRAP_ID}" ` -State $state try {{ throw "fixed failure after quarantine before target creation" }} catch {{ [ordered]@{{ error = $_.Exception.Message canonical_exists = Test-Path -LiteralPath $targetRelease quarantine_exists = Test-Path -LiteralPath $quarantine.path -PathType Container diagnostic_exists = Test-Path -LiteralPath $quarantine.diagnostic_path -PathType Leaf }} | ConvertTo-Json -Compress }} """ completed = _run_powershell( body, source=source, install_root=install_root, manifest=manifest ) report = json.loads(completed.stdout.lstrip("\ufeff")) assert report == { "error": "fixed failure after quarantine before target creation", "canonical_exists": False, "quarantine_exists": True, "diagnostic_exists": True, } def test_failure_during_deployment_quarantines_partial_staging(tmp_path: Path) -> None: source, install_root, target, manifest = _release_fixture(tmp_path) (source / "READY.json").unlink() body = rf""" try {{ Install-CleanRelease ` -InstallRoot $installRoot ` -VersionsRoot $versionsRoot ` -SourceRelease $sourceRelease ` -TargetRelease $targetRelease ` -ReleaseId "{RELEASE_ID}" ` -BootstrapId "{BOOTSTRAP_ID}" ` -AgentVersion "{AGENT_VERSION}" ` -ProtocolVersion 1 ` -ReleaseRows $releaseRows ` -ReleasePrefix "{RELEASE_PREFIX}" | Out-Null throw "deployment unexpectedly succeeded" }} catch {{ $failed = @(Get-ChildItem -LiteralPath (Join-Path $installRoot "quarantine") -Directory | Where-Object {{ $_.Name -like "{RELEASE_ID}_failed_staging_*" }}) [ordered]@{{ error = $_.Exception.Message canonical_exists = Test-Path -LiteralPath $targetRelease failed_staging_count = $failed.Count }} | ConvertTo-Json -Compress }} """ completed = _run_powershell( body, source=source, install_root=install_root, manifest=manifest ) report = json.loads(completed.stdout.lstrip("\ufeff")) assert "Clean release deployment failed" in report["error"] assert report["canonical_exists"] is False assert report["failed_staging_count"] == 1 def test_installer_switch_failure_restores_saved_task_and_launcher_state() -> None: text = _installer().read_text(encoding="utf-8-sig") switch = text.index("Set-ScheduledTask -TaskName $taskName -Action $action") catch = text.index("catch {", switch) restore_task = text.index("Register-ScheduledTask -TaskName $taskName -Xml $xml -Force", catch) restore_files = text.index('foreach ($name in @("launcher"', catch) restart_old = text.index("if ($wasRunning)", catch) assert switch < catch < restore_task < restore_files < restart_old def test_successful_reinstall_is_idempotent(tmp_path: Path) -> None: source, install_root, target, manifest = _release_fixture(tmp_path) first = _prepare(source, install_root, manifest) before = _snapshot(target) second = _prepare(source, install_root, manifest) assert first["result"]["initial_state"] == "TARGET_ABSENT" assert second["result"]["initial_state"] == "TARGET_VERIFIED" assert second["result"]["reused"] is True assert _snapshot(target) == before quarantine = install_root / "quarantine" assert not quarantine.exists() or not any(quarantine.iterdir()) def test_existing_quarantine_is_never_overwritten(tmp_path: Path) -> None: source, install_root, target, manifest = _release_fixture(tmp_path) shutil.copytree(source, target) (target / "READY.json").write_bytes(b"conflict\n") sentinel = install_root / "quarantine" / "existing-audit" / "sentinel.bin" sentinel.parent.mkdir(parents=True) sentinel.write_bytes(b"must remain unchanged") before = _snapshot(sentinel.parent) result = _prepare(source, install_root, manifest)["result"] assert _snapshot(sentinel.parent) == before assert Path(str(result["quarantine_path"])) != sentinel.parent def test_matching_version_strings_do_not_validate_changed_bytes(tmp_path: Path) -> None: source, install_root, target, manifest = _release_fixture(tmp_path) shutil.copytree(source, target) agent = target / "app" / "tools" / "rf001_rx_http_agent.py" agent.write_text( f'# changed bytes, same identity strings\nAGENT_VERSION = "{AGENT_VERSION}"\n', encoding="utf-8", ) result = _prepare(source, install_root, manifest)["result"] assert result["initial_state"] == "TARGET_CONFLICT" assert result["reused"] is False _assert_matches_manifest(target, manifest)