Files
Tajna-tretej-stolicy/osint-mirror-trace/solve/check_release.py
2026-04-22 10:58:32 +03:00

105 lines
4.1 KiB
Python

from __future__ import annotations
import csv
import json
import subprocess
import sys
import zipfile
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
CONFIG = json.loads((ROOT / "src" / "task_config.json").read_text(encoding="utf-8"))
def require(path: Path) -> None:
if not path.exists():
raise SystemExit(f"missing required file: {path}")
def assert_contains(path: Path, needle: str, error: str) -> None:
if needle not in path.read_text(encoding="utf-8"):
raise SystemExit(error)
def main() -> int:
archive_path = ROOT / "public" / CONFIG["archive_name"]
bundle_dir = ROOT / "public" / "mirrortrace_casebundle"
retained_copy = bundle_dir / "20_artifacts" / CONFIG["retained_copy_name"]
require(ROOT / "public" / "case_brief.txt")
require(ROOT / "public" / "negotiation_excerpt.txt")
require(archive_path)
require(bundle_dir / "10_datasets" / "graph_nodes.csv")
require(bundle_dir / "10_datasets" / "graph_edges.csv")
require(bundle_dir / "20_artifacts" / "doc_01.pdf")
require(bundle_dir / "20_artifacts" / "doc_03.pdf")
require(bundle_dir / "20_artifacts" / "capture_05.html")
require(bundle_dir / "20_artifacts" / "capture_11.html")
require(retained_copy)
assert_contains(
ROOT / "public" / "case_brief.txt",
CONFIG["retained_copy_name"],
"case_brief.txt is missing retained copy reference",
)
doc_01_bytes = (bundle_dir / "20_artifacts" / "doc_01.pdf").read_bytes()
if f"/Author ({CONFIG['correct']['pdf_author']})".encode("ascii") not in doc_01_bytes:
raise SystemExit("doc_01.pdf is missing expected metadata author")
if b"Retained legal copy marker: ED-C0" not in doc_01_bytes:
raise SystemExit("doc_01.pdf is missing expected retained copy marker")
doc_03_bytes = (bundle_dir / "20_artifacts" / "doc_03.pdf").read_bytes()
if f"/Author ({CONFIG['same_cluster_decoy']['pdf_author']})".encode("ascii") not in doc_03_bytes:
raise SystemExit("doc_03.pdf is missing expected same-cluster decoy author")
capture_05 = (bundle_dir / "20_artifacts" / "capture_05.html").read_text(encoding="utf-8")
if CONFIG["correct"]["full_name"] not in capture_05:
raise SystemExit("capture_05.html is missing expected identity")
capture_11 = (bundle_dir / "20_artifacts" / "capture_11.html").read_text(encoding="utf-8")
if CONFIG["same_cluster_decoy"]["personal_domain"] not in capture_11:
raise SystemExit("capture_11.html is missing expected same-cluster decoy pivot")
with (bundle_dir / "10_datasets" / "graph_edges.csv").open(encoding="utf-8", newline="") as fh:
rows = list(csv.DictReader(fh))
expected_edges = {
("panel", "cert_ms441"),
("helpdesk_mercury", "doc_03"),
("git_mercury", "personal_vk"),
("helpdesk_mercury", "personal_as"),
}
actual_edges = {(row["source"], row["target"]) for row in rows}
if not expected_edges.issubset(actual_edges):
raise SystemExit("graph_edges.csv is missing expected hard-mode relations")
subprocess.run(
["unzip", "-P", CONFIG["passphrase"], "-t", str(retained_copy)],
check=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
with zipfile.ZipFile(archive_path) as zf:
expected = {
"mirrortrace_casebundle/00_brief/case_brief.txt",
"mirrortrace_casebundle/10_datasets/graph_nodes.csv",
"mirrortrace_casebundle/10_datasets/graph_edges.csv",
"mirrortrace_casebundle/20_artifacts/doc_01.pdf",
"mirrortrace_casebundle/20_artifacts/doc_03.pdf",
"mirrortrace_casebundle/20_artifacts/capture_05.html",
"mirrortrace_casebundle/20_artifacts/capture_11.html",
f"mirrortrace_casebundle/20_artifacts/{CONFIG['retained_copy_name']}",
}
names = set(zf.namelist())
if not expected.issubset(names):
raise SystemExit("participant archive is missing expected hard-mode files")
print("MirrorTrace offline release check passed.")
return 0
if __name__ == "__main__":
sys.exit(main())