#!/usr/bin/env python3 """Verify every published CAIN-42 claim in one command, trusting none of the three sites. No CAIN imports; needs Python 3.8+ and `cryptography`. curl -so verify_all.py https://clawx.click/verify_all.py.txt python3 verify_all.py # human-readable report python3 verify_all.py --json # machine-readable report (for crawlers / other AIs) Checks, in order: KEY the evidence-root public key is identical on cainstudio.online, mcpgate.online and clawx.click INDEX /cain42-evidence-index.json is byte-identical on all 3 sites, its digest re-hashes, and its Ed25519 signature verifies against that key REGISTRY the signed claims registry re-hashes and verifies against the same key; the index names this registry (a mismatch means the index is older than the registry: reported, not hidden) CLAIMS the index's claims (id, status, level) equal the registry's ARTIFACTS every evidence file of every claim, fetched from EVERY site, has the SHA-256 the signed registry states LIVE the live endpoints the index lists answer (cluster health, hosted pipeline, proofs, soak) What this does NOT do: re-run each claim's own deep verifier (quorum certificates, drills, models). Every claim lists that command (`verify`) and its REPRODUCE.txt; this tool prints them. Passing means the published evidence is intact, consistent across sites and signed by one key. It does not mean a third party has reviewed it: none has. """ from __future__ import annotations import base64 import hashlib import json import sys import urllib.request from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey SITES = {"cainstudio.online": "https://cainstudio.online/proof/bundle/", "mcpgate.online": "https://mcpgate.online/proof/bundle/", "clawx.click": "https://clawx.click/evidence/"} INDEX = {s: f"https://{s}/cain42-evidence-index.json" for s in SITES} INDEX_UNSIGNED = ("digest", "evidence_root_public_key_b64", "signature_b64", "signature_covers") def fetch(url: str, data=None) -> bytes: req = urllib.request.Request(url, data=data, method="POST" if data is not None else "GET", headers={"User-Agent": "cain42-verify-all"}) with urllib.request.urlopen(req, timeout=60) as r: return r.read() def canon(o) -> bytes: return json.dumps(o, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode() def sig_ok(pub_b64: str, sig_b64: str, msg: bytes) -> bool: try: Ed25519PublicKey.from_public_bytes(base64.b64decode(pub_b64)).verify(base64.b64decode(sig_b64), msg) return True except Exception: # noqa: BLE001 return False def run(): res = [] def rec(check, ok, detail, level="FAIL"): res.append({"check": check, "result": "PASS" if ok else level, "detail": detail}) return ok keys = {} for s, base in SITES.items(): try: keys[s] = json.loads(fetch(base + "claims/evidence-root.pub.json"))["public_key_b64"] except Exception as e: # noqa: BLE001 keys[s] = f"UNREACHABLE: {e}" key = keys["clawx.click"] rec("KEY", len(set(keys.values())) == 1, f"evidence-root key {key[:16]}... on {len(keys)} sites" if len(set(keys.values())) == 1 else f"keys differ: {keys}") raw = {} for s, u in INDEX.items(): try: raw[s] = fetch(u) except Exception as e: # noqa: BLE001 raw[s] = f"UNREACHABLE: {e}".encode() same = len({hashlib.sha256(b).hexdigest() for b in raw.values()}) == 1 idx = json.loads(raw["clawx.click"]) body = {k: v for k, v in idx.items() if k not in INDEX_UNSIGNED} d = hashlib.sha256(canon(body)).hexdigest() rec("INDEX", same and d == idx.get("digest") and idx.get("evidence_root_public_key_b64") == key and sig_ok(key, idx.get("signature_b64", ""), d.encode()), f"identical on 3 sites: {same}; digest {d[:16]} {'matches' if d == idx.get('digest') else 'DOES NOT match'}; " f"generated {idx.get('generated_at')}") reg = json.loads(fetch(SITES["clawx.click"] + "claims/CAIN42_FINAL_PUBLIC_CLAIMS.json")) rbody = {k: v for k, v in reg.items() if k not in ("registry_digest", "signature_b64")} rd = hashlib.sha256(canon(rbody)).hexdigest() rec("REGISTRY", rd == reg.get("registry_digest") and reg.get("evidence_root_public_key_b64") == key and sig_ok(key, reg.get("signature_b64", ""), rd.encode()), f"{len(reg['claims'])} claims, digest {rd[:16]}, issued {reg.get('issued_at')}") named = idx.get("claims_registry", {}).get("registry_digest") rec("INDEX->REG", named == rd, "index names the current registry" if named == rd else f"index names registry {str(named)[:16]} but the current one is {rd[:16]}: the index is older than the " f"registry (it is rebuilt hourly); artifacts are checked against the signed registry", level="WARN") ic = {c["id"]: (c["status"], c["evidence_level"]) for c in idx.get("claims", [])} rc = {c["claim_id"]: (c["status"], c["evidence_level"]) for c in reg["claims"]} rec("CLAIMS", ic == rc, "index and registry agree on every claim's status and level" if ic == rc else f"differ: only in registry {sorted(set(rc) - set(ic))}, only in index {sorted(set(ic) - set(rc))}, " f"changed {sorted(k for k in set(ic) & set(rc) if ic[k] != rc[k])}", level="WARN" if named != rd else "FAIL") n_files = n_bad = 0 for c in reg["claims"]: for a in c["artifacts"]: for s, base in SITES.items(): n_files += 1 url = base + f"{a['bundle']}/{a['file']}" try: h = hashlib.sha256(fetch(url)).hexdigest() except Exception as e: # noqa: BLE001 h = f"UNREACHABLE: {e}" if h != a["sha256"]: n_bad += 1 rec("ARTIFACT", False, f"{c['claim_id']}: {url} sha256 {h[:16]} != signed {a['sha256'][:16]}") rec("ARTIFACTS", n_bad == 0, f"{n_files - n_bad}/{n_files} evidence files (every claim x every site) match the signed SHA-256") for name, url in (idx.get("live_endpoints") or {}).items(): if "{" in url or url.startswith("POST"): continue try: fetch(url) ok, why = True, "answers" except Exception as e: # noqa: BLE001 ok, why = False, str(e)[:80] rec("LIVE", ok, f"{name}: {why}", level="WARN") claims = [{"id": c["claim_id"], "status": c["status"], "level": c["evidence_level"], "deep_verify": c["verification_method"], "limits": c["limits"]} for c in reg["claims"]] return res, claims, idx def main(argv) -> int: res, claims, idx = run() fails = [r for r in res if r["result"] == "FAIL"] verdict = "INTACT" if not fails else "INVALID" if "--json" in argv: print(json.dumps({"verdict": verdict, "checks": res, "claims": claims, "gates_summary": idx.get("gates_summary"), "known_limitations": idx.get("known_limitations")}, indent=1)) return 0 if not fails else 1 for r in res: print(f"[{r['result']:4s}] {r['check']:10s} {r['detail']}") print(f"\nclaims: " + ", ".join(f"{k} {v}" for k, v in sorted( {s: sum(1 for c in claims if c['status'] == s) for s in {c['status'] for c in claims}}.items()))) print(f"gates: {idx.get('gates_summary')} known limitations listed: {len(idx.get('known_limitations') or [])}") print("deep verification of each claim: python3 verify_all.py --json | read claims[].deep_verify") print(f"\n{verdict}: " + ("the published CAIN-42 evidence is intact, identical on all 3 sites and signed by one key " "(self-attested: no third party has reviewed it)" if not fails else f"{len(fails)} check(s) failed")) return 0 if not fails else 1 if __name__ == "__main__": sys.exit(main(sys.argv[1:]))