"""verify_decision.py — INDEPENDENT, offline verifier for a THRONDAR governed decision.

Given a saved ``/v1/chat`` response and the bridge's PUBLISHED public keys, this script
re-derives the signed bytes from scratch and verifies, with real post-quantum crypto
(ML-DSA-87 / FIPS 204 + Falcon-1024), that:

  1. the ANSWER was dual-signed by the bridge's attestation identity
     (``GET /v1/provenance/pubkeys``), and
  2. the DECISION RECORD (members, governance verdict, cost, answer-digest) was
     dual-signed by the bridge's PINNABLE ledger identity (``GET /v1/ledger/pubkey``) —
     the response's embedded ledger pubkey must EQUAL the published one.

It also demonstrates tamper-evidence: flip any field and verification fails.

No bridge access or API token is needed to verify a decision someone shares with you —
only the response JSON + the two public-key JSONs. Public keys only; no secrets.

Requires:  pip install pqcrypto      (PQClean ML-DSA-87 + Falcon-1024 backends)

Capture the three inputs from any THRONDAR bridge (public keys need no auth):
  curl -s https://<bridge>/v1/provenance/pubkeys > provenance_pubkeys.json
  curl -s https://<bridge>/v1/ledger/pubkey      > ledger_pubkeys.json
  # response.json = a /v1/chat response someone shared with you

Usage:
  python verify_decision.py response.json provenance_pubkeys.json ledger_pubkeys.json

Exit 0 = every proof passes; 1 = any failure; 2 = bad usage.
"""
from __future__ import annotations

import base64
import hashlib
import json
import sys


def _b64d(s: str) -> bytes:
    return base64.b64decode(s.encode("ascii"))


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


def _mldsa():
    from pqcrypto.sign import ml_dsa_87 as m  # FIPS 204
    return m


def _falcon():
    try:
        from pqcrypto.sign import falcon_1024 as f
        return f
    except Exception:
        return None


def _verify(mod, pk: bytes, msg: bytes, sig: bytes) -> bool:
    try:
        return bool(mod.verify(pk, msg, sig))
    except Exception:
        return False


def _key(pubkeys: dict, role: str):
    for k in pubkeys.get("keys", []):
        if k.get("role") == role:
            return k
    return None


def verify_answer(resp: dict, prov: dict) -> list:
    out = []
    att = (resp.get("council") or {}).get("attestation") or {}
    if not att:
        return [("answer.attestation_present", False)]
    text = resp.get("final_response", "")
    context = (prov.get("context") or "apex-jarvis/APEX-PQC-v1/artifact").encode("utf-8")
    message = _canon({"text": text})
    signed = context + b"\x00" + message
    out.append((
        "answer.digest(SHA3-512)",
        base64.b64encode(hashlib.sha3_512(message).digest()).decode("ascii") == att.get("digest"),
    ))
    prim = _key(prov, "primary")
    if prim and att.get("sig_primary"):
        out.append(("answer.ML-DSA-87", _verify(_mldsa(), _b64d(prim["public_key_b64"]), signed, _b64d(att["sig_primary"]))))
    sec = _key(prov, "secondary")
    if sec and att.get("sig_secondary"):
        f = _falcon()
        out.append(("answer.Falcon-1024", f is not None and _verify(f, _b64d(sec["public_key_b64"]), signed, _b64d(att["sig_secondary"]))))
    return out


def verify_ledger(resp: dict, ledger: dict) -> list:
    out = []
    dl = resp.get("decision_ledger")
    if not dl:
        return [("decision_ledger.present", False)]
    record = dl.get("record")
    digest_hex = hashlib.sha384(_canon(record)).hexdigest()
    out.append(("ledger.sha384", digest_hex == dl.get("sha384")))
    domain = ledger.get("domain") or "throndar/apex-decision-ledger/v1"
    signed = (domain + "\n").encode("utf-8") + digest_hex.encode("ascii")
    prim = _key(ledger, "primary")
    if prim:
        out.append(("ledger.pubkey_pinned", dl.get("pubkey_primary") == prim.get("public_key_b64")))
        out.append(("ledger.ML-DSA-87", _verify(_mldsa(), _b64d(prim["public_key_b64"]), signed, _b64d(dl["sig_primary"]))))
    else:
        out.append(("ledger.published_pubkey_available", False))
    sec = _key(ledger, "secondary")
    if sec and dl.get("dual_signed") and dl.get("sig_secondary"):
        out.append(("ledger.pubkey_pinned_secondary", dl.get("pubkey_secondary") == sec.get("public_key_b64")))
        f = _falcon()
        out.append(("ledger.Falcon-1024", f is not None and _verify(f, _b64d(sec["public_key_b64"]), signed, _b64d(dl["sig_secondary"]))))
    return out


def main(argv) -> int:
    try:
        sys.stdout.reconfigure(encoding="utf-8")
    except Exception:
        pass
    if len(argv) < 4:
        print(__doc__)
        return 2
    resp = json.load(open(argv[1], encoding="utf-8"))
    prov = json.load(open(argv[2], encoding="utf-8"))
    ledger = json.load(open(argv[3], encoding="utf-8"))
    results = verify_answer(resp, prov) + verify_ledger(resp, ledger)
    print("=== THRONDAR decision verification (independent, post-quantum) ===")
    all_ok = True
    for name, ok in results:
        print(f"  {'PASS' if ok else 'FAIL'}  {name}")
        all_ok = all_ok and ok
    print("-----------------------------------------------------------------")
    print("RESULT:", "ALL PROOFS PASS" if all_ok else "VERIFICATION FAILED")
    return 0 if all_ok else 1


if __name__ == "__main__":
    raise SystemExit(main(sys.argv))
