{"record":{"id":"1c50978c6918f343","repo":"JuliusBrussee/caveman","slug":"usage-sign-binary-checksums-mjs-checksums-txt","errorCode":null,"errorMessage":"usage: sign-binary-checksums.mjs <checksums.txt> <output.keysig> <public-key.pem>","messagePattern":"usage: sign-binary-checksums\\.mjs <checksums\\.txt> <output\\.keysig> <public-key\\.pem>","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/sign-binary-checksums.mjs","lineNumber":43,"sourceCode":"    bundle?.messageSignature?.messageDigest?.digest === digest &&\n    verify(\n      \"sha256\",\n      checksums,\n      createPublicKey(publicKeyPEM),\n      Buffer.from(bundle?.messageSignature?.signature ?? \"\", \"base64\"),\n    );\n}\n\nfunction normalizePublicKey(value) {\n  return createPublicKey(value).export({ type: \"spki\", format: \"pem\" }).toString();\n}\n\nif (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {\n  try {\n    const [checksumsPath, outputPath, publicKeyPath] = process.argv.slice(2);\n    const privateKeyPEM = process.env.CAVEMAN_BINARY_SIGNING_PRIVATE_KEY_PEM;\n    if (!checksumsPath || !outputPath || !publicKeyPath) {\n      throw new Error(\"usage: sign-binary-checksums.mjs <checksums.txt> <output.keysig> <public-key.pem>\");\n    }\n    if (!privateKeyPEM) throw new Error(\"CAVEMAN_BINARY_SIGNING_PRIVATE_KEY_PEM is required\");\n    const checksums = readFileSync(checksumsPath);\n    const publicKeyPEM = readFileSync(publicKeyPath, \"utf8\");\n    if (normalizePublicKey(privateKeyPEM) !== normalizePublicKey(publicKeyPEM)) {\n      throw new Error(\"binary signing private key does not match committed public key\");\n    }\n    const bundle = checksumSignatureBundle(checksums, privateKeyPEM);\n    if (!verifyChecksumSignatureBundle(checksums, bundle, publicKeyPEM)) {\n      throw new Error(\"generated checksum signature failed local verification\");\n    }\n    writeFileSync(outputPath, `${JSON.stringify(bundle)}\\n`, { mode: 0o600 });\n  } catch (error) {\n    process.stderr.write(`${error.message}\\n`);\n    process.exit(1);\n  }\n}\n","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/scripts/sign-binary-checksums.mjs#L25-L61","documentation":"Usage error from the CLI entry block of scripts/sign-binary-checksums.mjs when the script is run directly without all three positional arguments: <checksums.txt> <output.keysig> <public-key.pem>. It fires before anything is read or signed, and the catch handler prints the message to stderr and exits 1.","triggerScenarios":"Running `node scripts/sign-binary-checksums.mjs`, or supplying only one or two of the three paths (e.g. forgetting the public-key.pem argument that lets the script self-verify against the committed key).","commonSituations":"First-time release signing; a wrapper script or CI job dropping an argument; copy-pasting an outdated command from docs after the CLI changed.","solutions":["Invoke with all three arguments: `node scripts/sign-binary-checksums.mjs <checksums.txt> <output.keysig> <public-key.pem>`.","Check your release runbook/wrapper for a missing third argument — the committed public key path is mandatory.","Confirm the exit is the usage path (message equals the usage string) before debugging anything else."],"exampleFix":"# before\nnode scripts/sign-binary-checksums.mjs dist/checksums.txt dist/checksums.keysig\n# after\nnode scripts/sign-binary-checksums.mjs dist/checksums.txt dist/checksums.keysig keys/binary-public.pem","handlingStrategy":"validation","validationCode":"const args = process.argv.slice(2);\nif (args.length !== 3) {\n  console.error(\"usage: sign-binary-checksums.mjs <checksums.txt> <output.keysig> <public-key.pem>\");\n  process.exit(2);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wrap release signing in a make target or script that hardcodes the three paths.","Treat any usage-string stderr output as an invocation bug, not a signing failure."],"tags":["cli","usage","signing","release"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}