{
  "service": "verify",
  "method": "POST, or GET with ?d=<packed receipt> for a link anyone can dereference",
  "price": "Free, always.",
  "body": "A Touchstone receipt, or {\"receipt\": {...}}",
  "returns": "Whether the signature still matches the contents.",
  "key": {
    "alg": "ed25519",
    "publicKeyId": "0d926c27c2dbb95f",
    "publicKey": "MCowBQYDK2VwAyEAg62V3C6BQOiVz+oG3/RFgYqC+LOotIqNxafkrsDME3s=",
    "publicKeyRaw": "g62V3C6BQOiVz+oG3/RFgYqC+LOotIqNxafkrsDME3s=",
    "signatureEncoding": "base64",
    "signedBytes": "Canonical JSON of the receipt with its `signature` member removed: object keys sorted at every depth, arrays left in their order, `undefined` members dropped, UTF-8.",
    "development": false,
    "verify": "// node check.cjs receipt.json   ->   true means the receipt is intact\nconst { createPublicKey, verify } = require(\"node:crypto\");\nconst receipt = require(require(\"node:path\").resolve(process.argv[2]));\n\nconst canonical = (v) =>\n  v === null || typeof v !== \"object\" ? JSON.stringify(v) ?? \"null\"\n  : Array.isArray(v) ? \"[\" + v.map(canonical).join(\",\") + \"]\"\n  : \"{\" + Object.entries(v)\n      .filter(([, i]) => i !== undefined)\n      .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n      .map(([k, i]) => JSON.stringify(k) + \":\" + canonical(i))\n      .join(\",\") + \"}\";\n\nconst { signature, ...unsigned } = receipt;\nconst key = createPublicKey({ key: Buffer.from(\"MCowBQYDK2VwAyEAg62V3C6BQOiVz+oG3/RFgYqC+LOotIqNxafkrsDME3s=\", \"base64\"), format: \"der\", type: \"spki\" });\nconsole.log(verify(null, Buffer.from(canonical(unsigned)), key, Buffer.from(signature.value, \"base64\")));"
  }
}