{"record":{"id":"ceb7c0f74c4a7c75","repo":"Hmbown/CodeWhale","slug":"envelope-does-not-verify-check-errors-join","errorCode":null,"errorMessage":"envelope does not verify: ${check.errors.join(\"; \")}","messagePattern":"envelope does not verify: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/scripts/facts-publish.mjs","lineNumber":407,"sourceCode":"  const keys = [];\n  const remainder = body.replace(/\\{\\s*keyId:\\s*\"([^\"]+)\",\\s*publicKey:\\s*\"([^\"]+)\",\\s*status:\\s*\"([^\"]+)\"\\s*,?\\s*\\}/g, (_, keyId, publicKey, status) => {\n    keys.push({ keyId, publicKey, status });\n    return \"\";\n  });\n  if (remainder.replace(/[\\s,]/g, \"\")) throw new Error(\"unparsed TypeScript TRUSTED_KEYS entry\");\n  return validateTrustedKeys(keys);\n}\n\nfunction loadTrustedKeysFromRepo() {\n  const keys = parseTsKeys(readBoundedFile(resolve(WEB_ROOT, \"lib/cloud-facts/keys.ts\"), 64 * 1024).toString(\"utf8\"));\n  return new Map(keys.map((key) => [key.keyId, key]));\n}\n\nexport function activePublishingKey(envelope, keys, now = Date.now()) {\n  const key = validateTrustedKeys(keys).find((key) => key.keyId === envelope.key_id && key.status === \"active\");\n  if (!key) throw new Error(\"primary signing key is not pinned and active; refusing publication\");\n  const check = verifyEnvelope(envelope, key.publicKey);\n  if (!check.ok) throw new Error(`envelope does not verify: ${check.errors.join(\"; \")}`);\n  if (!Number.isFinite(now) || utcTime(check.payload.published_at) > now + 300_000 ||\n      (check.payload.not_after != null && utcTime(check.payload.not_after) <= now)) throw new Error(\"publication timestamp is future or expired\");\n  return { key, check };\n}\n\nfunction refuseUnderCi() {\n  for (const marker of CI_MARKERS) {\n    if (process.env[marker] && !/^(0|false|no|off)$/i.test(process.env[marker])) {\n      throw new Error(`refusing to run with a secret under CI (${marker} is set); publish from the founder's machine`);\n    }\n  }\n}\n\nfunction sqlLiteral(value) {\n  if (value === null || value === undefined) return \"null\";\n  return `'${String(value).replace(/'/g, \"''\")}'`;\n}\n","sourceCodeStart":389,"sourceCodeEnd":425,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/web/scripts/facts-publish.mjs#L389-L425","documentation":"After finding the pinned active key, activePublishingKey calls verifyEnvelope(envelope, key.publicKey) and refuses publication when the cryptographic check fails, surfacing verifyEnvelope's error list joined by \"; \". This means the Ed25519 signature, canonical payload encoding, or envelope fields did not validate against the pinned public key.","triggerScenarios":"Calling activePublishingKey with an envelope whose payload was modified after signing, signed with a different private key than the pinned public key, with a corrupted payload_b64/signature, or with fields failing verifyEnvelope's structural checks (the specific reasons appear in check.errors).","commonSituations":"The payload JSON was regenerated (timestamps changed) without re-signing; the envelope was built with a dev key but published against production keys; base64 payloads were mangled by copy/paste or line wrapping.","solutions":["Read the check.errors list in the message to identify the exact failing verification (signature mismatch, bad encoding, missing field) and fix that specifically","Re-sign the current payload with the private key corresponding to the pinned active key_id, then retry with the fresh envelope","Verify the envelope bytes were not altered between signing and publishing (no editor formatting, re-encoding, or newline changes to payload_b64/signature)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const check = verifyEnvelope(envelope, pinnedPublicKey);\nif (!check.ok) {\n  console.error(\"envelope will be rejected:\", check.errors);\n  throw new Error(\"re-sign the current payload with the pinned key before publishing\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  await activePublishingKey(envelope, keys);\n} catch (err) {\n  if (err.message.startsWith(\"envelope does not verify:\")) {\n    console.error(\"Signature/payload verification failed:\", err.message.slice(\"envelope does not verify: \".length));\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Never modify payload fields after signing; regenerate the signature whenever the payload changes","Verify envelopes locally with verifyEnvelope before attempting publication","Ensure payload_b64/signature survive transport unchanged (no line wrapping, whitespace edits, or re-encoding)"],"tags":["cryptography","signature-verification","ed25519"],"backgroundTag":"checksum-mismatch","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}