Harden RF node control and agent updates

This commit is contained in:
LittleSam129
2026-09-30 11:42:19 +03:00
parent a94f2db4ee
commit 0d6fff224e
34 changed files with 14010 additions and 0 deletions

View File

@@ -0,0 +1,625 @@
"""Software-only tests for the stable versioned RX-agent launcher."""
from __future__ import annotations
from dataclasses import replace
from datetime import datetime, timedelta, timezone
import json
from pathlib import Path
import subprocess
import pytest
import tools.rf001_agent_launcher as launcher
class FakeProcess:
def __init__(self, process_id: int, returncode: int | None = None) -> None:
self.pid = process_id
self.returncode = returncode
def poll(self) -> int | None:
return self.returncode
def terminate(self) -> None:
self.returncode = 0
def kill(self) -> None:
self.returncode = -9
def wait(self, timeout: float | None = None) -> int:
del timeout
if self.returncode is None:
self.returncode = 0
return self.returncode
NOW = datetime(2026, 9, 29, 13, 0, tzinfo=timezone.utc)
WRAPPER = r"C:\runtime\.venv\Scripts\pythonw.exe"
CHILD = r"C:\runtime\Python313\python.exe"
AGENT = r"C:\release\app\tools\rf001_rx_http_agent.py"
def _attempt(
*,
process_id: int = 200,
nonce: str = "current-launch-nonce",
returncode: int | None = None,
) -> launcher.LaunchAttempt:
command = (
WRAPPER,
"-u",
"-B",
"-X",
"utf8",
AGENT,
"--launch-nonce",
nonce,
)
return launcher.LaunchAttempt(
process=FakeProcess(process_id, returncode), # type: ignore[arg-type]
command=command,
wrapper_pid=process_id,
launch_boundary=NOW.isoformat(),
wrapper_executable=WRAPPER,
child_executable=CHILD,
launch_nonce=nonce,
)
def _identity(
pid: int,
parent_pid: int,
*,
executable: str,
command: tuple[str, ...] | None = None,
seconds: float = 1.0,
) -> launcher.ProcessIdentity:
return launcher.ProcessIdentity(
pid=pid,
parent_pid=parent_pid,
executable=executable,
command_line=subprocess.list2cmdline(command or _attempt().command),
created_at=(NOW + timedelta(seconds=seconds)).isoformat(),
)
def _wrapper(attempt: launcher.LaunchAttempt | None = None) -> launcher.ProcessIdentity:
value = attempt or _attempt()
return _identity(
value.wrapper_pid,
100,
executable=value.wrapper_executable,
command=value.command,
)
def _child(attempt: launcher.LaunchAttempt | None = None) -> launcher.ProcessIdentity:
value = attempt or _attempt()
return _identity(
value.wrapper_pid + 1,
value.wrapper_pid,
executable=value.child_executable,
command=value.command,
)
def _health(
*,
pid: int = 200,
release_id: str = "rf001-agent-2026.09.29.1",
version: str = "2026.09.29.1",
nonce: str = "current-launch-nonce",
state: str = "RUNNING",
updated_at: str | None = None,
) -> dict[str, object]:
return {
"release_id": release_id,
"agent_version": version,
"launch_nonce": nonce,
"state": state,
"pid": pid,
"updated_at": updated_at or (NOW + timedelta(seconds=2)).isoformat(),
}
def _config(tmp_path: Path) -> dict[str, object]:
install = tmp_path / "install"
config: dict[str, object] = {
"install_root": str(install),
"releases_root": str(install / "versions"),
"active_release_file": str(install / "active_release.json"),
"launcher_status": str(install / "launcher_status.json"),
"launcher_request": str(install / "launcher_request.json"),
"health_file": str(install / "agent_health.json"),
"agent_log": str(install / "logs" / "agent.log"),
"agent_arguments": [],
}
return config
def _ready(config: dict[str, object], release_id: str, version: str) -> None:
root = Path(str(config["releases_root"])) / release_id
(root / "app" / "tools").mkdir(parents=True)
(root / "app" / "tools" / "rf001_rx_http_agent.py").write_text(
"# fixture\n", encoding="utf-8"
)
(root / "READY.json").write_text(
json.dumps(
{
"status": "READY",
"release_id": release_id,
"agent_version": version,
}
),
encoding="utf-8",
)
def _request(
config: dict[str, object],
current: str,
target: str,
version: str,
) -> dict[str, object]:
value = {
"task_id": "UPDATE_TEST_001",
"from_release_id": current,
"release_id": target,
"agent_version": version,
"safe_to_switch": True,
}
path = Path(str(config["launcher_request"]))
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(value), encoding="utf-8")
Path(str(config["health_file"])).write_text(
json.dumps({"busy": False, "active_task_id": None}),
encoding="utf-8",
)
return value
def test_launcher_switches_only_to_ready_release(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
config = _config(tmp_path)
old = "rf001-agent-2026.09.29.1"
new = "rf001-agent-2026.09.29.2"
_ready(config, old, "2026.09.29.1")
_ready(config, new, "2026.09.29.2")
request = _request(config, old, new, "2026.09.29.2")
terminated: list[FakeProcess] = []
monkeypatch.setattr(
launcher,
"terminate_process",
lambda process: terminated.append(process),
)
monkeypatch.setattr(
launcher,
"start_release",
lambda *_args, **_kwargs: (FakeProcess(2), "2026.09.29.2"),
)
process, release_id, version = launcher.switch_release(
config,
FakeProcess(1),
old,
"2026.09.29.1",
request,
)
assert process.pid == 2
assert release_id == new
assert version == "2026.09.29.2"
assert len(terminated) == 1
active = json.loads(Path(str(config["active_release_file"])).read_text())
assert active["release_id"] == new
status = json.loads(Path(str(config["launcher_status"])).read_text())
assert status["state"] == "RUNNING"
assert status["phase"] == "TARGET_HEALTHY"
assert status["rf_tx"] == 0
def test_launcher_rolls_back_after_new_version_start_failure(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
config = _config(tmp_path)
old = "rf001-agent-2026.09.29.1"
new = "rf001-agent-2026.09.29.2"
_ready(config, old, "2026.09.29.1")
_ready(config, new, "2026.09.29.2")
request = _request(config, old, new, "2026.09.29.2")
calls: list[str] = []
def fake_start(
_config_value: object,
release_id: str,
*,
expected_version: str | None = None,
) -> tuple[FakeProcess, str]:
del expected_version
calls.append(release_id)
if release_id == new:
raise RuntimeError("fixed startup failure")
return FakeProcess(3), "2026.09.29.1"
monkeypatch.setattr(launcher, "terminate_process", lambda _process: None)
monkeypatch.setattr(launcher, "start_release", fake_start)
process, release_id, version = launcher.switch_release(
config,
FakeProcess(1),
old,
"2026.09.29.1",
request,
)
assert process.pid == 3
assert release_id == old
assert version == "2026.09.29.1"
assert calls == [new, old]
active = json.loads(Path(str(config["active_release_file"])).read_text())
assert active["release_id"] == old
status = json.loads(Path(str(config["launcher_status"])).read_text())
assert status["state"] == "ROLLED_BACK"
assert status["phase"] == "LEGACY_RESTORED"
assert "fixed startup failure" in status["error"]
def test_launcher_rejects_busy_agent_without_stopping_it(tmp_path: Path) -> None:
config = _config(tmp_path)
old = "rf001-agent-2026.09.29.1"
new = "rf001-agent-2026.09.29.2"
_ready(config, old, "2026.09.29.1")
_ready(config, new, "2026.09.29.2")
request = _request(config, old, new, "2026.09.29.2")
Path(str(config["health_file"])).write_text(
json.dumps({"busy": True, "active_task_id": "STAIRCASE_TEST"}),
encoding="utf-8",
)
with pytest.raises(RuntimeError, match="not idle"):
launcher.switch_release(
config,
FakeProcess(1),
old,
"2026.09.29.1",
request,
)
def test_direct_exact_identity_passes() -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
result = launcher._validate_target_identity(
attempt,
wrapper,
attempt.wrapper_pid,
[wrapper],
)
assert result.mode == "DIRECT"
assert result.target == wrapper
def test_unique_expected_wrapper_child_passes() -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
child = _child(attempt)
result = launcher._validate_target_identity(
attempt,
wrapper,
child.pid,
[wrapper, child],
)
assert result.mode == "WINDOWS_VENV_WRAPPER"
assert result.target == child
@pytest.mark.parametrize(
("field", "value"),
[
("launch_nonce", "wrong"),
("release_id", "rf001-agent-2026.09.29.9"),
("agent_version", "2026.09.29.9"),
("state", "STARTING"),
],
)
def test_wrong_health_field_fails(field: str, value: str) -> None:
health = _health()
health[field] = value
assert not launcher._health_fields_match(
health,
release_id="rf001-agent-2026.09.29.1",
agent_version="2026.09.29.1",
launch_nonce="current-launch-nonce",
launch_boundary=NOW.isoformat(),
)
def test_stale_health_fails() -> None:
health = _health(updated_at=(NOW - timedelta(seconds=1)).isoformat())
assert not launcher._health_fields_match(
health,
release_id="rf001-agent-2026.09.29.1",
agent_version="2026.09.29.1",
launch_nonce="current-launch-nonce",
launch_boundary=NOW.isoformat(),
)
def test_unrelated_pid_fails() -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
unrelated = _identity(300, 999, executable=CHILD)
with pytest.raises(RuntimeError, match="not a direct wrapper child"):
launcher._validate_target_identity(
attempt,
wrapper,
unrelated.pid,
[wrapper, unrelated],
)
def test_unrelated_child_fails() -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
unrelated = replace(
_child(attempt),
command_line="python.exe unrelated.py",
)
with pytest.raises(RuntimeError, match="absent or ambiguous"):
launcher._validate_target_identity(
attempt,
wrapper,
unrelated.pid,
[wrapper, unrelated],
)
def test_unexpected_grandchild_fails() -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
child = _child(attempt)
grandchild = replace(child, pid=202, parent_pid=child.pid)
with pytest.raises(RuntimeError, match="not a direct wrapper child"):
launcher._validate_target_identity(
attempt,
wrapper,
grandchild.pid,
[wrapper, child, grandchild],
)
def test_two_matching_children_fail() -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
first = _child(attempt)
second = replace(first, pid=first.pid + 1)
with pytest.raises(RuntimeError, match="absent or ambiguous"):
launcher._validate_target_identity(
attempt,
wrapper,
first.pid,
[wrapper, first, second],
)
def test_creation_time_mismatch_fails() -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
stale_child = replace(
_child(attempt),
created_at=(NOW - timedelta(seconds=30)).isoformat(),
)
with pytest.raises(RuntimeError, match="absent or ambiguous"):
launcher._validate_target_identity(
attempt,
wrapper,
stale_child.pid,
[wrapper, stale_child],
)
def test_pid_reuse_between_validations_fails(
monkeypatch: pytest.MonkeyPatch,
) -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
child = _child(attempt)
reused = replace(
child,
created_at=(NOW + timedelta(seconds=3)).isoformat(),
)
snapshots = iter(([wrapper, child], [wrapper, reused]))
monkeypatch.setattr(
launcher,
"_query_process_identities",
lambda *_args, **_kwargs: next(snapshots),
)
with pytest.raises(RuntimeError, match="changed during validation"):
launcher._validate_target_twice(
attempt,
wrapper,
child.pid,
)
def test_wrapper_dies_too_early() -> None:
attempt = _attempt(returncode=1)
wrapper = _wrapper(attempt)
with pytest.raises(RuntimeError, match="wrapper died"):
launcher._validate_target_identity(
attempt,
wrapper,
wrapper.pid,
[wrapper],
)
def test_child_dies_before_final_validation(
monkeypatch: pytest.MonkeyPatch,
) -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
child = _child(attempt)
snapshots = iter(([wrapper, child], [wrapper]))
monkeypatch.setattr(
launcher,
"_query_process_identities",
lambda *_args, **_kwargs: next(snapshots),
)
with pytest.raises(RuntimeError, match="health process is absent"):
launcher._validate_target_twice(
attempt,
wrapper,
child.pid,
)
def test_wrong_executable_fails() -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
child = replace(_child(attempt), executable=r"C:\Other\python.exe")
with pytest.raises(RuntimeError, match="absent or ambiguous"):
launcher._validate_target_identity(
attempt,
wrapper,
child.pid,
[wrapper, child],
)
def test_wrong_command_line_fails() -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
child = replace(_child(attempt), command_line="python.exe other_agent.py")
with pytest.raises(RuntimeError, match="absent or ambiguous"):
launcher._validate_target_identity(
attempt,
wrapper,
child.pid,
[wrapper, child],
)
def test_cleanup_terminates_verified_child_and_wrapper_only(
monkeypatch: pytest.MonkeyPatch,
) -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
child = _child(attempt)
unrelated = _identity(300, 999, executable=CHILD)
alive = {wrapper.pid: wrapper, child.pid: child, unrelated.pid: unrelated}
terminated: list[int] = []
def query(wrapper_pid: int, health_pid: int | None = None) -> list[launcher.ProcessIdentity]:
del health_pid
return [
identity
for identity in alive.values()
if identity.pid == wrapper_pid or identity.parent_pid == wrapper_pid
]
def terminate_identity(identity: launcher.ProcessIdentity) -> str:
terminated.append(identity.pid)
alive.pop(identity.pid)
return f"PID {identity.pid}: terminated"
def terminate_wrapper(process: FakeProcess) -> None:
terminated.append(process.pid)
alive.pop(process.pid)
process.returncode = 0
monkeypatch.setattr(launcher, "_query_process_identities", query)
monkeypatch.setattr(launcher, "_terminate_verified_identity", terminate_identity)
monkeypatch.setattr(launcher, "terminate_process", terminate_wrapper)
result = launcher.strict_failure_cleanup(attempt, wrapper)
assert result.state == "COMPLETE"
assert result.orphan_verified_target_processes == ()
assert terminated == [child.pid, wrapper.pid]
assert unrelated.pid in alive
def test_cleanup_unknown_identity_kills_nothing(
monkeypatch: pytest.MonkeyPatch,
) -> None:
attempt = _attempt()
wrapper = _wrapper(attempt)
child = _child(attempt)
killed: list[int] = []
monkeypatch.setattr(
launcher,
"_query_process_identities",
lambda *_args, **_kwargs: [wrapper, child],
)
monkeypatch.setattr(
launcher,
"_terminate_verified_identity",
lambda identity: killed.append(identity.pid),
)
result = launcher.strict_failure_cleanup(attempt, None)
assert result.state == "CLEANUP_INCOMPLETE"
assert killed == []
def test_two_sequential_successful_starts_use_distinct_nonces(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
config = _config(tmp_path)
release_id = "rf001-agent-2026.09.29.1"
_ready(config, release_id, "2026.09.29.1")
nonces = iter(("first-nonce", "second-nonce"))
process_ids = iter((200, 300))
observed: list[tuple[int, str]] = []
monkeypatch.setattr(launcher.secrets, "token_hex", lambda _length: next(nonces))
monkeypatch.setattr(
launcher,
"_runtime_executables",
lambda _value: (WRAPPER, CHILD),
)
def spawn(
command: list[str],
*,
cwd: Path,
log_stream: object,
) -> FakeProcess:
del cwd, log_stream
process = FakeProcess(next(process_ids))
nonce = command[command.index("--launch-nonce") + 1]
Path(str(config["health_file"])).write_text(
json.dumps(_health(pid=process.pid, nonce=nonce, updated_at="2099-01-01T00:00:00+00:00")),
encoding="utf-8",
)
return process
def capture(attempt: launcher.LaunchAttempt, *, timeout_seconds: float) -> launcher.ProcessIdentity:
del timeout_seconds
return _identity(
attempt.wrapper_pid,
100,
executable=WRAPPER,
command=attempt.command,
)
def validate(
attempt: launcher.LaunchAttempt,
wrapper: launcher.ProcessIdentity,
health_pid: int,
) -> launcher.ValidatedTarget:
observed.append((health_pid, attempt.launch_nonce))
return launcher.ValidatedTarget("DIRECT", wrapper, wrapper)
monkeypatch.setattr(launcher, "_spawn_agent", spawn)
monkeypatch.setattr(launcher, "_capture_wrapper_identity", capture)
monkeypatch.setattr(launcher, "_validate_target_twice", validate)
first, _ = launcher.start_release(config, release_id)
second, _ = launcher.start_release(config, release_id)
assert first.pid == 200
assert second.pid == 300
assert observed == [(200, "first-nonce"), (300, "second-nonce")]

View File

@@ -0,0 +1,172 @@
"""Software-only tests for fixed RF-001 agent release archives."""
from __future__ import annotations
import json
from pathlib import Path
import stat
import zipfile
import pytest
from tools.rf001_agent_update import (
CONTENT_MANIFEST_NAME,
RELEASE_SOURCE_FILES,
ReleaseValidationError,
build_release_archive,
canonical_json_bytes,
inspect_release_archive,
sign_update_manifest,
verify_update_manifest_signature,
)
def _source_tree(root: Path, *, agent_version: str = "2026.09.29.1") -> None:
for index, relative in enumerate(RELEASE_SOURCE_FILES.values()):
path = root / relative
path.parent.mkdir(parents=True, exist_ok=True)
content = f"# fixed fixture {index}\n"
if relative == RELEASE_SOURCE_FILES["app/tools/rf001_rx_http_agent.py"]:
content += f'AGENT_VERSION = "{agent_version}"\n'
path.write_text(content, encoding="utf-8")
def test_release_roundtrip_uses_exact_allowlist(tmp_path: Path) -> None:
source = tmp_path / "source"
_source_tree(source)
package = tmp_path / "rf001-agent-2026.09.29.1.zip"
built = build_release_archive(
source,
package,
release_id="rf001-agent-2026.09.29.1",
agent_version="2026.09.29.1",
protocol_version=1,
)
extraction = tmp_path / "extracted"
checked = inspect_release_archive(
package,
expected_package_sha256=built.package_sha256,
expected_package_bytes=built.package_bytes,
expected_content_manifest_sha256=built.content_manifest_sha256,
extraction_root=extraction,
)
assert checked == built
assert {
path.relative_to(extraction).as_posix()
for path in extraction.rglob("*")
if path.is_file()
} == set(RELEASE_SOURCE_FILES) | {CONTENT_MANIFEST_NAME}
def test_update_manifest_rejects_bad_signature() -> None:
token = b"fixed-test-token-0123456789abcdef"
manifest = {
"schema_version": 1,
"release_id": "rf001-agent-2026.09.29.1",
"package_sha256": "a" * 64,
}
signature = sign_update_manifest(token, manifest)
verify_update_manifest_signature(token, manifest, signature)
with pytest.raises(ReleaseValidationError, match="mismatch"):
verify_update_manifest_signature(token, manifest, "0" * 64)
changed = dict(manifest, package_sha256="b" * 64)
with pytest.raises(ReleaseValidationError, match="mismatch"):
verify_update_manifest_signature(token, changed, signature)
@pytest.mark.parametrize(
"unsafe_name",
(
"../outside.py",
"/absolute.py",
"C:/absolute.py",
"app\\tools\\backslash.py",
),
)
def test_release_rejects_unsafe_paths(tmp_path: Path, unsafe_name: str) -> None:
package = tmp_path / "unsafe.zip"
with zipfile.ZipFile(package, "w") as archive:
archive.writestr(unsafe_name, b"x")
# zipfile normalizes a backslash to a slash before it can be inspected;
# that spelling still cannot enter the fixed release allowlist.
with pytest.raises(
ReleaseValidationError,
match="unsafe|drive-like|not allowlisted|manifest is absent",
):
inspect_release_archive(package)
def test_release_rejects_symlink_and_duplicate_names(tmp_path: Path) -> None:
symlink_package = tmp_path / "symlink.zip"
with zipfile.ZipFile(symlink_package, "w") as archive:
info = zipfile.ZipInfo("app/tools/link.py")
info.create_system = 3
info.external_attr = (stat.S_IFLNK | 0o777) << 16
archive.writestr(info, b"target")
with pytest.raises(ReleaseValidationError, match="links"):
inspect_release_archive(symlink_package)
duplicate_package = tmp_path / "duplicate.zip"
with zipfile.ZipFile(duplicate_package, "w") as archive:
archive.writestr("app/tools/a.py", b"a")
archive.writestr("APP/TOOLS/A.PY", b"b")
with pytest.raises(ReleaseValidationError, match="duplicate"):
inspect_release_archive(duplicate_package)
def test_release_rejects_unsupported_protocol_and_sha(tmp_path: Path) -> None:
source = tmp_path / "source"
_source_tree(source)
package = tmp_path / "release.zip"
built = build_release_archive(
source,
package,
release_id="rf001-agent-2026.09.29.1",
agent_version="2026.09.29.1",
protocol_version=2,
)
assert built.protocol_version == 2
with pytest.raises(ReleaseValidationError, match="package SHA256"):
inspect_release_archive(package, expected_package_sha256="0" * 64)
def test_content_manifest_must_be_canonical(tmp_path: Path) -> None:
package = tmp_path / "noncanonical.zip"
manifest = {
"schema_version": 1,
"release_id": "rf001-agent-2026.09.29.1",
"agent_version": "2026.09.29.1",
"protocol_version": 1,
"files": [],
}
assert canonical_json_bytes(manifest) != json.dumps(manifest).encode("utf-8")
with zipfile.ZipFile(package, "w") as archive:
archive.writestr(CONTENT_MANIFEST_NAME, json.dumps(manifest))
with pytest.raises(ReleaseValidationError, match="canonical"):
inspect_release_archive(package)
@pytest.mark.parametrize(
("source_version", "requested_version"),
(
("2026.09.29.2", "2026.09.29.1"),
("2026.09.29.1", "2026.09.29.2"),
),
)
def test_release_builder_rejects_version_mismatch_before_artifact(
tmp_path: Path,
source_version: str,
requested_version: str,
) -> None:
source = tmp_path / "source"
_source_tree(source, agent_version=source_version)
package = tmp_path / "must-not-exist.zip"
with pytest.raises(ReleaseValidationError, match="AGENT_VERSION|release_id"):
build_release_archive(
source,
package,
release_id=f"rf001-agent-{requested_version}",
agent_version=requested_version,
protocol_version=1,
)
assert not package.exists()

View File

@@ -0,0 +1,133 @@
"""Software-only regressions for external bootstrap install evidence."""
from __future__ import annotations
import hashlib
import hmac
import json
from pathlib import Path
import sys
import pytest
from tools.rf001_bootstrap_install_orchestrator import (
EvidencePathError,
PackageValidationError,
SIGNATURE_DOMAIN,
run_installer,
snapshot_tree,
validate_pristine_package,
)
def _sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def _signed_package(tmp_path: Path) -> tuple[Path, Path]:
package = tmp_path / "clean-bootstrap"
package.mkdir()
(package / "INSTALL_RX_AGENT.cmd").write_text("@echo off\n", encoding="utf-8")
payload = package / "payload.bin"
payload.write_bytes(b"fixed bootstrap payload")
rows = []
for path in sorted(item for item in package.rglob("*") if item.is_file()):
rows.append(
{
"path": path.relative_to(package).as_posix(),
"bytes": path.stat().st_size,
"sha256": _sha256(path),
}
)
manifest = {
"schema_version": 1,
"package_kind": "BOOTSTRAP",
"bootstrap_id": "rf001-bootstrap-2099.01.01.1",
"agent_release_id": "rf001-agent-2099.01.01.1",
"agent_version": "2099.01.01.1",
"files": rows,
}
manifest_bytes = (
json.dumps(manifest, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
(package / "BOOTSTRAP_MANIFEST.json").write_bytes(manifest_bytes)
token = tmp_path / "token.txt"
token.write_text("fixed-test-token-0123456789abcdef", encoding="utf-8")
signature = hmac.new(
token.read_text(encoding="utf-8").encode("utf-8"),
SIGNATURE_DOMAIN + manifest_bytes,
hashlib.sha256,
).hexdigest()
(package / "BOOTSTRAP_MANIFEST.hmac").write_text(
signature + "\n",
encoding="ascii",
)
return package, token
def test_pristine_package_uses_external_logs_and_remains_unchanged(
tmp_path: Path,
) -> None:
package, token = _signed_package(tmp_path)
evidence = tmp_path / "external-evidence"
before = snapshot_tree(package)
command = [
sys.executable,
"-c",
"import sys; print('installer stdout'); print('installer stderr', file=sys.stderr)",
]
result = run_installer(package, evidence, token, command=command)
assert result["exit_code"] == 0
assert result["package_content_unchanged_immediate"] is True
assert result["package_content_unchanged_after"] is True
assert result["package_metadata_unchanged_after"] is True
assert snapshot_tree(package) == before
assert (evidence / "install.stdout.txt").read_text().strip() == "installer stdout"
assert (evidence / "install.stderr.txt").read_text().strip() == "installer stderr"
assert not (package / "install.stdout.txt").exists()
assert not (package / "install.stderr.txt").exists()
preflight = json.loads((evidence / "package_preflight.json").read_text())
assert preflight["hmac"] == "PASS"
assert preflight["unexpected"] == 0
assert preflight["missing"] == 0
def test_contaminated_package_fails_closed_before_command(tmp_path: Path) -> None:
package, token = _signed_package(tmp_path)
(package / "install.stdout.txt").write_text("orchestration leak\n", encoding="utf-8")
evidence = tmp_path / "external-evidence"
command_marker = tmp_path / "command-ran.txt"
command = [
sys.executable,
"-c",
f"from pathlib import Path; Path({str(command_marker)!r}).write_text('ran')",
]
with pytest.raises(PackageValidationError, match="allowlist mismatch"):
run_installer(package, evidence, token, command=command)
assert not command_marker.exists()
assert not (evidence / "install.stdout.txt").exists()
assert not (evidence / "install.stderr.txt").exists()
def test_evidence_directory_inside_package_is_rejected(tmp_path: Path) -> None:
package, token = _signed_package(tmp_path)
evidence = package / "runtime-evidence"
with pytest.raises(EvidencePathError, match="outside the package"):
run_installer(package, evidence, token, command=[sys.executable, "-c", "pass"])
def test_pristine_validation_reports_exact_allowlist(tmp_path: Path) -> None:
package, token = _signed_package(tmp_path)
result = validate_pristine_package(package, token)
assert result["hmac"] == "PASS"
assert result["manifest_file_count"] == 2
assert result["package_file_count"] == 4
assert result["unexpected"] == 0
assert result["missing"] == 0

View File

@@ -0,0 +1,319 @@
"""Software-only tests for the authenticated bootstrap package."""
from __future__ import annotations
import hashlib
import json
import os
from pathlib import Path
from pathlib import PurePosixPath
import shutil
import subprocess
import unicodedata
import zipfile
import pytest
import tools.rf001_build_agent_packages as packages
from tools.rf001_agent_update import (
RELEASE_SOURCE_FILES,
ReleaseValidationError,
source_agent_version,
)
def _bootstrap_source(
root: Path,
*,
agent_version: str = "2026.09.29.1",
) -> Path:
fixed = {
"INSTALL_RX_AGENT.cmd": "@echo off\n",
"UNINSTALL_RX_AGENT.cmd": "@echo off\n",
"tools/rf001_bootstrap_readme.txt": "fixed bootstrap readme\n",
"tools/rf001_agent_launcher.py": "# fixed launcher\n",
"tools/install_rf001_rx_autostart.ps1": "# fixed installer\n",
"tools/uninstall_rf001_rx_autostart.ps1": "# fixed uninstaller\n",
}
for name, content in fixed.items():
path = root / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content, encoding="utf-8")
for index, relative in enumerate(RELEASE_SOURCE_FILES.values()):
path = root / relative
path.parent.mkdir(parents=True, exist_ok=True)
content = f"# fixed release source {index}\n"
if relative == RELEASE_SOURCE_FILES["app/tools/rf001_rx_http_agent.py"]:
content += f'AGENT_VERSION = "{agent_version}"\n'
path.write_text(content, encoding="utf-8")
reference = root / ".local/rf001_probe/lab065_reference_staircase.cs8"
reference.parent.mkdir(parents=True, exist_ok=True)
reference.write_bytes(b"fixed exact staircase fixture")
return reference
def _formed_installer_allowlist(release_id: str) -> list[str]:
powershell = shutil.which("powershell.exe")
if powershell is None:
pytest.skip("Windows PowerShell is required to evaluate the installer allowlist")
installer = Path(packages.__file__).with_name("install_rf001_rx_autostart.ps1")
environment = os.environ.copy()
environment["SDR_ROVER_INSTALLER_PATH"] = str(installer)
environment["SDR_ROVER_RELEASE_ID"] = release_id
command = r"""
$ErrorActionPreference = "Stop"
$tokens = $null
$parseErrors = $null
$syntax = [Management.Automation.Language.Parser]::ParseFile(
$env:SDR_ROVER_INSTALLER_PATH,
[ref]$tokens,
[ref]$parseErrors
)
if ($parseErrors.Count -ne 0) {
throw "Installer contains PowerShell parse errors"
}
$assignments = @($syntax.FindAll({
param($node)
$node -is [Management.Automation.Language.AssignmentStatementAst] -and
$node.Left -is [Management.Automation.Language.VariableExpressionAst] -and
$node.Left.VariablePath.UserPath -eq "expectedPaths"
}, $true))
if ($assignments.Count -ne 1) {
throw "Installer expectedPaths assignment is absent or ambiguous"
}
$releasePrefix = "versions/$($env:SDR_ROVER_RELEASE_ID)/"
. ([scriptblock]::Create($assignments[0].Extent.Text))
ConvertTo-Json -Compress -InputObject @($expectedPaths)
"""
completed = subprocess.run(
[powershell, "-NoProfile", "-NonInteractive", "-Command", command],
check=True,
capture_output=True,
encoding="utf-8",
env=environment,
)
value = json.loads(completed.stdout.lstrip("\ufeff"))
assert isinstance(value, list)
assert all(isinstance(path, str) for path in value)
return value
def test_bootstrap_is_authenticated_and_excludes_secret(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
source = tmp_path / "source"
reference = _bootstrap_source(source)
monkeypatch.setattr(
packages,
"REFERENCE_SHA256",
hashlib.sha256(reference.read_bytes()).hexdigest(),
)
token = tmp_path / "token.txt"
token.write_text("fixed-test-token-0123456789abcdef", encoding="utf-8")
package = tmp_path / "bootstrap.zip"
built = packages.build_bootstrap_archive(
source,
package,
bootstrap_id="rf001-bootstrap-2026.09.29.1",
agent_release_id="rf001-agent-2026.09.29.1",
agent_version="2026.09.29.1",
protocol_version=1,
token_path=token,
)
checked = packages.inspect_bootstrap_archive(package, token_path=token)
assert checked == built
assert checked.file_count == len(RELEASE_SOURCE_FILES) + 8
with zipfile.ZipFile(package) as archive:
names = archive.namelist()
manifest = json.loads(archive.read(packages.BOOTSTRAP_MANIFEST_NAME))
ready = json.loads(
archive.read("versions/rf001-agent-2026.09.29.1/READY.json")
)
assert not any("token" in name.casefold() for name in names)
assert not any(
b"fixed-test-token" in archive.read(name)
for name in names
)
actual_version = source_agent_version(
source / RELEASE_SOURCE_FILES["app/tools/rf001_rx_http_agent.py"]
)
assert manifest["agent_version"] == actual_version
assert ready["agent_version"] == actual_version
def test_new_bootstrap_preserves_existing_release_bytes(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
source = tmp_path / "source"
reference = _bootstrap_source(source)
monkeypatch.setattr(
packages,
"REFERENCE_SHA256",
hashlib.sha256(reference.read_bytes()).hexdigest(),
)
token = tmp_path / "token.txt"
token.write_text("fixed-test-token-0123456789abcdef", encoding="utf-8")
base_package = tmp_path / "bootstrap-4.zip"
next_package = tmp_path / "bootstrap-5.zip"
release_id = "rf001-agent-2026.09.29.1"
packages.build_bootstrap_archive(
source,
base_package,
bootstrap_id="rf001-bootstrap-2026.09.29.4",
agent_release_id=release_id,
agent_version="2026.09.29.1",
protocol_version=1,
token_path=token,
)
(source / "tools/rf001_agent_launcher.py").write_text(
"# corrected launcher\n",
encoding="utf-8",
)
packages.build_bootstrap_archive(
source,
next_package,
bootstrap_id="rf001-bootstrap-2026.09.29.5",
agent_release_id=release_id,
agent_version="2026.09.29.1",
protocol_version=1,
token_path=token,
agent_release_bootstrap_id="rf001-bootstrap-2026.09.29.4",
)
release_prefix = f"versions/{release_id}/"
with zipfile.ZipFile(base_package) as base, zipfile.ZipFile(next_package) as new:
release_names = sorted(
name for name in base.namelist() if name.startswith(release_prefix)
)
assert release_names
assert all(base.read(name) == new.read(name) for name in release_names)
assert base.read("launcher/rf001_agent_launcher.py") != new.read(
"launcher/rf001_agent_launcher.py"
)
manifest = json.loads(new.read(packages.BOOTSTRAP_MANIFEST_NAME))
ready = json.loads(new.read(f"{release_prefix}READY.json"))
assert manifest["bootstrap_id"] == "rf001-bootstrap-2026.09.29.5"
assert (
manifest["agent_release_bootstrap_id"]
== "rf001-bootstrap-2026.09.29.4"
)
assert ready["bootstrap_id"] == "rf001-bootstrap-2026.09.29.4"
def test_bootstrap_rejects_the_wrong_existing_secret(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
source = tmp_path / "source"
reference = _bootstrap_source(source)
monkeypatch.setattr(
packages,
"REFERENCE_SHA256",
hashlib.sha256(reference.read_bytes()).hexdigest(),
)
token = tmp_path / "token.txt"
token.write_text("fixed-test-token-0123456789abcdef", encoding="utf-8")
package = tmp_path / "bootstrap.zip"
packages.build_bootstrap_archive(
source,
package,
bootstrap_id="rf001-bootstrap-2026.09.29.1",
agent_release_id="rf001-agent-2026.09.29.1",
agent_version="2026.09.29.1",
protocol_version=1,
token_path=token,
)
wrong = tmp_path / "wrong.txt"
wrong.write_text("another-fixed-token-0123456789abcdef", encoding="utf-8")
with pytest.raises(ValueError, match="signature mismatch"):
packages.inspect_bootstrap_archive(package, token_path=wrong)
def test_installer_allowlist_matches_signed_manifest_and_has_safe_paths(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
source = tmp_path / "source"
reference = _bootstrap_source(source)
monkeypatch.setattr(
packages,
"REFERENCE_SHA256",
hashlib.sha256(reference.read_bytes()).hexdigest(),
)
token = tmp_path / "token.txt"
token.write_text("fixed-test-token-0123456789abcdef", encoding="utf-8")
package = tmp_path / "bootstrap.zip"
release_id = "rf001-agent-2026.09.29.1"
packages.build_bootstrap_archive(
source,
package,
bootstrap_id="rf001-bootstrap-2026.09.29.2",
agent_release_id=release_id,
agent_version="2026.09.29.1",
protocol_version=1,
token_path=token,
)
with zipfile.ZipFile(package) as archive:
manifest = json.loads(archive.read(packages.BOOTSTRAP_MANIFEST_NAME))
manifest_paths = {row["path"] for row in manifest["files"]}
formed_paths = _formed_installer_allowlist(release_id)
assert set(formed_paths) == manifest_paths
assert len(formed_paths) == len(manifest_paths)
assert f"versions/{release_id}/READY.json" in formed_paths
assert (
f"versions/{release_id}/app/tools/hackrf_process_check.py" in formed_paths
)
assert (
f"versions/{release_id}/app/tools/rf001_staircase_search.py" in formed_paths
)
for path in formed_paths:
assert not any(unicodedata.category(character) == "Cc" for character in path)
parsed = PurePosixPath(path)
assert not parsed.is_absolute()
assert all(part not in ("", ".", "..") for part in parsed.parts)
assert "\\" not in path
assert not any(":" in part for part in parsed.parts)
with zipfile.ZipFile(package, "a") as archive:
archive.writestr("unexpected/extra.txt", b"prohibited")
with pytest.raises(ValueError, match="unexpected files"):
packages.inspect_bootstrap_archive(package, token_path=token)
@pytest.mark.parametrize(
("source_version", "requested_version"),
(
("2026.09.29.2", "2026.09.29.1"),
("2026.09.29.1", "2026.09.29.2"),
),
)
def test_bootstrap_rejects_agent_version_mismatch_before_creating_artifact(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
source_version: str,
requested_version: str,
) -> None:
source = tmp_path / "source"
reference = _bootstrap_source(source, agent_version=source_version)
monkeypatch.setattr(
packages,
"REFERENCE_SHA256",
hashlib.sha256(reference.read_bytes()).hexdigest(),
)
token = tmp_path / "token.txt"
token.write_text("fixed-test-token-0123456789abcdef", encoding="utf-8")
package = tmp_path / "must-not-exist.zip"
with pytest.raises(ReleaseValidationError, match="AGENT_VERSION|release_id"):
packages.build_bootstrap_archive(
source,
package,
bootstrap_id="rf001-bootstrap-2026.09.29.3",
agent_release_id=f"rf001-agent-{requested_version}",
agent_version=requested_version,
protocol_version=1,
token_path=token,
)
assert not package.exists()

View File

@@ -0,0 +1,48 @@
"""Software-only process evidence tests for the Python RX runner."""
from __future__ import annotations
import hashlib
import json
from pathlib import Path
import sys
from tools.rf001_capture_runner import run_capture
def test_python_runner_persists_child_exit_and_hash(tmp_path: Path) -> None:
child = tmp_path / "child.py"
capture = tmp_path / "capture.cs8"
capture_bytes = b"software-only-capture-evidence\x00\x01"
child.write_text(
"from pathlib import Path\n"
f"Path({str(capture)!r}).write_bytes({capture_bytes!r})\n",
encoding="utf-8",
)
arguments = tmp_path / "arguments.json"
arguments.write_text(json.dumps(["-B", str(child)]), encoding="utf-8")
stdout = tmp_path / "stdout.txt"
stderr = tmp_path / "stderr.txt"
started = tmp_path / "started.json"
result = tmp_path / "result.json"
exit_code = run_capture(
Path(sys.executable),
arguments,
capture,
stdout,
stderr,
started,
result,
)
start_record = json.loads(started.read_text(encoding="utf-8"))
final_record = json.loads(result.read_text(encoding="utf-8"))
assert exit_code == 0
assert start_record["state"] == "RUNNING"
assert start_record["rf_tx"] == 0
assert final_record["exit_code"] == 0
assert final_record["capture_size"] == len(capture_bytes)
assert final_record["sha256"] == hashlib.sha256(capture_bytes).hexdigest()
assert final_record["runner_error"] is None
assert final_record["rf_tx"] == 0

View File

@@ -0,0 +1,537 @@
"""Software-only tests for the RF-001 HTTP control channel."""
from __future__ import annotations
import threading
import time
import pytest
import tools.rf001_http_control as control_module
from tools.rf001_http_control import (
AuthenticationError,
ControlHTTPServer,
ControlState,
PROTOCOL_VERSION,
ProtocolError,
RequestAuthenticator,
canonical_json,
request_json,
signed_headers,
)
TOKEN = b"software-only-test-token-0123456789abcdef0123456789abcdef"
def test_bootstrap_registration_uses_distinct_fixed_identifier(
tmp_path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
releases = tmp_path / "releases"
releases.mkdir()
package = releases / "rf001-bootstrap-2026.09.29.1.zip"
package.write_bytes(b"fixed bootstrap package")
monkeypatch.setattr(control_module, "DEFAULT_RELEASES_ROOT", releases)
state = ControlState(tmp_path / "state.json")
registered = state.register_bootstrap_release(
str(package),
release_id="rf001-bootstrap-2026.09.29.1",
agent_version="2026.09.29.1",
content_manifest_sha256="a" * 64,
token=TOKEN,
)
assert registered["package_kind"] == "BOOTSTRAP"
assert registered["rf_tx"] == 0
replacement = releases / "replacement.zip"
replacement.write_bytes(b"different bootstrap package")
with pytest.raises(ProtocolError, match="already registered differently"):
state.register_bootstrap_release(
str(replacement),
release_id="rf001-bootstrap-2026.09.29.1",
agent_version="2026.09.29.1",
content_manifest_sha256="b" * 64,
token=TOKEN,
)
with pytest.raises(ProtocolError, match="release_id"):
state.register_bootstrap_release(
str(package),
release_id="rf001-agent-2026.09.29.1",
agent_version="2026.09.29.1",
content_manifest_sha256="a" * 64,
token=TOKEN,
)
def test_request_authentication_rejects_replay_and_tampering() -> None:
authenticator = RequestAuthenticator(TOKEN, window_seconds=60)
body = canonical_json({"agent_id": "rx-user-pc", "rf_tx": 0})
target = "/api/v1/agent/check-in"
headers = signed_headers(
TOKEN,
"POST",
target,
body,
timestamp=1_000,
nonce="a" * 32,
)
authenticator.verify("POST", target, body, headers, now=1_000)
with pytest.raises(AuthenticationError, match="already used"):
authenticator.verify("POST", target, body, headers, now=1_000)
changed_headers = signed_headers(
TOKEN,
"POST",
target,
body,
timestamp=1_000,
nonce="b" * 32,
)
with pytest.raises(AuthenticationError, match="mismatch"):
authenticator.verify(
"POST",
target,
body + b" ",
changed_headers,
now=1_000,
)
def test_state_leases_inventory_and_records_idempotent_result(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
task = state.enqueue_inventory("rx-user-pc", include_hackrf_info=True)
response = state.check_in(
{
"protocol_version": PROTOCOL_VERSION,
"agent_id": "rx-user-pc",
"inventory": {"hostname": "User-PC", "rf_tx": 0},
"rf_tx": 0,
}
)
assert response["task"] == task
assert response["rf_tx"] == 0
result = {
"protocol_version": PROTOCOL_VERSION,
"task_id": task["task_id"],
"agent_id": "rx-user-pc",
"status": "COMPLETE",
"started_at": "2026-09-23T00:00:00+00:00",
"finished_at": "2026-09-23T00:00:01+00:00",
"result": {"hostname": "User-PC", "rf_tx": 0},
"errors": [],
"rf_tx": 0,
}
accepted = state.record_result(result)
assert accepted == {"accepted": True, "duplicate": False, "rf_tx": 0}
duplicate = state.record_result(result)
assert duplicate == {"accepted": True, "duplicate": True, "rf_tx": 0}
conflicting = dict(result)
conflicting["status"] = "FAILED"
with pytest.raises(ProtocolError, match="conflicting"):
state.record_result(conflicting)
def test_state_leases_fixed_offline_verify_task(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
expected_head = "a" * 40
task = state.enqueue_offline_verify(
"rx-user-pc",
expected_head=expected_head,
)
response = state.check_in(
{
"protocol_version": PROTOCOL_VERSION,
"agent_id": "rx-user-pc",
"inventory": {"hostname": "User-PC", "rf_tx": 0},
"rf_tx": 0,
}
)
assert response["task"] == task
assert task["kind"] == "OFFLINE_VERIFY"
assert task["expected_head"] == expected_head
assert task["rf_tx"] == 0
def test_offline_verify_rejects_invalid_expected_head(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
with pytest.raises(ProtocolError, match="expected_head"):
state.enqueue_offline_verify("rx-user-pc", expected_head="main")
def test_rx_capture_requires_exact_local_authorization(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
with pytest.raises(ProtocolError, match="exact RX authorization"):
state.enqueue_rx_capture(
"rx-user-pc",
expected_head="a" * 40,
authorization="yes",
)
task = state.enqueue_rx_capture(
"rx-user-pc",
expected_head="a" * 40,
authorization="AUTHORIZE RF RX",
)
assert task["kind"] == "RX_CAPTURE_START"
assert task["rx_serial"] == "000000000000000097c063dc2e5327d3"
assert task["rx_authorized"] is True
assert task["automatic_retry"] is False
assert task["rf_tx"] == 0
def test_expired_rx_capture_lease_is_not_retried(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
task = state.enqueue_rx_capture(
"rx-user-pc",
expected_head="a" * 40,
authorization="AUTHORIZE RF RX",
)
check_in = {
"protocol_version": PROTOCOL_VERSION,
"agent_id": "rx-user-pc",
"inventory": {"hostname": "User-PC", "rf_tx": 0},
"rf_tx": 0,
}
first = state.check_in(check_in)
assert first["task"] == task
state._data["tasks"][0]["leased_at_epoch"] = int(time.time()) - 31
second = state.check_in(check_in)
assert second["task"] is None
stored = state.snapshot()["tasks"][0]
assert stored["state"] == "LEASE_EXPIRED"
assert "lease_expired_at" in stored
assert stored["task_id"] == task["task_id"]
def test_status_and_decode_tasks_use_fixed_session(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
session_id = "RF001A_20260923T150000Z_1234ABCD"
status = state.enqueue_rx_status("rx-user-pc", session_id=session_id)
decode = state.enqueue_capture_decode(
"rx-user-pc",
session_id=session_id,
tx_started_at="2026-09-23T15:00:05+00:00",
tx_finished_at="2026-09-23T15:00:07+00:00",
)
diagnostics = state.enqueue_capture_diagnostics(
"rx-user-pc",
session_id=session_id,
tx_started_at="2026-09-23T15:00:05+00:00",
tx_finished_at="2026-09-23T15:00:07+00:00",
)
assert status["kind"] == "RX_CAPTURE_STATUS"
assert decode["kind"] == "CAPTURE_DECODE"
assert diagnostics["kind"] == "CAPTURE_DIAGNOSTICS"
assert status["session_id"] == decode["session_id"] == session_id
assert diagnostics["session_id"] == session_id
assert status["rf_tx"] == decode["rf_tx"] == diagnostics["rf_tx"] == 0
with pytest.raises(ProtocolError, match="invalid session_id"):
state.enqueue_rx_status("rx-user-pc", session_id="..\\outside")
def test_staircase_task_has_only_fixed_hashes_and_no_retry(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
session_id = "RF001A_20260925T125829Z_227EADB4"
task = state.enqueue_staircase_search(
"rx-user-pc",
session_id=session_id,
expected_rx_sha256="2" * 64,
expected_reference_sha256="f" * 64,
)
assert task["kind"] == "STAIRCASE_SEARCH"
assert task["session_id"] == session_id
assert task["expected_rx_sha256"] == "2" * 64
assert task["expected_reference_sha256"] == "f" * 64
assert task["hardware_accessed"] is False
assert task["automatic_retry"] is False
assert task["rf_tx"] == 0
assert "capture_path" not in task
assert "reference_path" not in task
assert "command" not in task
with pytest.raises(ProtocolError, match="invalid session_id"):
state.enqueue_staircase_search(
"rx-user-pc",
session_id="..\\outside",
expected_rx_sha256="2" * 64,
expected_reference_sha256="f" * 64,
)
with pytest.raises(ProtocolError, match="expected_rx_sha256"):
state.enqueue_staircase_search(
"rx-user-pc",
session_id=session_id,
expected_rx_sha256="bad",
expected_reference_sha256="f" * 64,
)
with pytest.raises(ProtocolError, match="expected_reference_sha256"):
state.enqueue_staircase_search(
"rx-user-pc",
session_id=session_id,
expected_rx_sha256="2" * 64,
expected_reference_sha256="bad",
)
def test_long_task_heartbeat_renews_expired_lease_without_reissue(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
task = state.enqueue_staircase_search(
"rx-user-pc",
session_id="RF001A_20260925T125829Z_227EADB4",
expected_rx_sha256="2" * 64,
expected_reference_sha256="f" * 64,
)
check_in = {
"protocol_version": PROTOCOL_VERSION,
"agent_id": "rx-user-pc",
"inventory": {"agent_version": "test", "rf_tx": 0},
"rf_tx": 0,
}
assert state.check_in(check_in)["task"] == task
state._data["tasks"][0]["leased_at_epoch"] = int(time.time()) - 300
active = {
**check_in,
"active_task": {
"task_id": task["task_id"],
"kind": "STAIRCASE_SEARCH",
"state": "RUNNING",
"phase": "SEARCHING",
"processed_samples": 400,
"total_samples": 1000,
"hardware_accessed": False,
"rf_tx": 0,
},
}
response = state.check_in(active)
assert response["task"] is None
stored = state.snapshot()["tasks"][0]
assert stored["state"] == "LEASED"
assert stored["progress"]["processed_samples"] == 400
def test_update_approval_is_bound_to_registered_release_and_not_repeated(
tmp_path,
) -> None:
state = ControlState(tmp_path / "state.json")
release_id = "rf001-agent-2026.09.29.2"
state._data["releases"][release_id] = {
"manifest": {
"schema_version": 1,
"release_id": release_id,
"agent_version": "2026.09.29.2",
"protocol_version": PROTOCOL_VERSION,
"package_kind": "AGENT_RELEASE",
"package_sha256": "a" * 64,
"package_bytes": 1234,
"content_manifest_sha256": "b" * 64,
},
"manifest_signature": "c" * 64,
"package_path": str(tmp_path / "release.zip"),
}
task = state.enqueue_agent_update(
"rx-user-pc",
release_id=release_id,
validity_seconds=3600,
)
assert task["kind"] == "UPDATE_AGENT"
assert task["release_id"] == release_id
assert task["package_sha256"] == "a" * 64
assert task["automatic_retry"] is False
assert task["hardware_accessed"] is False
assert task["rf_tx"] == 0
with pytest.raises(ProtocolError, match="already has an update task"):
state.enqueue_agent_update(
"rx-user-pc",
release_id=release_id,
validity_seconds=3600,
)
def test_queued_update_waits_for_active_software_task(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
running = state.enqueue_staircase_search(
"rx-user-pc",
session_id="RF001A_20260925T125829Z_227EADB4",
expected_rx_sha256="2" * 64,
expected_reference_sha256="f" * 64,
)
check_in = {
"protocol_version": PROTOCOL_VERSION,
"agent_id": "rx-user-pc",
"inventory": {"agent_version": "test", "rf_tx": 0},
"rf_tx": 0,
}
assert state.check_in(check_in)["task"] == running
release_id = "rf001-agent-2026.09.29.2"
state._data["releases"][release_id] = {
"manifest": {
"schema_version": 1,
"release_id": release_id,
"agent_version": "2026.09.29.2",
"protocol_version": PROTOCOL_VERSION,
"package_kind": "AGENT_RELEASE",
"package_sha256": "a" * 64,
"package_bytes": 1234,
"content_manifest_sha256": "b" * 64,
},
"manifest_signature": "c" * 64,
"package_path": str(tmp_path / "release.zip"),
}
update = state.enqueue_agent_update(
"rx-user-pc", release_id=release_id, validity_seconds=3600
)
response = state.check_in(
{
**check_in,
"active_task": {
"task_id": running["task_id"],
"kind": "STAIRCASE_SEARCH",
"state": "RUNNING",
"phase": "SEARCHING",
"processed_samples": 1,
"total_samples": 10,
"hardware_accessed": False,
"rf_tx": 0,
},
}
)
assert response["task"] is None
stored = next(
task
for task in state.snapshot()["tasks"]
if task["task_id"] == update["task_id"]
)
assert stored["state"] == "QUEUED"
assert stored["update_status"] == "WAITING_FOR_IDLE"
assert stored["blocked_by_task_id"] == running["task_id"]
def test_http_server_end_to_end_inventory_without_rf(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
server = ControlHTTPServer(
("127.0.0.1", 0),
state=state,
token=TOKEN,
allowed_agent_ip="127.0.0.1",
)
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
base_url = f"http://127.0.0.1:{server.server_address[1]}"
try:
task = request_json(
base_url,
TOKEN,
"POST",
"/api/v1/local/tasks/inventory",
{"agent_id": "rx-user-pc", "include_hackrf_info": True},
)
assert task["kind"] == "INVENTORY"
assert task["rf_tx"] == 0
check_in = request_json(
base_url,
TOKEN,
"POST",
"/api/v1/agent/check-in",
{
"protocol_version": PROTOCOL_VERSION,
"agent_id": "rx-user-pc",
"inventory": {"hostname": "User-PC", "rf_tx": 0},
"rf_tx": 0,
},
)
assert check_in["task"] == task
assert check_in["rf_tx"] == 0
result = {
"protocol_version": PROTOCOL_VERSION,
"task_id": task["task_id"],
"agent_id": "rx-user-pc",
"status": "COMPLETE",
"started_at": "2026-09-23T00:00:00+00:00",
"finished_at": "2026-09-23T00:00:01+00:00",
"result": {"hostname": "User-PC", "rf_tx": 0},
"errors": [],
"rf_tx": 0,
}
acknowledgement = request_json(
base_url,
TOKEN,
"POST",
"/api/v1/agent/result",
result,
)
assert acknowledgement["accepted"] is True
assert acknowledgement["rf_tx"] == 0
status = request_json(
base_url,
TOKEN,
"GET",
"/api/v1/local/status",
)
assert status["results"][task["task_id"]] == result
assert status["tasks"][0]["state"] == "COMPLETE"
finally:
server.shutdown()
server.server_close()
thread.join(timeout=5)
def test_result_cannot_claim_rf_tx(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
task = state.enqueue_inventory("rx-user-pc", include_hackrf_info=False)
result = {
"protocol_version": PROTOCOL_VERSION,
"task_id": task["task_id"],
"agent_id": "rx-user-pc",
"status": "COMPLETE",
"result": {},
"errors": [],
"rf_tx": 1,
}
with pytest.raises(ProtocolError, match="rf_tx = 0"):
state.record_result(result)
def test_cancelled_task_is_not_released_or_completed(tmp_path) -> None:
state = ControlState(tmp_path / "state.json")
task = state.enqueue_rx_capture(
"rx-user-pc",
expected_head="a" * 40,
authorization="AUTHORIZE RF RX",
)
cancellation = state.cancel_task(
task["task_id"],
reason="software packaging failure before hardware access",
)
assert cancellation["state"] == "CANCELLED"
assert cancellation["rf_tx"] == 0
response = state.check_in(
{
"protocol_version": PROTOCOL_VERSION,
"agent_id": "rx-user-pc",
"inventory": {"hostname": "User-PC", "rf_tx": 0},
"rf_tx": 0,
}
)
assert response["task"] is None
result = {
"protocol_version": PROTOCOL_VERSION,
"task_id": task["task_id"],
"agent_id": "rx-user-pc",
"status": "FAILED",
"result": {"hardware_accessed": False, "rf_tx": 0},
"errors": ["packaging failure"],
"rf_tx": 0,
}
with pytest.raises(ProtocolError, match="cancelled"):
state.record_result(result)

View File

@@ -0,0 +1,429 @@
"""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)

View File

@@ -0,0 +1,235 @@
"""Regression tests for strict launcher/health process identity."""
from __future__ import annotations
from dataclasses import replace
from datetime import datetime, timedelta, timezone
import json
from pathlib import Path
from tools.rf001_launcher_health_diagnostic import (
HandshakeExpectation,
ProcessRecord,
_terminate_owned_processes,
atomic_write_json,
evaluate_identity,
strict_owned_process_ids,
)
NOW = datetime(2026, 9, 29, 13, 0, tzinfo=timezone.utc)
SCRIPT = r"C:\diagnostic\rf001_launcher_health_diagnostic.py"
def _expectation(*, popen_pid: int = 200) -> HandshakeExpectation:
return HandshakeExpectation(
release_id="rf001-agent-2026.09.29.1",
agent_version="2026.09.29.1",
launch_nonce="fixed-unique-nonce",
state="RUNNING",
launcher_pid=100,
popen_pid=popen_pid,
launched_at=NOW.isoformat(),
diagnostic_script=SCRIPT,
)
def _record(pid: int, parent: int, *, seconds: float = 1.0) -> ProcessRecord:
return ProcessRecord(
pid=pid,
parent_pid=parent,
name="python.exe",
executable=r"C:\Python313\python.exe",
command_line=f'python "{SCRIPT}" --launch-nonce fixed-unique-nonce',
created_at=(NOW + timedelta(seconds=seconds)).isoformat(),
)
def _health(*, pid: int = 200) -> dict[str, object]:
return {
"release_id": "rf001-agent-2026.09.29.1",
"agent_version": "2026.09.29.1",
"launch_nonce": "fixed-unique-nonce",
"state": "RUNNING",
"pid": pid,
"updated_at": (NOW + timedelta(seconds=2)).isoformat(),
}
def _evaluate(
health: dict[str, object] | None,
records: list[ProcessRecord],
*,
expectation: HandshakeExpectation | None = None,
popen_alive: bool = True,
health_process_alive: bool = True,
) -> dict[str, object]:
return evaluate_identity(
health,
expectation or _expectation(),
records,
popen_alive=popen_alive,
health_process_alive=health_process_alive,
)
def test_exact_process_identity_passes() -> None:
result = _evaluate(_health(), [_record(200, 100)])
assert result["identity_valid"] is True
assert result["identity_model"] == "EXACT_POPEN_PROCESS"
def test_wrong_nonce_fails() -> None:
health = _health()
health["launch_nonce"] = "wrong"
assert _evaluate(health, [_record(200, 100)])["reason"] == "HEALTH_FIELDS_MISMATCH"
def test_wrong_release_fails() -> None:
health = _health()
health["release_id"] = "rf001-agent-elsewhere"
assert _evaluate(health, [_record(200, 100)])["reason"] == "HEALTH_FIELDS_MISMATCH"
def test_wrong_version_fails() -> None:
health = _health()
health["agent_version"] = "2026.09.29.2"
assert _evaluate(health, [_record(200, 100)])["reason"] == "HEALTH_FIELDS_MISMATCH"
def test_health_before_running_state_fails() -> None:
health = _health()
health["state"] = "STARTING"
assert _evaluate(health, [_record(200, 100)])["reason"] == "HEALTH_FIELDS_MISMATCH"
def test_stale_health_fails() -> None:
health = _health()
health["updated_at"] = (NOW - timedelta(seconds=1)).isoformat()
assert _evaluate(health, [_record(200, 100)])["reason"] == "STALE_HEALTH"
def test_rollback_does_not_accept_previous_launch_health() -> None:
previous_health = _health()
previous_health["launch_nonce"] = "previous-launch-nonce"
assert (
_evaluate(previous_health, [_record(200, 100)])["reason"]
== "HEALTH_FIELDS_MISMATCH"
)
def test_unrelated_pid_fails() -> None:
result = _evaluate(
_health(pid=300),
[_record(200, 100), _record(300, 999)],
)
assert result["reason"] == "UNRELATED_PID"
def test_unique_expected_wrapper_child_passes_strict_lineage() -> None:
result = _evaluate(
_health(pid=201),
[_record(200, 100), _record(201, 200)],
)
assert result["identity_valid"] is True
assert (
result["identity_model"]
== "UNIQUE_DIRECT_CHILD_WITH_NONCE_AND_CREATION_TIME"
)
assert result["pid_match"] is False
def test_unexpected_grandchild_fails() -> None:
result = _evaluate(
_health(pid=202),
[_record(200, 100), _record(201, 200), _record(202, 201)],
)
assert result["reason"] == "UNEXPECTED_GRANDCHILD"
def test_pid_reuse_creation_time_mismatch_fails() -> None:
reused = _record(200, 100, seconds=-30)
assert _evaluate(_health(), [reused])["reason"] == "PROCESS_CREATION_TIME_MISMATCH"
def test_target_dies_before_health_fails() -> None:
result = _evaluate(None, [_record(200, 100)], popen_alive=False)
assert result["reason"] == "HEALTH_ABSENT"
def test_target_writes_health_then_dies_immediately_fails() -> None:
result = _evaluate(
_health(),
[_record(200, 100)],
health_process_alive=False,
)
assert result["reason"] == "HEALTH_PROCESS_DIED"
def test_orphan_selection_never_includes_unrelated_process() -> None:
expectation = _expectation()
related = _record(201, 200)
unrelated = replace(_record(300, 999), command_line="python unrelated.py")
assert strict_owned_process_ids(
expectation,
[_record(200, 100), related, unrelated],
) == [201, 200]
def test_orphan_cleanup_terminates_only_strictly_owned_processes(monkeypatch) -> None:
expectation = _expectation()
wrapper = _record(200, 100)
child = _record(201, 200)
unrelated = replace(_record(300, 999), command_line="python unrelated.py")
records = [wrapper, child, unrelated]
terminated: list[int] = []
monkeypatch.setattr(
"tools.rf001_launcher_health_diagnostic.capture_windows_processes",
lambda: records,
)
monkeypatch.setattr(
"tools.rf001_launcher_health_diagnostic.os.kill",
lambda pid, _signal: terminated.append(pid),
)
actions = _terminate_owned_processes(expectation, records)
assert terminated == [201, 200]
assert actions == [
{"pid": 201, "status": "TERMINATED"},
{"pid": 200, "status": "TERMINATED"},
]
def test_repeated_success_is_deterministic_with_distinct_identity() -> None:
first = _expectation(popen_pid=200)
second = replace(
first,
popen_pid=300,
launch_nonce="second-unique-nonce",
launched_at=(NOW + timedelta(seconds=10)).isoformat(),
)
first_result = _evaluate(_health(pid=200), [_record(200, 100)], expectation=first)
second_record = replace(
_record(300, 100, seconds=11),
command_line=f'python "{SCRIPT}" --launch-nonce second-unique-nonce',
)
second_health = {
**_health(pid=300),
"launch_nonce": "second-unique-nonce",
"updated_at": (NOW + timedelta(seconds=12)).isoformat(),
}
second_result = _evaluate(second_health, [second_record], expectation=second)
assert first_result["identity_valid"] is True
assert second_result["identity_valid"] is True
assert first.launch_nonce != second.launch_nonce
assert first.popen_pid != second.popen_pid
def test_diagnostic_json_replacement_is_atomic(tmp_path: Path) -> None:
path = tmp_path / "health.json"
for sequence in range(20):
atomic_write_json(path, {"sequence": sequence})
assert json.loads(path.read_text(encoding="utf-8")) == {"sequence": sequence}
assert not path.with_suffix(".json.tmp").exists()

View File

@@ -0,0 +1,55 @@
"""Software-only checks for the fixed HTTP-agent offline decoder."""
from __future__ import annotations
import json
from pathlib import Path
import pytest
from tools.rf001_offline_decode import decode_offline
def test_decode_offline_forces_legacy_and_refuses_overwrite(tmp_path: Path) -> None:
repository = tmp_path / "repo"
repository.mkdir()
iq_path = tmp_path / "waveform.cs8"
truth_path = tmp_path / "truth.json"
report_path = tmp_path / "report.json"
iq_path.write_bytes(b"iq")
truth_path.write_text("{}", encoding="utf-8")
calls: list[dict[str, object]] = []
def fake_decoder(iq_file: Path, **options: object) -> dict[str, object]:
calls.append({"iq_file": iq_file, **options})
return {"crc_valid_packets": 100, "exact_packets": 100}
result = decode_offline(
repository,
iq_path,
truth_path,
report_path,
decoder=fake_decoder,
)
assert result == {"crc_valid_packets": 100, "exact_packets": 100}
assert calls == [
{
"iq_file": iq_path,
"iq_format": "cs8",
"truth_metadata_path": truth_path,
"decoder_backend": "legacy",
"capture_started_at": None,
"tx_started_at": None,
"tx_finished_at": None,
}
]
assert json.loads(report_path.read_text(encoding="utf-8")) == result
with pytest.raises(FileExistsError, match="already exists"):
decode_offline(
repository,
iq_path,
truth_path,
report_path,
decoder=fake_decoder,
)

View File

@@ -0,0 +1,356 @@
"""Software-only tests for the fixed RF-001A RX capture operations."""
from __future__ import annotations
import hashlib
import json
from pathlib import Path
from typing import Sequence
from tools.rf001_rx_capture import (
CAPTURE_FILE_NAME,
FIXED_RX_SERIAL,
MANIFEST_FILE_NAME,
REPORT_FILE_NAME,
RESULT_FILE_NAME,
read_capture_diagnostics,
read_capture_status,
start_rx_capture,
)
class FakeResult:
def __init__(self, arguments: Sequence[str], stdout: str) -> None:
self.arguments = list(arguments)
self.returncode = 0
self.stdout = stdout
self.stderr = ""
def _write_repository(repository: Path) -> None:
(repository / "configs" / "rf").mkdir(parents=True)
(repository / "tools").mkdir()
profile = {
"test_id": "RF001A_COMMON_CLOCK_001",
"center_frequency_hz": 1_400_000_000,
"sample_rate_hz": 8_000_000,
"symbol_rate_sps": 500_000,
"modulation": "QPSK",
"inner_fec": "2/3",
"application_payload_bytes": 256,
"packet_count": 100,
"inter_packet_gap_ms": 5,
"clock_mode": "COMMON_10_MHZ",
"rx_lna_db": 24,
"rx_vga_db": 24,
"rf_amp_enabled": False,
"antenna_bias_enabled": False,
"hardware_format": "cs8",
"rx_capture_seconds": 20,
"rx_capture_samples": 160_000_000,
}
(repository / "configs" / "rf" / "rf001a_common_clock.json").write_text(
json.dumps(profile),
encoding="utf-8",
)
def test_capture_start_uses_fixed_receive_only_command(tmp_path: Path) -> None:
repository = tmp_path / "repo"
repository.mkdir()
_write_repository(repository)
tool_dir = tmp_path / "hackrf"
tool_dir.mkdir()
info = tool_dir / "hackrf_info.exe"
clock = tool_dir / "hackrf_clock.exe"
transfer = tool_dir / "hackrf_transfer.exe"
for path in (info, clock, transfer):
path.write_bytes(b"")
commands: list[list[str]] = []
def runner(arguments: Sequence[str], timeout: float) -> FakeResult:
del timeout
command = list(arguments)
commands.append(command)
if command == [str(info)]:
return FakeResult(command, f"Serial number: {FIXED_RX_SERIAL}")
if command == [str(clock), "-d", FIXED_RX_SERIAL, "-i"]:
return FakeResult(command, "CLKIN status: clock signal detected")
raise AssertionError(command)
launched: list[list[str]] = []
capture_path: Path | None = None
def launcher(arguments: Sequence[str]) -> int:
nonlocal capture_path
command = list(arguments)
launched.append(command)
capture_path = Path(command[command.index("--capture-path") + 1])
started_path = Path(command[command.index("--started-status") + 1])
started_path.write_text(
json.dumps(
{
"state": "RUNNING",
"pid": 4321,
"started_at": "2026-09-23T15:00:00+00:00",
"capture_path": str(capture_path),
}
),
encoding="utf-8",
)
capture_path.write_bytes(b"12")
return 1234
def grow(_: float) -> None:
assert capture_path is not None
with capture_path.open("ab") as stream:
stream.write(b"34")
result, errors = start_rx_capture(
repository,
tmp_path / "runtime",
"RF001A_20260923T150000Z_1234ABCD",
FIXED_RX_SERIAL,
hackrf_info_path=info,
hackrf_clock_path=clock,
hackrf_transfer_path=transfer,
command_runner=runner,
process_gate=lambda: (True, {"state": "CLEAR"}),
background_launcher=launcher,
process_stopper=lambda pid: None,
sleep=grow,
)
assert errors == []
assert result["state"] == "READY"
assert result["rf_rx"] == 1
assert result["rf_tx"] == 0
assert result["automatic_retry"] is False
assert result["common_clock_verified"] is True
assert len(launched) == 1
arguments_path = Path(
launched[0][launched[0].index("--arguments-json") + 1]
)
transfer_arguments = json.loads(arguments_path.read_text(encoding="utf-8"))
assert transfer_arguments == [
"-d", FIXED_RX_SERIAL,
"-r", str(result["capture_path"]),
"-f", "1400000000",
"-s", "8000000",
"-n", "2400000000",
"-l", "24",
"-g", "24",
"-a", "0",
"-p", "0",
"-B",
]
assert "-t" not in transfer_arguments
assert commands == [
[str(info)],
[str(clock), "-d", FIXED_RX_SERIAL, "-i"],
]
def test_capture_start_rejects_explicit_no_clock_status(tmp_path: Path) -> None:
repository = tmp_path / "repo"
repository.mkdir()
_write_repository(repository)
tool_dir = tmp_path / "hackrf"
tool_dir.mkdir()
info = tool_dir / "hackrf_info.exe"
clock = tool_dir / "hackrf_clock.exe"
transfer = tool_dir / "hackrf_transfer.exe"
for path in (info, clock, transfer):
path.write_bytes(b"")
def runner(arguments: Sequence[str], timeout: float) -> FakeResult:
del timeout
command = list(arguments)
if command == [str(info)]:
return FakeResult(command, f"Serial number: {FIXED_RX_SERIAL}")
if command == [str(clock), "-d", FIXED_RX_SERIAL, "-i"]:
return FakeResult(command, "CLKIN status: no clock signal detected")
raise AssertionError(command)
launched: list[list[str]] = []
result, errors = start_rx_capture(
repository,
tmp_path / "runtime",
"RF001A_20260925T120000Z_1234ABCD",
FIXED_RX_SERIAL,
hackrf_info_path=info,
hackrf_clock_path=clock,
hackrf_transfer_path=transfer,
command_runner=runner,
process_gate=lambda: (True, {"state": "CLEAR"}),
background_launcher=lambda arguments: launched.append(list(arguments)) or 1234,
process_stopper=lambda pid: None,
)
assert result["hardware_accessed"] is True
assert result["rf_rx"] == 0
assert result["rf_tx"] == 0
assert result["common_clock_verified"] is False
assert errors == ["RuntimeError: CLKIN clock signal was not detected"]
assert launched == []
def test_capture_status_requires_exact_complete_file(tmp_path: Path) -> None:
session_id = "RF001A_20260923T150000Z_1234ABCD"
session = tmp_path / "rx_capture" / session_id
session.mkdir(parents=True)
capture = session / CAPTURE_FILE_NAME
capture.write_bytes(b"1234")
result_path = session / RESULT_FILE_NAME
result_path.write_text(
json.dumps(
{
"exit_code": 0,
"runner_error": None,
"capture_size": 4,
"sha256": "fixture",
}
),
encoding="utf-8",
)
(session / MANIFEST_FILE_NAME).write_text(
json.dumps(
{
"session_id": session_id,
"capture_path": str(capture),
"capture_started_at": "2026-09-23T15:00:00+00:00",
"expected_capture_end": "2026-09-23T15:00:20+00:00",
"expected_capture_bytes": 4,
"result_status_path": str(result_path),
"common_clock_verified": True,
"rf_tx": 0,
}
),
encoding="utf-8",
)
result, errors = read_capture_status(tmp_path, session_id)
assert errors == []
assert result["state"] == "CAPTURE_COMPLETE"
assert result["capture_bytes"] == 4
assert result["hardware_accessed"] is False
assert result["rf_tx"] == 0
def test_capture_diagnostics_returns_report_and_signal_power(tmp_path: Path) -> None:
session_id = "RF001A_20260925T104504Z_5FA2C83B"
session = tmp_path / "rx_capture" / session_id
session.mkdir(parents=True)
capture = session / CAPTURE_FILE_NAME
samples = bytearray()
for index in range(200):
code = 10 if 80 <= index < 120 else 1
samples.extend((code, code))
capture.write_bytes(samples)
capture_sha256 = hashlib.sha256(samples).hexdigest()
result_path = session / RESULT_FILE_NAME
result_path.write_text(
json.dumps(
{
"exit_code": 0,
"runner_error": None,
"capture_size": len(samples),
"sha256": capture_sha256,
}
),
encoding="utf-8",
)
(session / MANIFEST_FILE_NAME).write_text(
json.dumps(
{
"session_id": session_id,
"capture_path": str(capture),
"capture_started_at": "2026-09-25T10:00:00+00:00",
"expected_capture_end": "2026-09-25T10:00:01+00:00",
"expected_capture_bytes": len(samples),
"result_status_path": str(result_path),
"common_clock_verified": True,
"rf_tx": 0,
}
),
encoding="utf-8",
)
report = {
"rf_tx": 0,
"iq_sha256": capture_sha256,
"detected_preambles": 0,
"rejected_candidates": 0,
"crc_valid_packets": 0,
"exact_packets": 0,
"rx_clipping_rail_codes": 0,
"analysis_windows": [{"start_sample": 64, "stop_sample": 136}],
}
(session / REPORT_FILE_NAME).write_text(
json.dumps(report),
encoding="utf-8",
)
diagnostics, errors = read_capture_diagnostics(
tmp_path,
session_id,
"2026-09-25T10:00:00.000010+00:00",
"2026-09-25T10:00:00.000015+00:00",
)
assert errors == []
assert diagnostics["hardware_accessed"] is False
assert diagnostics["rf_tx"] == 0
assert diagnostics["report"] == report
signal = diagnostics["signal_metrics"]
assert signal["tx_window"]["start_sample"] == 80
assert signal["tx_window"]["stop_sample"] == 120
assert signal["tx_to_baseline_power_ratio"] == 100.0
assert signal["tx_to_baseline_db"] == 20.0
def test_missing_process_gate_dependency_reports_failure_without_hardware(
tmp_path: Path,
) -> None:
repository = tmp_path / "repo"
repository.mkdir()
_write_repository(repository)
tool_dir = tmp_path / "hackrf"
tool_dir.mkdir()
info = tool_dir / "hackrf_info.exe"
clock = tool_dir / "hackrf_clock.exe"
transfer = tool_dir / "hackrf_transfer.exe"
for path in (info, clock, transfer):
path.write_bytes(b"")
commands: list[list[str]] = []
def runner(arguments: Sequence[str], timeout: float) -> FakeResult:
del timeout
commands.append(list(arguments))
return FakeResult(arguments, "unexpected")
def missing_gate() -> tuple[bool, dict[str, object]]:
raise ModuleNotFoundError("tools.hackrf_process_check")
result, errors = start_rx_capture(
repository,
tmp_path / "runtime",
"RF001A_20260924T090807Z_B8E6794D",
FIXED_RX_SERIAL,
hackrf_info_path=info,
hackrf_clock_path=clock,
hackrf_transfer_path=transfer,
command_runner=runner,
process_gate=missing_gate,
process_stopper=lambda pid: None,
)
assert result["hardware_accessed"] is False
assert result["rf_rx"] == 0
assert result["rf_tx"] == 0
assert errors == [
"ModuleNotFoundError: tools.hackrf_process_check"
]
assert commands == []

View File

@@ -0,0 +1,824 @@
"""Software-only tests for the fixed-command RX HTTP agent."""
from __future__ import annotations
import argparse
from datetime import datetime, timedelta, timezone
import hashlib
import json
from pathlib import Path
import shutil
from typing import Sequence
import pytest
import tools.rf001_agent_update as update_module
import tools.rf001_rx_http_agent as agent_module
from tools.rf001_http_control import PROTOCOL_VERSION, ProtocolError
from tools.rf001_rx_http_agent import (
CommandResult,
collect_inventory,
execute_task,
normalized_agent_id,
read_git_metadata,
)
def fake_runner(arguments: Sequence[str], timeout: float) -> CommandResult:
del timeout
command = list(arguments)
if command == ["hostname"]:
stdout = "User-PC"
elif command == ["whoami"]:
stdout = "user-pc\\professional"
elif command[0] == "git":
stdout = "fake-git-read-only-result"
elif command[0].lower().endswith("hackrf_info.exe"):
stdout = "hackrf_info version: 2024.02.1"
else: # pragma: no cover - protects the test allowlist
raise AssertionError(f"unexpected command: {command}")
return CommandResult(command, 0, stdout, "")
def test_agent_id_is_normalized_without_shell_content() -> None:
assert normalized_agent_id("User-PC") == "user-pc"
assert normalized_agent_id(" RX Laptop! ") == "rx-laptop"
def test_inventory_runs_only_fixed_read_only_commands(tmp_path: Path) -> None:
repository = tmp_path / "repo"
repository.mkdir()
hackrf_info = tmp_path / "hackrf_info.exe"
hackrf_info.write_bytes(b"")
inventory, errors = collect_inventory(
repository,
include_hackrf_info=True,
hackrf_info_path=hackrf_info,
command_runner=fake_runner,
)
assert errors == []
assert inventory["rf_tx"] == 0
assert inventory["hostname_command"]["stdout"] == "User-PC"
assert inventory["whoami_command"]["stdout"] == "user-pc\\professional"
assert inventory["hackrf_info"]["executed"] is True
assert inventory["hackrf_info"]["rf_tx"] == 0
def test_agent_rejects_unknown_task_and_rf_tx(tmp_path: Path) -> None:
base_task: dict[str, object] = {
"protocol_version": PROTOCOL_VERSION,
"task_id": "INVENTORY_TEST_001",
"kind": "INVENTORY",
"agent_id": "rx-user-pc",
"created_at": "2026-09-23T00:00:00+00:00",
"include_hackrf_info": False,
"rf_tx": 0,
}
unknown = dict(base_task)
unknown["kind"] = "SHELL"
with pytest.raises(ProtocolError, match="unsupported task kind"):
execute_task(
unknown,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
command_runner=fake_runner,
)
transmit = dict(base_task)
transmit["rf_tx"] = 1
with pytest.raises(ProtocolError, match="rf_tx = 0"):
execute_task(
transmit,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
command_runner=fake_runner,
)
def test_agent_dispatches_fixed_capture_diagnostics_without_hardware(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
calls: list[tuple[Path, str, str, str]] = []
def diagnostics(
work_root: Path,
session_id: str,
tx_started_at: str,
tx_finished_at: str,
) -> tuple[dict[str, object], list[str]]:
calls.append((work_root, session_id, tx_started_at, tx_finished_at))
return {
"session_id": session_id,
"hardware_accessed": False,
"rf_tx": 0,
"report": {"detected_preambles": 0},
}, []
monkeypatch.setattr(agent_module, "read_capture_diagnostics", diagnostics)
session_id = "RF001A_20260925T104504Z_5FA2C83B"
task = {
"protocol_version": PROTOCOL_VERSION,
"task_id": "DIAG_TEST_001",
"kind": "CAPTURE_DIAGNOSTICS",
"agent_id": "rx-user-pc",
"created_at": "2026-09-25T10:51:00+00:00",
"session_id": session_id,
"tx_started_at": "2026-09-25T10:46:54+00:00",
"tx_finished_at": "2026-09-25T10:46:56+00:00",
"rf_tx": 0,
}
result = execute_task(
task,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=tmp_path / "runtime",
command_runner=fake_runner,
)
assert result["status"] == "COMPLETE"
assert result["result"]["hardware_accessed"] is False
assert result["rf_tx"] == 0
assert calls == [
(
tmp_path / "runtime",
session_id,
"2026-09-25T10:46:54+00:00",
"2026-09-25T10:46:56+00:00",
)
]
def _write_git_metadata(repository: Path, head: str) -> None:
git_dir = repository / ".git"
ref = git_dir / "refs" / "heads" / "video-development"
ref.parent.mkdir(parents=True)
(git_dir / "HEAD").write_text(
"ref: refs/heads/video-development\n",
encoding="ascii",
)
ref.write_text(head + "\n", encoding="ascii")
def test_read_git_metadata_without_git_executable(tmp_path: Path) -> None:
repository = tmp_path / "repo"
repository.mkdir()
head = "a94f2db4ee8377201a97263166cb09431df5f5d6"
_write_git_metadata(repository, head)
metadata = read_git_metadata(repository)
assert metadata["branch"] == "video-development"
assert metadata["head"] == head
assert metadata["status"] == "NOT_RUN_NO_GIT_EXECUTABLE"
def test_read_git_metadata_from_linked_worktree(tmp_path: Path) -> None:
repository = tmp_path / "worktree"
repository.mkdir()
common = tmp_path / "main.git"
worktree_git = common / "worktrees" / "worktree"
worktree_git.mkdir(parents=True)
(repository / ".git").write_text(
f"gitdir: {worktree_git}\n",
encoding="utf-8",
)
(worktree_git / "commondir").write_text("../..\n", encoding="ascii")
(worktree_git / "HEAD").write_text(
"ref: refs/heads/video-development\n",
encoding="ascii",
)
head = "a94f2db4ee8377201a97263166cb09431df5f5d6"
ref = common / "refs" / "heads" / "video-development"
ref.parent.mkdir(parents=True)
ref.write_text(head + "\n", encoding="ascii")
metadata = read_git_metadata(repository)
assert metadata["git_dir"] == str(worktree_git.resolve())
assert metadata["common_dir"] == str(common.resolve())
assert metadata["branch"] == "video-development"
assert metadata["head"] == head
def test_offline_verify_is_fixed_software_only_task(tmp_path: Path) -> None:
repository = tmp_path / "repo"
repository.mkdir()
head = "a94f2db4ee8377201a97263166cb09431df5f5d6"
_write_git_metadata(repository, head)
(repository / "tools").mkdir()
(repository / "configs" / "rf").mkdir(parents=True)
for relative in (
Path("tools/rf001a_prepare.py"),
Path("tools/qpsk_rf_rx.py"),
Path("configs/rf/rf001a_truth_metadata.json"),
):
(repository / relative).write_text("fixture\n", encoding="utf-8")
commands: list[list[str]] = []
def offline_runner(arguments: Sequence[str], timeout: float) -> CommandResult:
del timeout
command = list(arguments)
commands.append(command)
if "rf001a_prepare.py" in command[4]:
output = Path(command[command.index("--output-dir") + 1])
output.mkdir()
(output / "tx_waveform.cs8").write_bytes(b"fixture")
(output / "tx_metadata.json").write_text("{}", encoding="utf-8")
elif "rf001_offline_decode.py" in command[4]:
report = Path(command[command.index("--report") + 1])
report.write_text(
'{"crc_valid_packets": 100, "exact_packets": 100}',
encoding="utf-8",
)
else: # pragma: no cover - protects the fixed command contract
raise AssertionError(command)
return CommandResult(command, 0, "PASS", "")
task = {
"protocol_version": PROTOCOL_VERSION,
"task_id": "OFFLINE_TEST_001",
"kind": "OFFLINE_VERIFY",
"agent_id": "rx-user-pc",
"created_at": "2026-09-23T00:00:00+00:00",
"expected_head": head,
"rf_tx": 0,
}
result = execute_task(
task,
agent_id="rx-user-pc",
repository=repository,
hackrf_info_path=None,
work_root=tmp_path / "runtime",
command_runner=offline_runner,
)
assert result["status"] == "COMPLETE"
assert result["result"]["hardware_accessed"] is False
assert result["result"]["crc_valid_packets"] == 100
assert result["result"]["exact_packets"] == 100
assert "--repository" in commands[1]
assert all("hackrf" not in Path(command[0]).name.lower() for command in commands)
assert all("-t" not in command for command in commands)
assert result["rf_tx"] == 0
def _sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def _staircase_fixture(
tmp_path: Path,
) -> tuple[Path, dict[str, object], Path, Path]:
work_root = tmp_path / "runtime"
session_id = "RF001A_20260925T125829Z_227EADB4"
session_directory = work_root / "rx_capture" / session_id
session_directory.mkdir(parents=True)
capture = session_directory / "rf001a_ota_capture.cs8"
capture.write_bytes(b"fixed-rx-capture")
reference = work_root / "references" / "lab065_reference_staircase.cs8"
reference.parent.mkdir(parents=True)
reference.write_bytes(b"fixed-staircase-reference")
task: dict[str, object] = {
"protocol_version": PROTOCOL_VERSION,
"task_id": "STAIRCASE_TEST_001",
"kind": "STAIRCASE_SEARCH",
"agent_id": "rx-user-pc",
"created_at": "2026-09-28T12:00:00+00:00",
"session_id": session_id,
"expected_rx_sha256": _sha256(capture),
"expected_reference_sha256": _sha256(reference),
"hardware_accessed": False,
"automatic_retry": False,
"rf_tx": 0,
}
return work_root, task, capture, reference
def _write_staircase_report(arguments: Sequence[str]) -> Path:
command = list(arguments)
report_path = Path(command[command.index("--report") + 1])
report = {
"analyzer_version": "test",
"mode": "OFFLINE_REFERENCE_STAIRCASE_SEARCH",
"capture_sha256": command[command.index("--capture-sha256") + 1],
"reference_sha256": _sha256(
Path(command[command.index("--reference") + 1])
),
"search": {
"coverage_start_sample": 0,
"coverage_stop_sample": 8,
"coverage_seconds": 0.000001,
"coverage_complete": True,
"source_samples_processed": 8,
"frequency_grid_hz": [-3.0, 0.0, 3.0],
"background_score_p99": 0.01,
"candidates": [],
},
"verifications": [],
"verdict": "NOT_DETECTED",
"verdict_reasons": ["NO_CANDIDATES"],
"analysis_seconds": 1.25,
"peak_process_memory_bytes": 1234,
"peak_additional_memory_bytes": 456,
"hardware_accessed": False,
"rf_tx": 0,
}
report_path.write_text(json.dumps(report), encoding="utf-8")
return report_path
def test_staircase_task_rejects_invalid_session_and_hashes(tmp_path: Path) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
invalid_session = dict(task, session_id="..\\outside")
with pytest.raises(ProtocolError, match="session_id"):
execute_task(
invalid_session,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
)
for field in ("expected_rx_sha256", "expected_reference_sha256"):
invalid_hash = dict(task)
invalid_hash[field] = "invalid"
with pytest.raises(ProtocolError, match=field):
execute_task(
invalid_hash,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
)
def test_staircase_hash_mismatch_does_not_start_child(tmp_path: Path) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
calls: list[list[str]] = []
def forbidden_runner(arguments: Sequence[str], timeout: float) -> CommandResult:
del timeout
calls.append(list(arguments))
raise AssertionError("child process must not run after a hash mismatch")
for field in ("expected_rx_sha256", "expected_reference_sha256"):
changed = dict(task)
changed[field] = "0" * 64
result = execute_task(
changed,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
command_runner=forbidden_runner,
)
assert result["status"] == "FAILED"
assert result["result"]["reference_detection"] == "EXECUTION_FAILED"
assert calls == []
def test_staircase_repeat_reuses_existing_report_without_child(
tmp_path: Path,
) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
calls: list[list[str]] = []
def analyzer_runner(arguments: Sequence[str], timeout: float) -> CommandResult:
assert timeout == 43_200.0
calls.append(list(arguments))
_write_staircase_report(arguments)
assert "hackrf" not in " ".join(arguments).lower()
return CommandResult(list(arguments), 0, "REFERENCE STAIRCASE = NOT_DETECTED", "")
first = execute_task(
task,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
command_runner=analyzer_runner,
)
second = execute_task(
task,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
command_runner=lambda *_args: (_ for _ in ()).throw(
AssertionError("existing report must not start another child")
),
)
assert first["status"] == "COMPLETE"
assert first["result"]["hardware_accessed"] is False
assert first["result"]["rf_tx"] == 0
assert first["result"]["reused_existing_report"] is False
assert second["status"] == "COMPLETE"
assert second["result"]["reused_existing_report"] is True
assert len(calls) == 1
def test_staircase_child_failure_is_execution_failed(tmp_path: Path) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
def failed_runner(arguments: Sequence[str], timeout: float) -> CommandResult:
del timeout
return CommandResult(list(arguments), 9, "", "fixed failure")
result = execute_task(
task,
agent_id="rx-user-pc",
repository=tmp_path,
hackrf_info_path=None,
work_root=work_root,
command_runner=failed_runner,
)
assert result["status"] == "FAILED"
assert result["result"]["reference_detection"] == "EXECUTION_FAILED"
assert result["result"]["hardware_accessed"] is False
assert result["result"]["rf_tx"] == 0
assert "exited with 9" in result["errors"][0]
def _update_fixture(
tmp_path: Path,
) -> tuple[
Path,
bytes,
dict[str, object],
dict[str, object],
argparse.Namespace,
]:
source = tmp_path / "source"
for index, relative in enumerate(update_module.RELEASE_SOURCE_FILES.values()):
path = source / relative
path.parent.mkdir(parents=True, exist_ok=True)
content = f"# fixed update fixture {index}\n"
if relative == update_module.RELEASE_SOURCE_FILES[
"app/tools/rf001_rx_http_agent.py"
]:
content += 'AGENT_VERSION = "2026.09.29.2"\n'
path.write_text(content, encoding="utf-8")
release_id = "rf001-agent-2026.09.29.2"
package = tmp_path / f"{release_id}.zip"
inspection = update_module.build_release_archive(
source,
package,
release_id=release_id,
agent_version="2026.09.29.2",
protocol_version=PROTOCOL_VERSION,
)
manifest: dict[str, object] = {
**inspection.descriptor(),
"package_kind": "AGENT_RELEASE",
}
token = b"fixed-test-token-0123456789abcdef"
task: dict[str, object] = {
"protocol_version": PROTOCOL_VERSION,
"task_id": "UPDATE_TEST_001",
"kind": "UPDATE_AGENT",
"agent_id": "rx-user-pc",
"created_at": datetime.now(timezone.utc).isoformat(),
"release_id": release_id,
"agent_version": "2026.09.29.2",
"package_sha256": inspection.package_sha256,
"package_bytes": inspection.package_bytes,
"content_manifest_sha256": inspection.content_manifest_sha256,
"compatible_protocol_version": PROTOCOL_VERSION,
"approval_expires_at": (
datetime.now(timezone.utc) + timedelta(hours=1)
).isoformat(),
"automatic_retry": False,
"hardware_accessed": False,
"rf_tx": 0,
}
install_root = tmp_path / "install"
install_root.mkdir()
launcher_status = install_root / "launcher_status.json"
launcher_status.write_text(
json.dumps(
{
"active_release_id": "rf001-agent-2026.09.29.1",
"active_agent_version": "2026.09.29.1",
"rf_tx": 0,
}
),
encoding="utf-8",
)
arguments = argparse.Namespace(
agent_id="rx-user-pc",
server="http://127.0.0.1:8765",
timeout=1.0,
install_root=install_root,
launcher_request=install_root / "launcher_request.json",
launcher_status=launcher_status,
release_id="rf001-agent-2026.09.29.1",
)
return package, token, task, manifest, arguments
def _successful_self_test(
arguments: Sequence[str], timeout: float
) -> CommandResult:
assert timeout == 120.0
assert "hackrf" not in " ".join(arguments).lower()
return CommandResult(list(arguments), 0, "SELF TEST = PASS", "")
def test_agent_stages_authenticated_update_and_reuses_it(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
package, token, task, manifest, arguments = _update_fixture(tmp_path)
downloads: list[Path] = []
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {
"manifest": manifest,
"manifest_signature": update_module.sign_update_manifest(token, manifest),
},
)
def download(
_server: str,
_token: bytes,
_target: str,
destination: Path,
**_kwargs: object,
) -> None:
downloads.append(destination)
shutil.copyfile(package, destination)
monkeypatch.setattr(agent_module, "request_file", download)
result, errors, request = agent_module.stage_agent_update(
task,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert errors == []
assert result["update_status"] == "STAGED"
assert result["hardware_accessed"] is False
assert result["rf_tx"] == 0
assert request is not None
assert len(downloads) == 1
result, errors, repeated_request = agent_module.stage_agent_update(
task,
arguments=arguments,
token=token,
command_runner=lambda *_args: (_ for _ in ()).throw(
AssertionError("an already staged release must not run again")
),
)
assert errors == []
assert result["update_status"] == "ALREADY_STAGED"
assert repeated_request is not None
assert {
key: value
for key, value in repeated_request.items()
if key != "requested_at"
} == {key: value for key, value in request.items() if key != "requested_at"}
assert len(downloads) == 1
def test_agent_rejects_bad_update_signature_sha_and_protocol(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
_package, token, task, manifest, arguments = _update_fixture(tmp_path)
network_downloads: list[str] = []
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {
"manifest": manifest,
"manifest_signature": "0" * 64,
},
)
monkeypatch.setattr(
agent_module,
"request_file",
lambda *_args, **_kwargs: network_downloads.append("called"),
)
result, errors, request = agent_module.stage_agent_update(
task,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert result["update_status"] == "EXECUTION_FAILED"
assert any("signature mismatch" in error for error in errors)
assert request is None
assert network_downloads == []
incompatible = dict(task, compatible_protocol_version=PROTOCOL_VERSION + 1)
_result, errors, _request = agent_module.stage_agent_update(
incompatible,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert any("incompatible" in error for error in errors)
changed_sha = dict(task, package_sha256="0" * 64)
signed = update_module.sign_update_manifest(token, manifest)
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {
"manifest": manifest,
"manifest_signature": signed,
},
)
_result, errors, _request = agent_module.stage_agent_update(
changed_sha,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert any("field mismatch: package_sha256" in error for error in errors)
assert network_downloads == []
def test_agent_retries_one_interrupted_download_then_stages(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
package, token, task, manifest, arguments = _update_fixture(tmp_path)
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {
"manifest": manifest,
"manifest_signature": update_module.sign_update_manifest(token, manifest),
},
)
calls = 0
def interrupted_then_complete(
_server: str,
_token: bytes,
_target: str,
destination: Path,
**_kwargs: object,
) -> None:
nonlocal calls
calls += 1
if calls == 1:
destination.write_bytes(b"partial")
raise OSError("fixed interrupted transfer")
shutil.copyfile(package, destination)
monkeypatch.setattr(agent_module, "request_file", interrupted_then_complete)
result, errors, request = agent_module.stage_agent_update(
task,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert errors == []
assert result["update_status"] == "STAGED"
assert request is not None
assert calls == 2
state = json.loads(
(
arguments.install_root
/ "staging"
/ str(task["task_id"])
/ "download_state.json"
).read_text(encoding="utf-8")
)
assert state["network_attempts"] == 2
def test_agent_does_not_exceed_persisted_download_attempt_limit(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
_package, token, task, manifest, arguments = _update_fixture(tmp_path)
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {
"manifest": manifest,
"manifest_signature": update_module.sign_update_manifest(token, manifest),
},
)
calls = 0
def always_interrupted(*_args: object, **_kwargs: object) -> None:
nonlocal calls
calls += 1
raise OSError("fixed interrupted transfer")
monkeypatch.setattr(agent_module, "request_file", always_interrupted)
for _ in range(2):
result, errors, request = agent_module.stage_agent_update(
task,
arguments=arguments,
token=token,
command_runner=_successful_self_test,
)
assert result["update_status"] == "EXECUTION_FAILED"
assert errors
assert request is None
assert calls == 2
def test_agent_restart_does_not_duplicate_background_analyzer(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
starts: list[list[str]] = []
class FakeProcess:
pid = 4242
def fake_popen(arguments: Sequence[str], **_kwargs: object) -> FakeProcess:
starts.append(list(arguments))
return FakeProcess()
monkeypatch.setattr(agent_module.subprocess, "Popen", fake_popen)
pointer = agent_module.start_staircase_background_job(
task,
agent_id="rx-user-pc",
work_root=work_root,
)
assert pointer["pid"] == 4242
with pytest.raises(RuntimeError, match="already active"):
agent_module.start_staircase_background_job(
task,
agent_id="rx-user-pc",
work_root=work_root,
)
assert len(starts) == 1
assert pointer["hardware_accessed"] is False
assert pointer["rf_tx"] == 0
def test_completed_background_result_survives_network_loss(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
work_root, task, _capture, _reference = _staircase_fixture(tmp_path)
directory = work_root / "agent_jobs" / str(task["task_id"])
directory.mkdir(parents=True)
pointer = {
"schema_version": 1,
"task": task,
"pid": 999999,
"started_at": datetime.now(timezone.utc).isoformat(),
"automatic_retry": False,
"hardware_accessed": False,
"rf_tx": 0,
}
agent_module.atomic_write_json(
work_root / "agent_jobs" / "active_job.json", pointer
)
result = {
"protocol_version": PROTOCOL_VERSION,
"task_id": task["task_id"],
"agent_id": "rx-user-pc",
"status": "COMPLETE",
"result": {"hardware_accessed": False, "rf_tx": 0},
"errors": [],
"rf_tx": 0,
}
agent_module.atomic_write_json(directory / "result.json", result)
arguments = argparse.Namespace(
work_root=work_root,
server="http://127.0.0.1:8765",
timeout=1.0,
)
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
OSError("fixed network loss")
),
)
with pytest.raises(OSError, match="network loss"):
agent_module.deliver_background_result(arguments, b"token", pointer)
assert (work_root / "agent_jobs" / "active_job.json").is_file()
assert (directory / "result.json").is_file()
monkeypatch.setattr(
agent_module,
"request_json",
lambda *_args, **_kwargs: {"accepted": True, "rf_tx": 0},
)
assert agent_module.deliver_background_result(arguments, b"token", pointer)
assert not (work_root / "agent_jobs" / "active_job.json").exists()
assert (directory / "delivered_job.json").is_file()
assert (directory / "result.json").is_file()

View File

@@ -0,0 +1,354 @@
from __future__ import annotations
import hashlib
import math
from pathlib import Path
import numpy as np
import pytest
from scipy import signal
from tools.rf001_staircase_search import (
DEFAULT_CRITERIA,
DEFAULT_LAYOUT,
EXPECTED_REFERENCE_SHA256,
ReferenceLayout,
SearchCriteria,
analyze,
design_antialias_filter,
locate_reference_streaming,
load_reference,
read_filtered_decimated_window,
verify_candidate,
)
LAYOUT = ReferenceLayout(
sample_rate_hz=8_000,
symbol_rate=200,
carrier_hz=500.0,
leading_samples=800,
segment_samples=800,
gap_samples=400,
trailing_samples=800,
)
CRITERIA = SearchCriteria(
decimation=1,
input_block_samples=50_000,
cfo_min_hz=-3.0,
cfo_max_hz=3.0,
cfo_step_hz=0.5,
histogram_stride=8,
)
PROJECT_ROOT = Path(__file__).resolve().parents[1]
EXACT_REFERENCE_PATH = (
PROJECT_ROOT / ".local" / "rf001_probe" / "lab065_reference_staircase.cs8"
)
def _reference() -> np.ndarray:
random_generator = np.random.default_rng(20260925)
symbols = random_generator.choice((-1.0, 1.0), LAYOUT.segment_samples // 40)
base = np.repeat(symbols, 40).astype(np.complex64)
time_axis = np.arange(LAYOUT.segment_samples) / LAYOUT.sample_rate_hz
base *= np.exp(2j * np.pi * LAYOUT.carrier_hz * time_axis)
base *= 60.0 / np.sqrt(np.mean(np.abs(base) ** 2))
values = np.zeros(LAYOUT.total_samples, dtype=np.complex64)
for level, (start, stop) in zip(LAYOUT.levels_db, LAYOUT.active_windows()):
values[start:stop] = base * (10 ** (level / 20))
return values
def _write_cs8(path: Path, values: np.ndarray) -> str:
interleaved = np.empty(2 * values.size, dtype=np.int8)
interleaved[0::2] = np.clip(np.rint(values.real), -128, 127).astype(np.int8)
interleaved[1::2] = np.clip(np.rint(values.imag), -128, 127).astype(np.int8)
path.write_bytes(interleaved.tobytes())
return hashlib.sha256(interleaved.tobytes()).hexdigest()
def _capture(reference: np.ndarray, *, gain: float, cfo_hz: float, start: int) -> np.ndarray:
random_generator = np.random.default_rng(417)
values = (
random_generator.normal(0.0, 1.5, 1_000_000)
+ 1j * random_generator.normal(0.0, 1.5, 1_000_000)
).astype(np.complex64)
time_axis = np.arange(reference.size) / LAYOUT.sample_rate_hz
values[start:start + reference.size] += (
gain
* reference
* np.exp(1j * (0.73 + 2 * np.pi * cfo_hz * time_axis))
)
return values
@pytest.mark.parametrize(
("gain", "cfo_hz", "start"),
((0.25, -2.5, 49_777), (0.75, 0.0, 420_201), (1.5, 2.5, 749_999)),
)
def test_unknown_position_gain_cfo_and_block_boundary(
tmp_path: Path,
gain: float,
cfo_hz: float,
start: int,
) -> None:
reference_path = tmp_path / "reference.cs8"
capture_path = tmp_path / "capture.cs8"
reference_hash = _write_cs8(reference_path, _reference())
_write_cs8(capture_path, _capture(_reference(), gain=gain, cfo_hz=cfo_hz, start=start))
reference, _ = load_reference(
reference_path,
LAYOUT,
CRITERIA,
expected_sha256=reference_hash,
)
search = locate_reference_streaming(capture_path, reference, LAYOUT, CRITERIA)
candidate = search["candidates"][0]
verification = verify_candidate(capture_path, reference, candidate, LAYOUT, CRITERIA)
assert abs(int(candidate["start_sample"]) - start) <= 1
assert abs(float(candidate["cfo_hz"]) - cfo_hz) <= CRITERIA.cfo_step_hz
assert float(candidate["score"]) >= CRITERIA.normalized_correlation_minimum
assert verification["qualified"] is True
def test_negative_control_without_staircase_is_not_detected(tmp_path: Path) -> None:
reference_path = tmp_path / "reference.cs8"
capture_path = tmp_path / "noise.cs8"
report_path = tmp_path / "report.json"
reference_hash = _write_cs8(reference_path, _reference())
random_generator = np.random.default_rng(818)
noise = (
random_generator.normal(0.0, 3.0, 1_000_000)
+ 1j * random_generator.normal(0.0, 3.0, 1_000_000)
).astype(np.complex64)
capture_hash = _write_cs8(capture_path, noise)
result = analyze(
reference_path,
capture_path,
report_path,
expected_capture_sha256=capture_hash,
layout=LAYOUT,
criteria=CRITERIA,
expected_reference_sha256=reference_hash,
)
assert result["verdict"] == "NOT_DETECTED"
assert report_path.is_file()
assert result["hardware_accessed"] is False
assert result["rf_tx"] == 0
def test_report_is_not_overwritten(tmp_path: Path) -> None:
reference_path = tmp_path / "reference.cs8"
capture_path = tmp_path / "capture.cs8"
report_path = tmp_path / "report.json"
reference_hash = _write_cs8(reference_path, _reference())
capture_hash = _write_cs8(
capture_path,
_capture(_reference(), gain=1.0, cfo_hz=0.0, start=4_000),
)
result = analyze(
reference_path,
capture_path,
report_path,
expected_capture_sha256=capture_hash,
layout=LAYOUT,
criteria=CRITERIA,
expected_reference_sha256=reference_hash,
)
assert result["verdict"] == "DETECTED"
with pytest.raises(FileExistsError):
analyze(
reference_path,
capture_path,
report_path,
expected_capture_sha256=capture_hash,
layout=LAYOUT,
criteria=CRITERIA,
expected_reference_sha256=reference_hash,
)
def _require_exact_reference() -> Path:
if not EXACT_REFERENCE_PATH.is_file():
pytest.skip("exact Lab065 reference is not available in this checkout")
assert EXACT_REFERENCE_PATH.stat().st_size == 12_000_000
assert hashlib.sha256(EXACT_REFERENCE_PATH.read_bytes()).hexdigest() == (
EXPECTED_REFERENCE_SHA256
)
return EXACT_REFERENCE_PATH
def _read_exact_reference_values(path: Path) -> np.ndarray:
raw = np.memmap(path, dtype=np.int8, mode="r")
return (
np.asarray(raw[0::2], dtype=np.float32)
+ 1j * np.asarray(raw[1::2], dtype=np.float32)
).astype(np.complex64)
def _write_noise_cs8(path: Path, samples: int, seed: int) -> None:
random_generator = np.random.default_rng(seed)
raw = np.memmap(path, dtype=np.int8, mode="w+", shape=(2 * samples,))
block = 500_000
for start in range(0, samples, block):
stop = min(samples, start + block)
count = stop - start
raw[2 * start:2 * stop:2] = np.clip(
np.rint(random_generator.normal(0.0, 0.75, count)),
-128,
127,
).astype(np.int8)
raw[2 * start + 1:2 * stop + 1:2] = np.clip(
np.rint(random_generator.normal(0.0, 0.75, count)),
-128,
127,
).astype(np.int8)
raw.flush()
del raw
def _inject_exact_reference(
capture_path: Path,
reference: np.ndarray,
*,
start: int,
gain: float,
phase: float,
cfo_hz: float,
) -> None:
raw = np.memmap(capture_path, dtype=np.int8, mode="r+")
existing = (
np.asarray(raw[2 * start:2 * (start + reference.size):2], dtype=np.float32)
+ 1j
* np.asarray(
raw[2 * start + 1:2 * (start + reference.size) + 1:2],
dtype=np.float32,
)
)
time_axis = np.arange(reference.size, dtype=np.float64) / DEFAULT_LAYOUT.sample_rate_hz
injected = existing + gain * reference * np.exp(
1j * (phase + 2 * np.pi * cfo_hz * time_axis)
)
raw[2 * start:2 * (start + reference.size):2] = np.clip(
np.rint(injected.real), -128, 127
).astype(np.int8)
raw[2 * start + 1:2 * (start + reference.size) + 1:2] = np.clip(
np.rint(injected.imag), -128, 127
).astype(np.int8)
raw.flush()
del raw
def test_antialias_filter_and_block_overlap_are_fixed() -> None:
reference_path = _require_exact_reference()
taps = design_antialias_filter(DEFAULT_LAYOUT, DEFAULT_CRITERIA)
assert taps.size == 895
assert (taps.size - 1) // 2 == 447
frequencies, response = signal.freqz(
taps,
worN=262_144,
fs=DEFAULT_LAYOUT.sample_rate_hz,
)
assert np.max(np.abs(response[frequencies >= 120_000])) <= 10 ** (-79 / 20)
total = math.ceil(DEFAULT_LAYOUT.total_samples / DEFAULT_CRITERIA.decimation)
split = 73_219
whole = read_filtered_decimated_window(
reference_path,
0,
total,
DEFAULT_LAYOUT,
DEFAULT_CRITERIA,
taps,
)
blocked = np.concatenate(
(
read_filtered_decimated_window(
reference_path,
0,
split,
DEFAULT_LAYOUT,
DEFAULT_CRITERIA,
taps,
),
read_filtered_decimated_window(
reference_path,
split,
total,
DEFAULT_LAYOUT,
DEFAULT_CRITERIA,
taps,
),
)
)
np.testing.assert_allclose(blocked, whole, rtol=0, atol=2e-5)
def test_exact_reference_unknown_positions_gain_phase_noise_and_cfo(
tmp_path: Path,
) -> None:
reference_path = _require_exact_reference()
reference_values = _read_exact_reference_values(reference_path)
cases = (
(123_457, 0.45, 0.73, -2.5),
(7_999_987, 0.70, -1.17, 0.0),
(15_999_983, 1.00, 2.21, 2.5),
)
capture_path = tmp_path / "exact_reference_cases.cs8"
_write_noise_cs8(capture_path, 22_500_000, seed=2026092801)
for start, gain, phase, cfo_hz in cases:
_inject_exact_reference(
capture_path,
reference_values,
start=start,
gain=gain,
phase=phase,
cfo_hz=cfo_hz,
)
reference, _ = load_reference(
reference_path,
DEFAULT_LAYOUT,
DEFAULT_CRITERIA,
expected_sha256=EXPECTED_REFERENCE_SHA256,
)
search = locate_reference_streaming(
capture_path,
reference,
DEFAULT_LAYOUT,
DEFAULT_CRITERIA,
)
assert search["coverage_complete"] is True
assert search["source_samples_processed"] == 22_500_000
candidates = list(search["candidates"])
for expected_start, _gain, _phase, expected_cfo in cases:
candidate = min(
candidates,
key=lambda row: abs(int(row["start_sample"]) - expected_start),
)
assert abs(int(candidate["start_sample"]) - expected_start) <= 32
assert abs(float(candidate["cfo_hz"]) - expected_cfo) <= 0.25
assert float(candidate["score"]) >= DEFAULT_CRITERIA.normalized_correlation_minimum
verification = verify_candidate(
capture_path,
reference,
candidate,
DEFAULT_LAYOUT,
DEFAULT_CRITERIA,
)
assert verification["qualified"] is True
def test_exact_reference_negative_control(tmp_path: Path) -> None:
reference_path = _require_exact_reference()
capture_path = tmp_path / "exact_reference_negative.cs8"
report_path = tmp_path / "negative_report.json"
_write_noise_cs8(capture_path, 8_000_000, seed=2026092802)
capture_hash = hashlib.sha256(capture_path.read_bytes()).hexdigest()
result = analyze(
reference_path,
capture_path,
report_path,
expected_capture_sha256=capture_hash,
)
assert result["verdict"] == "NOT_DETECTED"
assert result["search"]["coverage_complete"] is True