{
  "algorithm": "Ed25519",
  "key_custody": "Generated by the GAIP runtime and held only in GAIP's runtime database; excluded from backups; no person has been shown it. RETIRED keys stay listed so older signatures still verify; a key retired with retired_reason COMPROMISED is listed for transparency and must not be trusted.",
  "keys": [
    {
      "alg": "EdDSA",
      "created_at": "2026-10-01T09:28:00.069668Z",
      "crv": "Ed25519",
      "kid": "70ae8f5c793b4f5a",
      "kty": "OKP",
      "status": "ACTIVE",
      "use": "sig",
      "x": "sFij-KoqUO5ZCg40lL3WqPZ9yJg1B19Gupg1XfR5Is8"
    }
  ],
  "kid_rule": "kid = first 16 lower-case hex characters of SHA-256 over the raw 32-byte Ed25519 public key.",
  "message_rule": "Ed25519 (RFC 8032) signature over the ASCII bytes '<purpose>:<digest>' where digest is the lower-case hex SHA-256 named by purpose (any 'sha256:' or '0x' prefix removed).",
  "price_gbp": 0,
  "proof_boundary": "A valid signature shows GAIP's runtime key signed that digest. It does not prove the truth of the recorded event, legal identity, ownership, value or outcome. It is not a qualified electronic signature, seal or timestamp.",
  "purposes": {
    "gaip.accuracy_pair.receipt_sha256.v1": "pair_sha256 of a Second Look vendor-submitted accuracy pair (SHA-256 over the canonical JSON of the record without receipt_id, observation_id, pair_sha256, its signature fields and the handle binding; accuracy_pairs.py). It records what the vendor submitted beside what the page showed when GAIP read it, never a finding about the assistant or the shop.",
    "gaip.act.entry_sha256.v1": "entry_sha256 of a GAIP act log entry (gaip.act.v1: SHA-256 over the canonical JSON of the entry without receipt_id, observation_id, entry_sha256, its signature fields and any cosigner; act_log.py). It records that an agent submitted the entry at the stated time and, where shown, what a public page showed when GAIP read it; never that the act happened as described.",
    "gaip.agent_commerce_check.receipt_sha256.v1": "receipt_sha256 of a GAIP agent-commerce check receipt (SHA-256 over the canonical JSON of the receipt without its signature fields; agent_commerce_record.py). It records what a shop's own file said when GAIP read it, never GAIP's view of the shop.",
    "gaip.compliance_export.sha256.v1": "export_sha256 of a compliance-record export (SHA-256 over the canonical JSON of the export without its signature fields; compliance_record.py). GAIP's own daily readings of a consenting shop's product page, never a statement about any price or deadline.",
    "gaip.digest_manifest.root_sha256.v1": "digest_manifest.root_sha256 of a GAIP evidence pack, incident bundle or receipt export.",
    "gaip.disclosure.entry_sha256.v1": "entry_sha256 of a GAIP disclosure record (the chained record_sha256 of its History Spine row; disclosures.py). It records what the disclosing agent stated, never GAIP's view.",
    "gaip.disclosure_ack.entry_sha256.v1": "entry_sha256 of a recipient's acknowledgement of a GAIP disclosure record (the chained record_sha256 of its History Spine row; disclosures.py).",
    "gaip.erc8004.response_hash.v1": "responseHash of an ERC-8004-shaped validationResponse export (SHA-256 over JCS).",
    "gaip.evidence_export.bundle_sha256.v1": "bundle_sha256 of a GAIP evidence bundle (gaip.evidence-bundle.not-as-described.v1: SHA-256 over the canonical JSON of the bundle without its signature fields; evidence_export.py). It records what GAIP recorded at the times shown, never who is right.",
    "gaip.host_owner_verification.challenge_sha256.v1": "SHA-256 over the canonical JSON of {challenge, host_key} for a site owner's host-timeline verification; the owner's token is derived from this signature (host_timeline.py).",
    "gaip.mandate_check.receipt_sha256.v1": "receipt_sha256 of a GAIP Mandates checked-at receipt (SHA-256 over the canonical JSON of the receipt without its signature fields; agent_mandates.py).",
    "gaip.order_capture.receipt_sha256.v1": "receipt_sha256 of an order-time capture receipt (SHA-256 over the canonical JSON of the receipt without receipt_id, observation_id, receipt_sha256 and its signature fields; order_capture.py). It records what the shop's public product pages showed when the order was received, not who is right.",
    "gaip.permission_answer.answer_sha256.v1": "answer_sha256 of a gaip_check_permission answer (SHA-256 over the canonical JSON of the answer without its signature fields).",
    "gaip.preference_check.receipt_sha256.v1": "receipt_sha256 of a GAIP Preferences checked-at receipt (SHA-256 over the canonical JSON of the receipt without its signature fields; agent_preferences.py).",
    "gaip.recall_check.recall_sha256.v1": "recall_sha256 of a recall-check receipt (SHA-256 over the canonical JSON of the receipt without receipt_id, observation_id, recall_sha256 and its signature; recall_check.py).",
    "gaip.record_answer.answer_sha256.v1": "answer_sha256 of an answer from the record by date (tenure, names, keys, permissions, prices): SHA-256 over the canonical JSON of the answer without its signature fields; record_routes.py).",
    "gaip.record_extract.extract_sha256.v1": "extract_sha256 of a gaip_record_extract extract of GAIP's record (SHA-256 over the canonical JSON of the extract without its signature fields).",
    "gaip.record_sha256.v1": "record_sha256 of one GAIP History Spine record (the per-record hash-chain digest).",
    "gaip.revocations.document_sha256.v1": "document_sha256 of a GAIP revocations feed page, status list or revoked-since answer (SHA-256 over the canonical JSON of the document without its signature fields; revocations.py). It shows what GAIP published and when, nothing about effect.",
    "gaip.second_look.offer_sha256.v1": "offer_sha256 of a Second Look \"offer seen\" receipt (SHA-256 over the canonical JSON of the receipt without receipt_id, observation_id, offer_sha256 and its signature fields; second_look.py).",
    "gaip.serve.entry_sha256.v1": "entry_sha256 of a GAIP Served entry (the chained record_sha256 of its History Spine row: the serve, a fetch, the acknowledgement or the retry; served.py). It records what GAIP delivered and what the endpoint answered.",
    "gaip.signoff.entry_sha256.v1": "entry_sha256 of a GAIP sign-off record (the chained record_sha256 of its History Spine row; witness.py witness_signoff). It records a role's stated decision, never GAIP's.",
    "gaip.statement.statement_sha256.v1": "statement_sha256 of a GAIP monthly statement (SHA-256 over the canonical JSON of the statement's core: period, continuity_ref, totals, lines, chain_head and the sentence; statements.py).",
    "gaip.switch_pack.pack_sha256.v1": "pack_sha256 of a GAIP switch pack (gaip.switch-pack.v1: SHA-256 over the canonical JSON of the pack without its signature and per-call fields; switch_pack.py). GAIP's own export of the entries bound to one handle, with its public keys and the verifier steps; it binds no other provider and says nothing about any act.",
    "gaip.witness_finding.finding_sha256.v1": "finding_sha256 of a GAIP Deals finding record (SHA-256 over the canonical JSON of the record without its signature fields; deals.py).",
    "gaip.x402_sar.receipt_id.v1": "receipt_id of an x402 SAR v0.1 export (SHA-256 over JCS of the SAR core fields)."
  },
  "rotation": "A rotation adds a new ACTIVE key and keeps the old one listed as RETIRED with retired_at and retired_reason (ROTATED or COMPROMISED). Receipts are signed when they are read, so the same receipt read after a rotation carries a signature by the new key; a signature by a RETIRED key still verifies against this set unless retired_reason is COMPROMISED. For a few minutes after a rotation some answers may still carry the previous key's signature.",
  "schema_version": "gaip.receipt-keys.v1",
  "signing_available": true,
  "unavailable_reason": null,
  "verify_hint": "Find the key whose kid equals signature.kid, base64url-decode x and sig, rebuild '<purpose>:<digest>' and check the Ed25519 signature."
}