"""Verify a synthetic Trace hash chain without claiming issuer authenticity."""
from __future__ import annotations
import argparse,hashlib,json
from pathlib import Path

FIELDS={"schemaVersion","traceId","seq","eventType","atMs","sourceOrigin","data","previousHash","eventHash"}
TYPES=["OBSERVATION_ACCEPTED","POLICY_EVALUATED","MOCK_DRIVER_COMPLETED","REPORT_CANDIDATE_BUILT"]
FORBIDDEN={"courseCredit","hardwareAuthority","reservationCreated","teacherApproved","leaseIssued","channelOwnershipGranted","actionEligible"}
def canonical(value):return json.dumps(value,ensure_ascii=False,sort_keys=True,separators=(",",":")).encode("utf-8")
def digest(value):return hashlib.sha256(canonical(value)).hexdigest().upper()
def contains_forbidden(value):
 if isinstance(value,dict):return bool(FORBIDDEN&set(value)) or any(contains_forbidden(v) for v in value.values())
 if isinstance(value,list):return any(contains_forbidden(v) for v in value)
 return False
def result(valid,reason,count=0):return {"schemaVersion":"0.1.0","artifactType":"TRACE_CHAIN_VERIFICATION","chainValid":valid,"firstReason":reason,"eventCount":count,"provenanceVerified":False,"authenticIssuerVerified":False,"realEvidenceEligible":False,"hardwareAuthority":0,"actionEligible":False,"decision":"NO_GO"}
def verify(events):
 if not isinstance(events,list) or len(events)!=4:return result(False,"EVENT_COUNT_INVALID",len(events) if isinstance(events,list) else 0)
 previous="0"*64;trace_id=None
 for index,event in enumerate(events,1):
  if not isinstance(event,dict):return result(False,"EVENT_FIELDS_INVALID",index-1)
  if contains_forbidden(event):return result(False,"AUTHORITY_ESCALATION",index-1)
  if set(event)!=FIELDS:return result(False,"EVENT_FIELDS_INVALID",index-1)
  if event["schemaVersion"]!="0.1.0" or event["sourceOrigin"]!="SYNTHETIC" or event["seq"]!=index or type(event["atMs"]) is not int or event["atMs"]<0 or not isinstance(event["data"],dict):return result(False,"EVENT_SEMANTICS_INVALID",index-1)
  if event["eventType"]!=TYPES[index-1]:return result(False,"EVENT_SEQUENCE_INVALID",index-1)
  trace_id=trace_id or event["traceId"]
  if event["traceId"]!=trace_id or not isinstance(trace_id,str) or not trace_id:return result(False,"TRACE_ID_INVALID",index-1)
  if event["previousHash"]!=previous:return result(False,"PREVIOUS_HASH_MISMATCH",index-1)
  body={key:event[key] for key in FIELDS-{"eventHash"}};computed=digest(body)
  if event["eventHash"]!=computed:return result(False,"EVENT_HASH_MISMATCH",index-1)
  previous=computed
 return result(True,"CHAIN_VALID_PROVENANCE_UNVERIFIED",len(events))
def main(argv=None):
 parser=argparse.ArgumentParser(description="Verify a synthetic Trace hash chain");parser.add_argument("--input",required=True,type=Path);args=parser.parse_args(argv)
 try:events=[json.loads(line) for line in args.input.read_text(encoding="utf-8").splitlines() if line.strip()]
 except (OSError,UnicodeDecodeError,json.JSONDecodeError):output=result(False,"JSONL_INVALID")
 else:output=verify(events)
 print(json.dumps(output,ensure_ascii=False,sort_keys=True,separators=(",",":")));return 0 if output["chainValid"] else 2
if __name__=="__main__":raise SystemExit(main())
