"""Archive lint (US07-01): the frozen CLI archive is complete, honest, and inert. Freezing the donors is only worth something if three things stay true: the archive still holds exactly the bytes it claims, it holds no secret, and production cannot reach it. Each of those is a one-line mistake away — a helpful `sys.path` insert, a copied `.env`, an edited "just this once" source — so each is asserted here. """ from __future__ import annotations import hashlib import re import subprocess import sys from pathlib import Path import pytest import yaml REPO = Path(__file__).resolve().parents[2] ARCHIVE = REPO / "legacy_cli_archive" SOURCES = ARCHIVE / "src" LEDGER = ARCHIVE / "donor_ledger.yaml" CHECKSUMS = ARCHIVE / "CHECKSUMS.sha256" # Everything the concept requires an archive to carry (§3 "Donor-first CLI # migration and archival"): the sources, their docs, a dependency lock, schema # notes, a redacted sample configuration, the ledger, and recorded checksums. REQUIRED_ARTIFACTS = ( "README.md", "donor_ledger.yaml", "CHECKSUMS.sha256", "requirements-lock.txt", "photo_analyzer.env.sample", ) ARCHIVED_MODULES = ("photo_analyzer", "nsfwtag", "webapp", "nsfw_tag", "compare_models") # Only the two suites that compare against the donors may put the archive on the # import path; every other tree must not name it at all. IMPORT_ALLOWED = { REPO / "tests" / "characterization" / "conftest.py", REPO / "tests" / "characterization" / "test_donor_ledger.py", # lints the ledger there REPO / "tests" / "integration" / "test_safety_parity.py", Path(__file__), } SECRET_PATTERNS = ( re.compile(r"sk-(?!REPLACE_WITH_YOUR_KEY)[A-Za-z0-9_\-]{16,}"), re.compile(r"AIza[0-9A-Za-z_\-]{20,}"), # Google API keys re.compile(r"(?i)api[_-]?key\s*[=:]\s*['\"][A-Za-z0-9_\-]{16,}['\"]"), ) def _archived_files() -> list[Path]: return sorted(p for p in SOURCES.rglob("*") if p.is_file() and "__pycache__" not in p.parts) # ── completeness ───────────────────────────────────────────────────────────── def test_the_archive_carries_every_required_artifact(): for artifact in REQUIRED_ARTIFACTS: path = ARCHIVE / artifact assert path.is_file(), f"archive is missing {artifact}" assert path.stat().st_size > 0, f"archive artifact {artifact} is empty" assert (SOURCES / "photo_analyzer.py").is_file() assert (SOURCES / "nsfwtag" / "README.md").is_file(), "donor docs must be archived too" assert (SOURCES / "webapp" / "README.md").is_file() def test_every_ledger_source_is_present_in_the_archive(): rows = yaml.safe_load(LEDGER.read_text(encoding="utf-8"))["rows"] for row in rows: source = SOURCES / row["source"]["file"] assert source.is_file(), f"{row['id']}: {row['source']['file']} is not archived" def test_the_readme_records_provenance_and_the_no_import_rule(): readme = (ARCHIVE / "README.md").read_text(encoding="utf-8") for expected in ("CHECKSUMS.sha256", "requirements-lock.txt", "donor_ledger.yaml"): assert expected in readme, f"README does not point at {expected}" assert "Schema notes" in readme, "the donor's schema must be documented" assert "nsfw_scores.csv" in readme, "the CSV's fate must be documented" # ── integrity ──────────────────────────────────────────────────────────────── def test_every_archived_source_matches_its_checksum(): """A frozen archive that silently drifts is not evidence of anything.""" recorded = {} for line in CHECKSUMS.read_text(encoding="utf-8").splitlines(): digest, _, rel = line.partition(" ") if rel: recorded[rel.strip()] = digest actual = { str(path.relative_to(ARCHIVE)): hashlib.sha256(path.read_bytes()).hexdigest() for path in _archived_files() } assert actual == recorded, "archived sources and CHECKSUMS.sha256 disagree" # ── redaction ──────────────────────────────────────────────────────────────── def test_the_archive_contains_no_credential(): for path in [*_archived_files(), *(ARCHIVE / a for a in REQUIRED_ARTIFACTS)]: if path.suffix in (".png", ".jpg", ".webp"): continue text = path.read_text(encoding="utf-8", errors="replace") for pattern in SECRET_PATTERNS: assert not pattern.search(text), f"possible secret in {path.relative_to(REPO)}" def test_the_sample_configuration_is_a_placeholder_only(): sample = (ARCHIVE / "photo_analyzer.env.sample").read_text(encoding="utf-8") assert "REDACTED" in sample # Placeholders are not key-shaped, so neither a scanner nor a reader can # mistake the sample for a credential. assert "LLM_API_KEY=<" in sample # No real env file, database, log, or CSV may ride along in the archive. strays = [ p.name for p in ARCHIVE.rglob("*") if p.is_file() and p.suffix in (".env", ".db", ".sqlite", ".sqlite3", ".log", ".csv") ] assert strays == [], f"unexpected runtime files archived: {strays}" # ── inertness ──────────────────────────────────────────────────────────────── def test_production_code_never_imports_an_archived_module(): for path in (REPO / "photo_pipeline").rglob("*.py"): text = path.read_text(encoding="utf-8") for module in ARCHIVED_MODULES: assert not re.search(rf"^\s*(import|from)\s+{module}\b", text, re.MULTILINE), \ f"{path.relative_to(REPO)} imports the archived {module}" assert "legacy_cli_archive" not in text, \ f"{path.relative_to(REPO)} names the archive" def test_only_the_parity_suites_put_the_archive_on_the_import_path(): for path in (REPO / "tests").rglob("*.py"): if path in IMPORT_ALLOWED or "__pycache__" in path.parts: continue assert "legacy_cli_archive" not in path.read_text(encoding="utf-8"), \ f"{path.relative_to(REPO)} reaches into the archive" def test_the_archived_modules_are_unimportable_from_a_clean_interpreter(): """The real check: a fresh process with the repo on its path cannot load them.""" script = ( "import importlib.util, sys; " f"sys.path.insert(0, {str(REPO)!r}); " "print([m for m in " f"{list(ARCHIVED_MODULES)!r}" " if importlib.util.find_spec(m) is not None])" ) result = subprocess.run( [sys.executable, "-c", script], capture_output=True, text=True, cwd=str(REPO), check=True ) assert result.stdout.strip() == "[]", f"still importable: {result.stdout.strip()}" def test_the_application_starts_without_the_archive(tmp_path): """Nothing in the runtime path may need the frozen sources to exist.""" pytest.importorskip("fastapi") from photo_pipeline.api.app import create_app from photo_pipeline.config import Config config = Config.from_env( {"PHOTO_PIPELINE_DATA_DIR": str(tmp_path / "data"), "PHOTO_PIPELINE_LIBRARY_ROOTS": ""} ) assert create_app(config) is not None