coulomb-social/scripts/verify-packaged-source.py
tegwick fa64e4f868
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
Correct live image source pin and reconcile service attribution evidence
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
2026-10-30 23:06:13 +01:00

67 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Compare retained OCI application bytes with exact Git commits, without startup.
No pull, mounts, network, application entrypoint, database or external writes.
Inventory follows the runtime COPY instructions in this repo's Dockerfile.
This proves packaged source equality, not dependency/build reproducibility.
"""
import argparse
import hashlib
import json
import re
import subprocess
PROBE = """import hashlib,json,pathlib
r=pathlib.Path('/app')
f={str(p.relative_to(r)):hashlib.sha256(p.read_bytes()).hexdigest()
for p in (r/'coulomb_social').rglob('*')
if p.is_file() and '__pycache__' not in p.parts and p.suffix != '.pyc'}
for n in ['manage.py','pyproject.toml','docker-entrypoint.sh']:
f[n]=hashlib.sha256((r/n).read_bytes()).hexdigest()
print(json.dumps(f,sort_keys=True))
"""
def canonical(value):
return json.dumps(value, sort_keys=True, separators=(",", ":")).encode()
def verify(image, sources):
if not re.fullmatch(r"forgejo\.coulomb\.social/coulomb/"
r"coulomb-social@sha256:[a-f0-9]{64}", image):
raise ValueError("Exact retained application image digest required")
if not sources or any(not re.fullmatch(r"[a-f0-9]{40}", source) for source in sources):
raise ValueError("Full source commit hashes required")
actual = json.loads(subprocess.check_output([
"docker", "run", "--rm", "--pull=never", "--network", "none", "--read-only",
"--cap-drop", "ALL", "--security-opt", "no-new-privileges", "--entrypoint", "python",
image, "-c", PROBE], timeout=60))
comparisons = []
for source in sources:
paths = subprocess.check_output([
"git", "ls-tree", "-r", "--name-only", source, "coulomb_social", "manage.py",
"pyproject.toml", "scripts/docker-entrypoint.sh"], text=True).splitlines()
expected = {}
for name in paths:
packaged = (name.removeprefix("scripts/")
if name == "scripts/docker-entrypoint.sh" else name)
expected[packaged] = hashlib.sha256(subprocess.check_output(
["git", "show", source + ":" + name])).hexdigest()
differences = sum(expected.get(n) != actual.get(n) for n in set(expected) | set(actual))
comparisons.append({"commit": source, "packaged_file_count": len(actual),
"source_file_count": len(expected), "different_files": differences,
"all_packaged_source_bytes_match": differences == 0})
return {"schema": "coulomb.packaged-source-provenance.v1", "image": image,
"network": "none", "read_only_root": True, "entrypoint_bypassed": True,
"database_contact": False, "production_changes": False, "comparisons": comparisons,
"actual_packaged_manifest_sha256": hashlib.sha256(canonical(actual)).hexdigest(),
"dependency_or_build_reproducibility_proved": False}
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--image", required=True)
parser.add_argument("--source", action="append", required=True)
arguments = parser.parse_args()
print(json.dumps(verify(arguments.image, arguments.source), indent=2))