← Files Canonical Memory VerifierARCHIVED FILE
tools/build_candidate_zip.py
7.94 KB · Sep 30, 2026 · 23:13 UTC
#!/usr/bin/env python3
"""Build a deterministic local-review ZIP from PUBLIC_MANIFEST.json."""
from __future__ import annotations
import argparse
import hashlib
import json
import os
import re
import stat
import unicodedata
import zipfile
from pathlib import Path, PurePosixPath
ROOT = Path(__file__).resolve().parents[1]
PUBLIC_MANIFEST = ROOT / "PUBLIC_MANIFEST.json"
IGNORED_DIRECTORY_NAMES = {".git"}
MANIFEST_FIELDS = {"format_version", "self_excluded", "release_status", "files"}
FILE_FIELDS = {"path", "bytes", "sha256", "origin"}
ALLOWED_ORIGINS = {"new_clean_room", "synthetic_generator", "synthetic_test_data"}
ALLOWED_RELEASE_STATUSES = {"candidate_licensed_not_published"}
SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
class DuplicateKeyError(ValueError):
pass
def object_pairs_no_duplicates(pairs: list[tuple[str, object]]) -> dict[str, object]:
result: dict[str, object] = {}
for key, value in pairs:
if key in result:
raise DuplicateKeyError(f"duplicate object key: {key}")
result[key] = value
return result
def fail(message: str) -> int:
print(
json.dumps(
{"status": "FAIL", "error": message},
sort_keys=True,
separators=(",", ":"),
)
)
return 1
def is_reparse(path: Path) -> bool:
info = path.lstat()
flag = getattr(stat, "FILE_ATTRIBUTE_REPARSE_POINT", 0)
return path.is_symlink() or bool(getattr(info, "st_file_attributes", 0) & flag)
def safe_relative(value: str) -> bool:
pure = PurePosixPath(value)
return (
isinstance(value, str)
and value != ""
and not pure.is_absolute()
and len(pure.parts) > 0
and all(part not in {"", ".", ".."} for part in pure.parts)
and "\\" not in value
and ":" not in value
)
def load_and_validate_manifest(data: bytes) -> dict:
try:
manifest = json.loads(
data.decode("utf-8", errors="strict"),
object_pairs_hook=object_pairs_no_duplicates,
)
except (UnicodeDecodeError, json.JSONDecodeError, DuplicateKeyError) as exc:
raise ValueError("public manifest is not strict JSON") from exc
if not isinstance(manifest, dict) or set(manifest) != MANIFEST_FIELDS:
raise ValueError("public manifest fields are invalid")
if manifest.get("format_version") != "1.0":
raise ValueError("unsupported public manifest format")
if manifest.get("self_excluded") != "PUBLIC_MANIFEST.json":
raise ValueError("public manifest self exclusion is invalid")
if manifest.get("release_status") not in ALLOWED_RELEASE_STATUSES:
raise ValueError("public manifest release status is invalid")
declared = manifest.get("files")
if not isinstance(declared, list) or not declared or len(declared) > 10000:
raise ValueError("public manifest file inventory is invalid")
seen: set[str] = set()
seen_normalized: set[str] = set()
for item in declared:
if not isinstance(item, dict) or set(item) != FILE_FIELDS:
raise ValueError("public manifest file record is invalid")
relative = item.get("path")
if not isinstance(relative, str) or not safe_relative(relative):
raise ValueError("unsafe public manifest member")
if relative == "PUBLIC_MANIFEST.json" or relative in seen:
raise ValueError("duplicate public manifest member")
normalized = unicodedata.normalize("NFC", relative).casefold()
if normalized in seen_normalized:
raise ValueError("normalized public manifest member collision")
size = item.get("bytes")
if not isinstance(size, int) or isinstance(size, bool) or size < 0:
raise ValueError("public manifest byte count is invalid")
digest = item.get("sha256")
if not isinstance(digest, str) or not SHA256_RE.fullmatch(digest):
raise ValueError("public manifest SHA-256 is invalid")
if item.get("origin") not in ALLOWED_ORIGINS:
raise ValueError("public manifest origin is invalid")
seen.add(relative)
seen_normalized.add(normalized)
return manifest
def path_chain_is_regular(path: Path) -> bool:
current = ROOT
if is_reparse(current):
return False
for part in path.relative_to(ROOT).parts:
current = current / part
if is_reparse(current):
return False
return True
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--output", required=True)
args = parser.parse_args()
output = Path(args.output).resolve()
try:
output.relative_to(ROOT)
except ValueError:
pass
else:
return fail("output must be outside the plugin root")
if is_reparse(PUBLIC_MANIFEST) or not PUBLIC_MANIFEST.is_file():
return fail("public manifest is missing or nonregular")
manifest_bytes = PUBLIC_MANIFEST.read_bytes()
try:
manifest = load_and_validate_manifest(manifest_bytes)
except ValueError as exc:
return fail(str(exc))
declared = manifest["files"]
members = ["PUBLIC_MANIFEST.json"] + [item["path"] for item in declared]
actual_members: set[str] = set()
for path in sorted(ROOT.rglob("*")):
relative_parts = path.relative_to(ROOT).parts
if any(part in IGNORED_DIRECTORY_NAMES for part in relative_parts):
continue
if is_reparse(path):
return fail("reparse point or symbolic link in plugin tree")
if path.is_dir():
continue
if not path.is_file():
return fail("nonregular entry in plugin tree")
path.resolve(strict=True).relative_to(ROOT.resolve(strict=True))
actual_members.add(path.relative_to(ROOT).as_posix())
if actual_members != set(members):
return fail("plugin tree differs from public manifest inventory")
for item in declared:
path = ROOT / Path(item["path"])
if not path.is_file() or not path_chain_is_regular(path):
return fail("declared member is missing or nonregular")
data = path.read_bytes()
if len(data) != item["bytes"] or hashlib.sha256(data).hexdigest() != item["sha256"]:
return fail("public manifest byte binding mismatch")
output.parent.mkdir(parents=True, exist_ok=True)
temporary = output.with_name(output.name + ".tmp")
if temporary.exists():
temporary.unlink()
try:
with zipfile.ZipFile(
temporary,
mode="w",
compression=zipfile.ZIP_DEFLATED,
compresslevel=9,
) as archive:
for relative in sorted(members):
data = (
manifest_bytes
if relative == "PUBLIC_MANIFEST.json"
else (ROOT / Path(relative)).read_bytes()
)
info = zipfile.ZipInfo(relative, date_time=(1980, 1, 1, 0, 0, 0))
info.compress_type = zipfile.ZIP_DEFLATED
info.external_attr = 0o100644 << 16
info.flag_bits |= 0x800
archive.writestr(info, data, compress_type=zipfile.ZIP_DEFLATED, compresslevel=9)
os.replace(temporary, output)
finally:
if temporary.exists():
temporary.unlink()
with zipfile.ZipFile(output, "r") as archive:
actual = archive.namelist()
if actual != sorted(members) or len(actual) != len(set(actual)):
return fail("ZIP member inventory mismatch")
if archive.testzip() is not None:
return fail("ZIP CRC verification failed")
data = output.read_bytes()
print(
json.dumps(
{
"status": "BUILT",
"member_count": len(members),
"bytes": len(data),
"sha256": hashlib.sha256(data).hexdigest(),
"submission_authorized": False,
},
sort_keys=True,
separators=(",", ":"),
)
)
return 0
if __name__ == "__main__":
raise SystemExit(main())
SHA-256: bcc25bdda79a52a1294302b1b8f0a2decef43f045b347d79488f7b242cf14f82