{
 "key_id": "nycticketfacts-answer-2026-09-06",
 "alg": "Ed25519",
 "public_key_spki_b64": "MCowBQYDK2VwAyEAaBvTLs5oT5Z8RL/3vxhHZGFcWA6hXR91iACNVRASz6E=",
 "public_key_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAaBvTLs5oT5Z8RL/3vxhHZGFcWA6hXR91iACNVRASz6E=\n-----END PUBLIC KEY-----",
 "created": "2026-09-06",
 "policy": "axion-receipt/v1: sha256 over the body minus this receipt, dataset <stamp>, fields as served",
 "signs": "/api/violations responses on https://nycticketfacts.com — each carries a receipt field with a detached signature",
 "signed_message_format": "answer-receipt/v1|<key_id>|<payload_sha256>|<signed_at>|<dataset_version>",
 "verify_endpoint": "https://nycticketfacts.com/api/verify-receipt",
 "offline_recipe": [
  "1. Take the raw response text. Parse it. Remove the `receipt` field.",
  "2. Re-serialize with JSON.stringify(obj, null, 1) — JSON.parse preserves key order, so this reproduces the signed bytes exactly.",
  "3. SHA-256 the result; the hex digest must equal receipt.payload_sha256.",
  "4. Rebuild `answer-receipt/v1|key_id|payload_sha256|signed_at|dataset_version` from the receipt fields; it must equal receipt.signed_message.",
  "5. Verify receipt.sig (base64) over that message with this Ed25519 public key."
 ],
 "rotation": "If this key is ever rotated, the old key stays listed here under previous_keys with its retirement date so old receipts remain verifiable.",
 "contact": "hello@getaxionlabs.com"
}