swayfx-mosaic/tooling/probes/step20c-scenefx-static-contract/verify-freeze.py

33 lines
1.4 KiB
Python

#!/usr/bin/env python3
"""Verify immutable historical manifests after publication wording changes.
WHY: documentation snapshots preserve evidence without rewriting sealed hashes.
CONTRACT: explicit mappings replace only files recorded in the source manifest.
INVARIANT: verification is read-only; every original digest must still match.
"""
import argparse
import hashlib
import json
from pathlib import Path
p = argparse.ArgumentParser(description=__doc__)
p.add_argument('lab', type=Path)
p.add_argument('--snapshot-map', type=Path, required=True)
a = p.parse_args()
mapping = json.loads(a.snapshot_map.read_text())
seen = set()
for kind, count, expected in [
('source', 1892, '5ad64eaf0aec2290689c46b7754eb4563980396ba2a06e852d1c8e903086f138'),
('evidence', 143, '85d034f4075436bbdda302afdfa94955365aa51adcfb7e8b04ed6bb28377f649')]:
manifest = a.lab/'results'/(kind+'-sha256.txt')
assert hashlib.sha256(manifest.read_bytes()).hexdigest() == expected
lines = manifest.read_text().splitlines()
assert len(lines) == count
for line in lines:
digest, name = line.split(' ', 1)
if kind == 'source' and name in mapping:
seen.add(name)
name = mapping[name]
assert hashlib.sha256(Path(name).read_bytes()).hexdigest() == digest, name
print(kind, count, expected, 'PASS')
assert seen == set(mapping), 'mapping must contain only sealed source entries'