{"record":{"id":"b80156224ab1b6f7","repo":"Hmbown/CodeWhale","slug":"result-failures-join-n","errorCode":null,"errorMessage":"${result.failures.join(\"\\n  - \")}","messagePattern":"\\$\\{result\\.failures\\.join\\(\"\\\\n  - \"\\)\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/scripts/check-cloud-facts.mjs","lineNumber":57,"sourceCode":"  if (source.release?.latest !== latest.version) failures.push(\"stable.json release.latest differs from latest-published-release.json\");\n  if (source.release?.release_url && source.release.release_url !== latest.url) failures.push(\"stable.json release.release_url differs from latest-published-release.json\");\n  // An explicit empty table is valid and inert; parse failures are never empty.\n  const rustKeys = parseRustKeys(text(resolve(REPO_ROOT, \"crates/config/src/cloud_facts/keys.rs\")));\n  const tsKeys = parseTsKeys(text(resolve(WEB_ROOT, \"lib/cloud-facts/keys.ts\")));\n  if (JSON.stringify(rustKeys) !== JSON.stringify(tsKeys)) failures.push(\"Rust and web pinned key tables diverge\");\n  const testOnlyPub = text(resolve(REPO_ROOT, \"docs/cloud-facts/fixtures/test-only.pub\")).trim();\n  for (const name of [\"envelope-stable-v7.json\", \"envelope-future-only-v8.json\"]) {\n    const result = verifyEnvelope(json(resolve(REPO_ROOT, \"docs/cloud-facts/fixtures\", name)), testOnlyPub);\n    if (!result.ok) failures.push(`fixture ${name}: ${result.errors.join(\"; \")}`);\n  }\n  if ([...rustKeys, ...tsKeys].some((key) => key.publicKey === testOnlyPub || key.keyId === \"cwf-test-only\")) failures.push(\"TEST-ONLY keys must never be production trust anchors\");\n  return { failures, factsVersion: source.facts_version, activeKeys: tsKeys.filter((key) => key.status === \"active\").length };\n}\n\nif (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {\n  try {\n    const result = checkCloudFacts();\n    if (result.failures.length) throw new Error(result.failures.join(\"\\n  - \"));\n    console.log(`check-cloud-facts: OK (facts_version=${result.factsVersion}, ${result.activeKeys} active production keys)`);\n  } catch (error) {\n    console.error(`check-cloud-facts: FAIL\\n  - ${error.message}`);\n    process.exitCode = 1;\n  }\n}\n","sourceCodeStart":39,"sourceCodeEnd":64,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/web/scripts/check-cloud-facts.mjs#L39-L64","documentation":"The check-cloud-facts CLI entry point throws when checkCloudFacts() returns a non-empty failures array, joining all cross-check failures (facts version, key sets, active key counts between the web facts and the Rust/TS sources) into one multi-line message. The message is dynamic: it lists every concrete mismatch found.","triggerScenarios":"Running the script when the deployed/web facts JSON disagrees with source code: a trusted key was rotated in Rust but not in the facts JSON, facts_version was bumped inconsistently, or active-key counts differ.","commonSituations":"A key rotation PR updated one side only; facts JSON regenerated from a stale branch; CI catching drift between web and native key material before deploy.","solutions":["Read each `- ` bullet in the thrown message; it names the exact mismatch.","Regenerate or hand-update the facts JSON so keys, versions, and counts match the Rust/TS sources.","If a key was rotated, update BOTH the Rust TRUSTED_KEYS table and the web facts in the same commit.","Re-run the script until it prints `check-cloud-facts: OK`."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before running, diff facts against sources yourself:\n// node web/scripts/check-cloud-facts.mjs && echo ready","typeGuard":null,"tryCatchPattern":"try { const r = checkCloudFacts(); if (r.failures.length) console.error(\"mismatches:\\n  - \" + r.failures.join(\"\\n  - \")); } catch (e) { console.error(e.message); }","preventionTips":["Rotate keys in Rust table, TS sources, and facts JSON in one commit.","Bump facts_version consistently.","Run check-cloud-facts locally before pushing.","Regenerate facts JSON from the same branch as the code change."],"tags":["consistency-check","security","build-check","crypto-keys"],"backgroundTag":"schema-validation-failed","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"}