# SPDX-License-Identifier: MIT """Bind a Clark hash-screen receipt to the existing semantic handoff checker.""" from __future__ import annotations import argparse,json from hashlib import sha256 from pathlib import Path if __package__:from .prepare_clark_handoff import prepare,validate_manifest else:from prepare_clark_handoff import prepare,validate_manifest REQUEST="ab2a8887110cb058d496e0afe1563fe7e42ee260a63608efa2de03a62e58a534";HASH=set("0123456789abcdef") FIELDS=["schema_version","status","request_sha256","dispatch_sha256","role","worksheet_sha256","received_on","files","total_bytes","raw_content_copied_to_receipt","sender_address_stored","production_database_used","submission_created","identity_verified","independence_verified","scientific_validation_claimed","manual_private_curator_review_required","intake_sha256"] REQUIRED=["worksheet.csv","validation-draft.json","reviewer-self-check.json","handoff-manifest.json"] def _hash(v):return isinstance(v,str) and len(v)==64 and not(set(v)-HASH) def _intake(v): if list(v)!=FIELDS or v["schema_version"]!="openlab-clark-attachment-intake-receipt-v1" or v["status"]!="files_hash_screened_for_private_curator_review_not_submission" or v["request_sha256"]!=REQUEST:raise ValueError("intake identity or fields drift") for f in ["dispatch_sha256","worksheet_sha256","intake_sha256"]: if not _hash(v[f]):raise ValueError("intake hash invalid") body={k:v[k] for k in FIELDS[:-1]};expected=sha256(json.dumps(body,ensure_ascii=False,separators=(",",":"),sort_keys=True).encode()).hexdigest() if v["intake_sha256"]!=expected:raise ValueError("intake seal mismatch") if v["raw_content_copied_to_receipt"] is not False or v["sender_address_stored"] is not False or v["production_database_used"] is not False or v["submission_created"] is not False or v["identity_verified"] is not False or v["independence_verified"] is not False or v["scientific_validation_claimed"] is not False or v["manual_private_curator_review_required"] is not True:raise ValueError("intake boundary drift") return v def admit(intake,directory): intake=_intake(intake);root=Path(directory) if not root.is_dir() or root.is_symlink():raise ValueError("regular admission directory required") by_name={x["name"]:x for x in intake["files"]} if len(by_name)!=len(intake["files"]) or not set(REQUIRED)<=set(by_name):raise ValueError("intake receipt file set incomplete") for name,item in by_name.items(): if set(item)!={"name","bytes","sha256"} or not _hash(item["sha256"]):raise ValueError("intake file binding invalid") p=root/name if p.is_symlink() or not p.is_file():raise ValueError("admission file missing or nonregular") data=p.read_bytes() if len(data)!=item["bytes"] or sha256(data).hexdigest()!=item["sha256"]:raise ValueError("admission file differs from intake receipt") provided=validate_manifest(json.loads((root/"handoff-manifest.json").read_text(encoding="utf-8"))) calculated=prepare(root/"worksheet.csv",root/"validation-draft.json",root/"reviewer-self-check.json") if provided!=calculated:raise ValueError("provided handoff manifest differs from semantic recheck") if intake["role"]!=calculated["reviewer_role"] or intake["worksheet_sha256"]!=calculated["files"][0]["sha256"]:raise ValueError("intake role or worksheet binding drift") result={"schema_version":"openlab-clark-intake-admission-receipt-v1","status":"admitted_for_private_role_pairing_not_submission","request_sha256":REQUEST,"intake_sha256":intake["intake_sha256"],"dispatch_sha256":intake["dispatch_sha256"],"role":calculated["reviewer_role"],"worksheet_sha256":calculated["files"][0]["sha256"],"handoff_manifest_sha256":by_name["handoff-manifest.json"]["sha256"],"semantic_recheck_passed":True,"raw_content_copied_to_receipt":False,"production_database_used":False,"submission_created":False,"identity_verified":False,"independence_verified":False,"scientific_validation_claimed":False,"manual_private_pairing_required":True} result["admission_sha256"]=sha256(json.dumps(result,ensure_ascii=False,separators=(",",":"),sort_keys=True).encode()).hexdigest();return result def main(): p=argparse.ArgumentParser();p.add_argument("intake");p.add_argument("directory");p.add_argument("--out",required=True);a=p.parse_args();r=admit(json.loads(Path(a.intake).read_text(encoding="utf-8")),a.directory);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()