#!/usr/bin/env python3
"""Verify a Sovereign Agent Receipts file — offline, without any Sovereignware code, account or network.

    python3 verify_agent_receipts.py receipts.jsonl public_key.pem

Checks, for every receipt in order:
  1. its SHA-256 over the canonical JSON body (sorted keys, no spaces, UTF-8, without "hash"/"sig") equals "hash"
     — any edited byte fails here;
  2. "prev" equals the previous receipt's hash (the first one: 64 zeros) — a deleted, inserted or reordered
     receipt fails here, and so does every one after it;
  3. "sig" is a valid Ed25519 signature of "hash" by the published public key.
Needs only Python 3 and the `cryptography` package. Exit 0 = every receipt intact.
"""
import base64
import hashlib
import json
import sys

from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.serialization import load_pem_public_key


def canonical(obj) -> bytes:
    return json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")


def main(receipts_path: str, key_path: str) -> int:
    pub = load_pem_public_key(open(key_path, "rb").read())
    prev, bad, n = "0" * 64, 0, 0
    for n, line in enumerate((l for l in open(receipts_path, encoding="utf-8") if l.strip()), 1):
        r = json.loads(line)
        body = {k: v for k, v in r.items() if k not in ("hash", "sig")}
        errs = []
        if hashlib.sha256(canonical(body)).hexdigest() != r.get("hash"):
            errs.append("content changed after signing")
        if r.get("prev") != prev:
            errs.append("chain broken here (a receipt before it was removed, added or reordered)")
        try:
            pub.verify(base64.b64decode(r.get("sig", "")), str(r.get("hash", "")).encode())
        except (InvalidSignature, ValueError):
            errs.append("signature invalid for this public key")
        mark = "OK " if not errs else "BAD"
        print(f"{mark} #{n:<4} {r.get('acted_at', '')[:19]}  {r.get('action', {}).get('summary', '')[:90]}")
        for e in errs:
            print(f"        ✗ {e}")
        bad += bool(errs)
        prev = r.get("hash")
    print(f"\n{n} receipt(s), {bad} failing. Chain head: {prev}")
    return 0 if n and not bad else 1


if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(__doc__)
        sys.exit(2)
    sys.exit(main(sys.argv[1], sys.argv[2]))
