# Verify a HANRIA receipt

Every `permit`, `deny` or `escalate` from the free hosted check carries a `receipt` signed with
Ed25519. This script checks one without asking HANRIA. Node 22 or later, no dependencies.

```
node verify_receipt.mjs ANSWER.json MANDATE.json ACTION.json
```

`ANSWER.json` is the check's answer as you received it (or only its `receipt`). `MANDATE.json` and
`ACTION.json` are the exact documents you sent. The script recomputes both digests, checks the
15 minute window, and checks the signature against the published key at
https://check.hanria.ai/.well-known/hanria-receipt-keys.json. Pass `--keys FILE` to use a key file
you saved, and `--at TIME` to check the window at another time. Exit 0 only when every check passes.

A passing receipt proves what the hosted check answered for this action under this mandate, and
when. It does not prove the action was performed, and it does not prove the mandate is the
operator's.

The rule, for writing your own verifier: canonical JSON has its keys sorted, no spaces, and
non-ASCII written as \uXXXX. `action_digest` is SHA-256 of `hanria-action-v1` followed by the
action's canonical JSON. `mandate_digest` is SHA-256 of the mandate's canonical JSON. The signed
bytes are the UTF-8 of `hanria-receipt-v1`, a newline, and the canonical JSON of the receipt
without `signature`. `signature` is base64url.
