#!/usr/bin/env python3 """ verify_cross_binding.py — independent Python verifier for the JCR-1 `schema_id` schema. Reads `cross-binding-vectors.json`, recanonicalises each binding under sorted-key JSON (UTF-8, no whitespace), BLAKE3-hashes the bytes, and asserts the hex matches the vector's embedded `content_hash`. Deps: blake3 (`pip install blake3`). Usage: python3 verify_cross_binding.py [cross-binding-vectors.json] """ import sys, json from pathlib import Path try: import blake3 except ImportError: sys.stderr.write( "this verifier requires the blake3 module — `pip install blake3`\n" ) sys.exit(2) def canonicalise(value): if isinstance(value, dict): return {k: canonicalise(value[k]) for k in sorted(value)} if isinstance(value, list): return [canonicalise(v) for v in value] return value def canonical_bytes(value) -> bytes: return json.dumps( canonicalise(value), separators=(",", ":"), ensure_ascii=False, ).encode("utf-8") def main(): path = ( Path(sys.argv[1]) if len(sys.argv) > 1 else Path(__file__).parent / "cross-binding-vectors.json" ) suite = json.loads(path.read_text()) expected_spec = "JouleClaw cross-standards binding v1" if suite.get("spec") != expected_spec: sys.stderr.write(f"spec mismatch: got {suite.get('spec')!r}, want {expected_spec!r}\n") sys.exit(1) failed = 0 for vec in suite["vectors"]: n = vec["n"] desc = vec["description"] expected_hash = vec["content_hash"] payload = vec["binding"] canon = canonical_bytes(payload) computed = blake3.blake3(canon).hexdigest() if computed == expected_hash: print(f" ✓ vector {n}: {desc}") else: print(f" ✗ vector {n}: {desc}") print(f" expected: {expected_hash}") print(f" computed: {computed}") failed += 1 if failed: sys.stderr.write(f"\n{failed} vector(s) failed verification\n") sys.exit(1) print(f"\nverify_cross_binding.py — all {len(suite['vectors'])} vectors PASS") if __name__ == "__main__": main()