Gateway Receipt Integrity Verifier — Staging
Inspect a Gateway staging receipt without creating an account or uploading receipt data. This isolated page recomputes the record's decision hash, verifies its Ed25519 signature against the published staging key, and — when you supply adjacent receipts — checks links within that supplied chain segment.
The supplied decision record has not been altered since its canonical SHA-256 decision_hash was computed.
The signature verifies under the published key for this staging kid. That establishes staging-key provenance — not production identity or third-party attestation.
When adjacent receipts are supplied, their signed prev_hash and seq links hold within that segment. This does not prove that no segment or tail was omitted.
Paste a Gateway receipt
Paste one receipt, or an array of adjacent receipts from one staging organization to also check the supplied chain links.
TIP: paste directly from GET /v1/decisions or the inline decision response. Whitespace and key order are normalized before hashing.
How verification works
The verifier reproduces the gateway's canonicalization byte-for-byte. Canonical JSON is:
- recursively sort every object's keys lexicographically (byte-wise / UTF-8); arrays keep their order;
- serialize compactly — no whitespace, UTF-8, standard JSON string escaping.
This is the same canonical form the gateway's Rust implementation uses (hag_saas_adapter::snapshot::canonicalize_value + serde_json::to_vec), in the spirit of RFC 8785 / JCS. Two hashes are computed:
- decision_hash = lowercase hex SHA-256 of the canonical bytes of the decision record.
- sig = Ed25519 over the canonical bytes of exactly the five-field envelope (keys sort alphabetically):
{"decision_hash":"…","issued_at":"…","kid":"…","prev_hash":"…","seq":0}
Because prev_hash and seq are inside the signed bytes, a valid signature authenticates the receipt's claimed sequence number and predecessor hash. Continuity exists only when adjacent signed receipts are supplied and those links match. The signature is checked with the browser's Web Crypto API (Ed25519). Receipt checks run locally, and this page's enforced security policy blocks third-party scripts and outbound data requests.
Published staging key
Each receipt carries a convenience copy of its public_key. The verifier does not treat that embedded copy as trusted. It compares the embedded key with the staging key pinned in this verifier, then checks the signature against the pinned key:
| KID | ENVIRONMENT | ED25519 PUBLIC KEY (BASE64) |
|---|---|---|
| staging-2026-07-06 | hag-gateway-staging | ld8arGfvi2LDtD8uQ91BdXnitdiFBU8Q6AP3IkrEGPQ= |
Rotation means a new seed and a new kid; verifiers keep old keys to validate historical receipts. The pinned staging key is also documented in the gateway repository's docs/receipts-verification.md for customer diligence and offline tooling.
Run the verification tests yourself
Three checks exercise the properties this verifier claims. All three use the staging-key-signed sample above — no setup, no account.
- CHECK 01 — POSITIVE CONTROL. Load the worked example and verify. Expect RECEIPT INTEGRITY VERIFIED: the decision hash recomputes, the embedded key matches the published staging key for staging-2026-07-06, and the Ed25519 signature verifies.
- CHECK 02 — TAMPER CHECK. Press Run tamper check. It loads the same receipt with one field flipped (verdict: permit → deny) and verifies immediately. Expect INTEGRITY NOT VERIFIED: a single altered field breaks the hash recomputation, so the receipt can no longer claim the decision it shows. Or tamper by hand — change any hashed or signed field and re-check.
- CHECK 03 — SUPPLIED-SEGMENT CHECK. Paste a JSON array of receipts from one organization (e.g. from GET /v1/decisions). The verifier requires one organization, orders the supplied receipts by seq, rejects duplicates and sequence gaps, and checks each internal prev_hash link. SUPPLIED SEGMENT LINKS INTACT reports only when those checks pass; it does not establish an unsupplied predecessor or tail.
The same checks can run offline: the gateway ships a Python reference verifier and a Rust API (hag_saas_adapter::receipts::verify_receipt), documented in docs/receipts-verification.md, for CI pipelines and air-gapped review.
- A signed decision record is not independent execution proof. A valid receipt establishes what the staging-key holder recorded and signed. It does not independently establish that the policy was correct, that downstream equipment executed or rejected the action, or that every relevant action was mediated by the Gateway.
- Staging key. The only published anchor today is staging-2026-07-06 (the hag-gateway-staging environment). This is a real, live-verifiable signing key, not a production attestation.
- Hash chain, not a complete external ledger. Version 1 validates order and integrity within the supplied per-organization chain segment. It cannot prove that an entire segment or trailing portion was not omitted, and it does not yet provide third-party-witnessable tree heads or compact inclusion proofs. Merkle batching is planned for version 2.
- Chain segments reset on process restart. The chain head is held in memory, so a gateway restart begins a new segment (seq: 0, genesis prev_hash). Restarts are therefore visible as a new genesis; cross-segment continuity is not yet cryptographically linked.
- Numeric tokens are preserved verbatim. Integers, strings, booleans and null — everything in the signed envelope — are exact across ecosystems. Non-integer floats in a decision record are compared using the exact numeric text the gateway emitted; if a receipt's decision block was re-serialized by a different JSON library that renormalizes numbers, the recomputed hash may differ. Verify against the original gateway bytes. (Full JCS number canonicalization is future work.)
- The embedded public_key is not a trust anchor. This page checks it against the published key above and verifies the signature against the published key, never the embedded copy.
- This is a verification tool, not a certification claim. It demonstrates that a Gateway staging receipt's hash and signature can be checked locally against the staging key published on this site. It does not assert any third-party certification.
Prefer to verify offline or in CI? The gateway ships a Python reference verifier and a Rust API (hag_saas_adapter::receipts::verify_receipt) documented in docs/receipts-verification.md. See also our AARM alignment page and the full artifact index on Resources — The Record.
Evaluate the boundary, not just the artifact.
Bring one consequential AI action or data crossing. We will map the enforcement point, review the evidence the Gateway can produce, and define the smallest credible evaluation path.
BRING ONE AI WORKFLOW, ONE CONSEQUENTIAL ACTION, OR ONE DATA BOUNDARY.