#!/usr/bin/env python3 """Disposable packaged-tool checks. Never enumerate or open physical serial. Usage: python qualify_frozen_rnode.py /absolute/path/to/archy-rnodeconf These checks qualify packaging, not device access or successful radio flashing. """ import json import os from pathlib import Path import subprocess import sys import tempfile from types import SimpleNamespace from unittest.mock import patch import archy_rnodeconf as wrapper def qualify(binary): binary = str(Path(binary).resolve(strict=True)) with tempfile.TemporaryDirectory(prefix="rnode-frozen-") as temporary: home = Path(temporary) environment = {"HOME": temporary, "TMPDIR": temporary, "PATH": "/nonexistent", "LANG": "C.UTF-8"} def run(*args): return subprocess.run([binary, *args], env=environment, cwd=temporary, capture_output=True, timeout=30) result = run("--archy-capabilities") assert result.returncode == 0, result.stderr assert json.loads(result.stdout) == {"contract": 1} result = run("--archy-esptool", "version") assert result.returncode == 0 and b"5.6.0" in result.stdout, result # Exercise the real substitution call chain into the actual frozen # child, with a downloaded script that must never execute. marker = home / "downloaded-code-ran" downloaded = home / "esptool.py" downloaded.write_text(f"open({str(marker)!r}, 'w').write('unsafe')\n") exits = [] def upstream_main(): exits.append(subprocess.call([binary, str(downloaded), "version"], env=environment, cwd=temporary, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, timeout=30)) with patch.object(sys, "executable", binary), patch.object(sys, "frozen", True, create=True): assert wrapper.invoke(SimpleNamespace(main=upstream_main), []) == 0 assert exits == [0] and not marker.exists() # Paths outside the USB-tty contract refuse before opening the object. for target in ("/dev/null", str(downloaded), "--help"): assert run("--archy-install", target).returncode != 0 print("PASS frozen stub, embedded flasher, actual child substitution, invalid targets; no host Python/PATH") if __name__ == "__main__": if len(sys.argv) != 2: raise SystemExit("Expected the frozen archy-rnodeconf artifact path") qualify(sys.argv[1])