# SPDX-License-Identifier: MIT """Validate a completed 45-cell Clark review against a sealed local review kit.""" from __future__ import annotations import argparse,json from hashlib import sha256 from pathlib import Path if __package__:from .clark_curator_source_review import validate else:from clark_curator_source_review import validate FIELDS=["schema_version","status","binding_sha256","pairing_sha256","files","source_cells","all_cells_checked","production_database_used","submission_created","identity_verified","independence_verified","scientific_validation_claimed","discovery_claimed","kit_sha256"] HASH=set("0123456789abcdef") def _hash(v):return isinstance(v,str) and len(v)==64 and not(set(v)-HASH) def complete(kit_dir,completed_review): root=Path(kit_dir) if not root.is_dir() or root.is_symlink():raise ValueError("regular review kit directory required") manifest_path=root/"review-kit-manifest.json";raw=manifest_path.read_bytes();m=json.loads(raw.decode("utf-8")) if list(m)!=FIELDS or m["schema_version"]!="openlab-clark-bound-review-kit-v1" or m["status"]!="local_private_curator_review_kit_staged_not_reviewed":raise ValueError("review kit identity or fields drift") if not all(_hash(m[x]) for x in ["binding_sha256","pairing_sha256","kit_sha256"]):raise ValueError("review kit hash invalid") expected=sha256(json.dumps({k:m[k] for k in FIELDS[:-1]},ensure_ascii=False,separators=(",",":"),sort_keys=True).encode()).hexdigest() if m["kit_sha256"]!=expected:raise ValueError("review kit seal mismatch") if m["source_cells"]!=45 or m["all_cells_checked"] is not False:raise ValueError("review kit must begin blank with 45 cells") for f in ["production_database_used","submission_created","identity_verified","independence_verified","scientific_validation_claimed","discovery_claimed"]: if m[f] is not False:raise ValueError("review kit promotion refused") if [x.get("name") for x in m["files"]]!=["curator-case.json","source-review-template.json"]:raise ValueError("review kit file list drift") for item in m["files"]: if set(item)!={"name","bytes","sha256"} or not _hash(item["sha256"]):raise ValueError("review kit file binding invalid") p=root/item["name"] if p.is_symlink() or not p.is_file():raise ValueError("review kit file missing or nonregular") data=p.read_bytes() if len(data)!=item["bytes"] or sha256(data).hexdigest()!=item["sha256"]:raise ValueError("review kit file differs from manifest") review_path=Path(completed_review) if review_path.resolve() in {p.resolve() for p in [manifest_path,root/"curator-case.json",root/"source-review-template.json"]}:raise ValueError("completed review must be a separate file") receipt=validate(root/"curator-case.json",review_path) body={"schema_version":"openlab-clark-review-kit-completion-v1","status":"source_review_completed_for_private_identity_independence_and_domain_assessment_not_validation","kit_sha256":m["kit_sha256"],"binding_sha256":m["binding_sha256"],"pairing_sha256":m["pairing_sha256"],"source_review_receipt_sha256":receipt["receipt_sha256"],"source_review":receipt,"identity_assessment_required":True,"independence_assessment_required":True,"domain_assessment_required":True,"production_database_used":False,"submission_created":False,"identity_verified":False,"independence_verified":False,"scientific_validation_claimed":False,"discovery_claimed":False} body["completion_sha256"]=sha256(json.dumps(body,ensure_ascii=False,separators=(",",":"),sort_keys=True).encode()).hexdigest();return body def main(): p=argparse.ArgumentParser();p.add_argument("kit_dir");p.add_argument("completed_review");p.add_argument("--out",required=True);a=p.parse_args();r=complete(a.kit_dir,a.completed_review);Path(a.out).write_text(json.dumps(r,ensure_ascii=False,indent=2)+"\n",encoding="utf-8");print(json.dumps(r,ensure_ascii=False)) if __name__=="__main__":main()