{"record":{"id":"bf56f2259f3ae28c","repo":"Hmbown/CodeWhale","slug":"the-release-is-missing-its-bundled-runtime","errorCode":null,"errorMessage":"The release is missing its bundled runtime.","messagePattern":"The release is missing its bundled runtime\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"crates/tui/plugins/computer-use/app/install-macos.mjs","lineNumber":45,"sourceCode":"    return { backup };\n  } finally { fs.rmSync(staging, { recursive: true, force: true }); }\n}\n\nexport function verifySignature(bundle) {\n  const result=spawnSync(\"codesign\",[\"--verify\",\"--deep\",\"--strict\",bundle],{encoding:\"utf8\"});\n  if(result.status!==0) throw new Error(`The app signature did not verify: ${result.stderr?.trim() ?? \"codesign unavailable\"}`);\n}\n\nexport function verifyReleaseBundle(bundle) {\n  verifySignature(bundle);\n  const requirement='=anchor apple generic and identifier \"net.codewhale.computer-use\" and certificate leaf[subject.OU] = \"5RDNSHA5TY\"';\n  for(const [command,args] of [[\"/usr/bin/codesign\",[\"--verify\",\"--strict\",\"-R\",requirement,bundle]],[\"/usr/sbin/spctl\",[\"--assess\",\"--type\",\"execute\",\"--verbose=2\",bundle]]]) {\n    const result=spawnSync(command,args,{encoding:\"utf8\"});\n    // Gatekeeper ships with macOS. Requiring its notarized source also rejects\n    // local allow-list overrides; consumer Macs do not need Xcode's stapler.\n    if(result.status!==0 || (command.endsWith(\"/spctl\") && !/^source=Notarized Developer ID\\r?$/m.test(result.stderr))) throw new Error(\"The update is not a valid notarized Codewhale release. Your current app has been kept.\");\n  }\n  if(!fs.existsSync(path.join(bundle,\"Contents\",\"MacOS\",\"node\"))) throw new Error(\"The release is missing its bundled runtime.\");\n}\n","sourceCodeStart":27,"sourceCodeEnd":47,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/app/install-macos.mjs#L27-L47","documentation":"After signature and notarization checks, verifyReleaseBundle confirms the bundle ships its bundled Node runtime at Contents/MacOS/node. A notarized but incomplete bundle — validly signed yet missing the runtime the daemon needs — is rejected so a half-published release can never replace a working install.","triggerScenarios":"Verifying a release bundle whose Contents/MacOS/node is absent: a packaging step skipped the runtime, an extraction dropped it, or a manually assembled bundle was signed without including node.","commonSituations":"Release packaging regression where the runtime copy step was removed or its path changed; a ZIP validation/extraction bug silently omitting an entry; someone rebuilt the bundle by hand and forgot the node binary.","solutions":["Rebuild the release bundle ensuring node is copied into Contents/MacOS before signing and notarization","Re-download the official release and re-verify (the current copy may be truncated)","Check validateReleaseZip/extraction logic if a local extraction dropped the file","Inspect the staged bundle with ls Contents/MacOS to confirm what is actually present"],"exampleFix":"// before (bundle staged without runtime)\ncode.verifyReleaseBundle(staged); // throws: missing bundled runtime\n// after\ncode.fs.mkdirSync(path.join(staged, \"Contents\", \"MacOS\"), { recursive: true });\ncode.fs.copyFileSync(path.join(runtimeDir, \"node\"), path.join(staged, \"Contents\", \"MacOS\", \"node\"));\ncode.verifyReleaseBundle(staged);","handlingStrategy":"validation","validationCode":"if (!fs.existsSync(path.join(bundle, \"Contents\", \"MacOS\", \"node\"))) {\n  throw new Error(\"bundle missing bundled node runtime\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  verifyReleaseBundle(bundle);\n} catch (e) {\n  if (e.message.includes(\"missing its bundled runtime\")) {\n    discardStagedBundle(bundle); // fail closed, keep current install\n  } else throw e;\n}","preventionTips":["Add a packaging CI step asserting Contents/MacOS/node exists before signing","Rebuild the bundle if any packaging step changes runtime paths","SHA-verify the downloaded archive before staging","Never hand-assemble release bundles; use the standard packer"],"tags":["macos","packaging","release-integrity","missing-file"],"backgroundTag":"missing-dependency","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}