{"record":{"id":"c93df39ede029a2c","repo":"affaan-m/ECC","slug":"openai-transfer-consent-is-required","errorCode":null,"errorMessage":"OpenAI transfer consent is required","messagePattern":"OpenAI transfer consent is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/council-multi-model/scripts/review-with-codex.js","lineNumber":186,"sourceCode":"  return versionMatch[1];\n}\n\nfunction buildEnvironment(sourceEnv = process.env) {\n  const allowed = [\n    'PATH', 'HOME', 'USERPROFILE', 'CODEX_HOME',\n    'TMPDIR', 'TMP', 'TEMP', 'SystemRoot', 'ComSpec', 'PATHEXT',\n  ];\n  return Object.fromEntries(\n    allowed.filter((name) => sourceEnv[name]).map((name) => [name, sourceEnv[name]])\n  );\n}\n\nfunction runReview(prompt, options, dependencies = {}) {\n  if (!prompt.trim()) throw new Error('review packet is empty');\n  if (Buffer.byteLength(prompt, 'utf8') > MAX_PROMPT_BYTES) {\n    throw new Error(`review packet exceeds ${MAX_PROMPT_BYTES} bytes`);\n  }\n  if (!options.consent) throw new Error('OpenAI transfer consent is required');\n  if (options.timeoutMs < 10_000 || options.timeoutMs > MAX_TIMEOUT_MS) {\n    throw new Error('timeout is outside the 10-120 second safety range');\n  }\n\n  const spawn = dependencies.spawnSync || spawnSync;\n  const environment = buildEnvironment(dependencies.env || process.env);\n  const verifySupport = dependencies.verifyToollessSupport || verifyToollessSupport;\n  verifySupport({ spawnSync: spawn, env: environment });\n  const makeTemp = dependencies.mkdtempSync || fs.mkdtempSync;\n  const readFile = dependencies.readFileSync || fs.readFileSync;\n  const remove = dependencies.rmSync || fs.rmSync;\n  const tempDir = makeTemp(path.join(os.tmpdir(), 'ecc-council-review-'));\n  const outputFile = path.join(tempDir, 'last-message.txt');\n\n  try {\n    const result = spawn('codex', buildCodexArgs(tempDir, outputFile), {\n      cwd: tempDir,\n      env: environment,","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/skills/council-multi-model/scripts/review-with-codex.js#L168-L204","documentation":"Because runReview transmits the prompt to OpenAI via Codex, the caller must affirmatively opt in by setting options.consent to a truthy value. The consent flag is a compliance guard ensuring no packet leaves the host without an explicit acknowledgment. Without it the function aborts at line 186 before any environment is built or subprocess spawned.","triggerScenarios":"Calling runReview(prompt, options) where options.consent is falsy or the key is absent. Programmatically building an options object without forwarding consent, or calling runReview directly in tests bypassing parseArgs (the CLI's --consent-to-openai flag is checked separately in parseArgs).","commonSituations":"Programmatic integration that forgot to set consent; tests that hand-build options; a wrapper that strips unknown keys before forwarding to runReview.","solutions":["Set options.consent = true (or pass --consent-to-openai on the CLI) before invoking.","If calling programmatically, derive consent from an explicit user action and fail loudly if it is missing rather than defaulting.","Audit wrapper code that constructs the options object to ensure consent is forwarded."],"exampleFix":"// before\nconst review = runReview(packet, { timeoutMs: 60000, hostProvider: 'openai' });\n\n// after\nconst review = runReview(packet, {\n  consent: true,\n  timeoutMs: 60000,\n  hostProvider: 'openai',\n});","handlingStrategy":"validation","validationCode":"function assertConsent(options) {\n  if (!options || options.consent !== true) {\n    throw new Error('Refusing to run review without explicit OpenAI transfer consent.');\n  }\n}\nassertConsent(options);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat consent as an explicit boolean, not a default; never infer it from the presence of other options.","Gate consent behind a real user action (CLI flag, config toggle) and fail loudly when absent.","In wrappers, forward the full options object rather than cherry-picking keys, so consent is not dropped."],"tags":["consent","compliance","validation","codex"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}