{"record":{"id":"fdafa40881826a62","repo":"Hmbown/CodeWhale","slug":"public-key-is-only-for-offline-verify-emit-sql-publication","errorCode":null,"errorMessage":"--public-key is only for offline verify/emit-sql; publication requires the active pinned table","messagePattern":"--public-key is only for offline verify/emit-sql; publication requires the active pinned table","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/scripts/facts-publish.mjs","lineNumber":572,"sourceCode":"    if (!pub) {\n      const trusted = loadTrustedKeysFromRepo().get(envelope.key_id);\n      if (!trusted || trusted.status !== \"active\") throw new Error(\"key is not pinned and active; use --public-key only for explicit offline verification\");\n      pub = trusted.publicKey;\n    }\n    const result = verifyEnvelope(envelope, String(pub));\n    console.log(JSON.stringify({ ok: result.ok, errors: result.errors, channel: envelope.channel, facts_version: envelope.facts_version, key_id: envelope.key_id, sha256: result.sha256 ?? null }, null, 2));\n    return result.ok ? 0 : 1;\n  }\n  if (cmd === \"emit-sql\") {\n    const envelope = readJson(resolve(String(positional[1] ?? \"\")));\n    let pub = flags[\"public-key\"];\n    if (!pub) pub = activePublishingKey(envelope, [...loadTrustedKeysFromRepo().values()]).key.publicKey;\n    process.stdout.write(emitSql(envelope, { publishedBy: String(flags[\"published-by\"] ?? \"\"), publicKeyB64: pub ? String(pub) : undefined, notes: String(flags.notes ?? \"\") }));\n    return 0;\n  }\n  if (cmd === \"publish\") {\n    const envelope = readJson(resolve(String(positional[1] ?? \"\")));\n    if (flags[\"public-key\"] !== undefined) throw new Error(\"--public-key is only for offline verify/emit-sql; publication requires the active pinned table\");\n    const { key, check } = activePublishingKey(envelope, [...loadTrustedKeysFromRepo().values()]);\n    const pub = key.publicKey;\n    const row = {\n      facts_version: envelope.facts_version,\n      schema_version: envelope.schema_version,\n      envelope_version: envelope.envelope,\n      applies_to: envelope.applies_to,\n      key_id: envelope.key_id,\n      payload_b64: envelope.payload_b64,\n      sig_b64: envelope.sig_b64,\n      sigs: envelope.sigs ?? [],\n      payload: check.payload,\n      published_at: envelope.published_at,\n      not_after: check.payload.not_after ?? null,\n      published_by: String(flags[\"published-by\"] ?? \"\"),\n      notes: String(flags.notes ?? \"\"),\n    };\n    if (flags[\"dry-run\"]) {","sourceCodeStart":554,"sourceCodeEnd":590,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/web/scripts/facts-publish.mjs#L554-L590","documentation":"The publish subcommand refuses to accept an ad-hoc --public-key. Publication must use the active key resolved from the repo-pinned trust table (activePublishingKey), so passing --public-key with publish throws immediately to prevent uploading a key nobody has pinned. Only verify and emit-sql accept --public-key (offline use).","triggerScenarios":"Running `publish envelope.json --public-key <key>`; scripts that generically pass --public-key to every subcommand; copy-pasting an offline-verify command line and swapping the verb to publish.","commonSituations":"Automating publication from a rotation flow that still carries the offline --public-key flag; misunderstanding which subcommands accept the flag; trying to publish under a key that was never pinned as active in the repo.","solutions":["Remove --public-key from the publish command line","Ensure the signing key is pinned with status \"active\" in the repo trust table so activePublishingKey resolves it","Use --dry-run to confirm the resolved key before publishing","If you truly need a different key, pin it first rather than passing it inline"],"exampleFix":"// before\nnode facts-publish.mjs publish envelope.json --public-key ~/cwf.pub\n// after\nnode facts-publish.mjs publish envelope.json --dry-run","handlingStrategy":"validation","validationCode":"if (cmd === 'publish' && flags['public-key'] !== undefined) throw new Error('drop --public-key: publish uses the pinned active key');","typeGuard":null,"tryCatchPattern":"try {\n  await run(['publish', envelopePath]);\n} catch (e) {\n  if (e.message.includes('only for offline verify/emit-sql')) console.error('Remove --public-key for publish; pin the key in the repo table instead');\n  throw e;\n}","preventionTips":["Keep publish invocations minimal: no key overrides","Use --dry-run to inspect the resolved publishing key","Pin rotation keys in the repo before publishing under them"],"tags":["cli","signing","trust","mutually-exclusive"],"backgroundTag":"mutually-exclusive-flags","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"}