{"record":{"id":"61a1793f52ea45e4","repo":"koala73/worldmonitor","slug":"company-monitoring-worker-unauthorized","errorCode":null,"errorMessage":"COMPANY_MONITORING_WORKER_UNAUTHORIZED","messagePattern":"COMPANY_MONITORING_WORKER_UNAUTHORIZED","errorType":"exception","errorClass":"ConvexError","httpStatus":null,"severity":"critical","filePath":"convex/companyMonitoring/orchestration.ts","lineNumber":211,"sourceCode":"async function timingSafeEqualStrings(left: string, right: string): Promise<boolean> {\n  const encoder = new TextEncoder();\n  const [leftDigest, rightDigest] = await Promise.all([\n    crypto.subtle.digest(\"SHA-256\", encoder.encode(left)),\n    crypto.subtle.digest(\"SHA-256\", encoder.encode(right)),\n  ]);\n  const leftBytes = new Uint8Array(leftDigest);\n  const rightBytes = new Uint8Array(rightDigest);\n  let mismatch = 0;\n  for (let index = 0; index < leftBytes.length; index += 1) {\n    mismatch |= leftBytes[index]! ^ rightBytes[index]!;\n  }\n  return mismatch === 0;\n}\n\nasync function requireWorkerSecret(secret: string): Promise<void> {\n  const expected = process.env.COMPANY_MONITORING_WORKER_SECRET ?? \"\";\n  if (!expected || !(await timingSafeEqualStrings(secret, expected))) {\n    throw new ConvexError(\"COMPANY_MONITORING_WORKER_UNAUTHORIZED\");\n  }\n}\n\nfunction providerRolloutEnabled(source: Source): boolean {\n  const flags: Record<Source, boolean> = {\n    exa: COMPANY_MONITORING_ROLLOUT_FLAGS.exaProvider,\n    x: COMPANY_MONITORING_ROLLOUT_FLAGS.xProvider,\n  };\n  return flags[source];\n}\n\nfunction enabledSources(): Source[] {\n  return ([\"exa\", \"x\"] as const).filter(providerRolloutEnabled);\n}\n\nfunction requireProviderClaimPolicy(\n  account: Doc<\"companyMonitoringAccounts\">,\n  source: Source,","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/koala73/worldmonitor/blob/ffec79ac339946fd2d24e85845da5755dcaa534b/convex/companyMonitoring/orchestration.ts#L193-L229","documentation":"Thrown by requireWorkerSecret when the provided worker secret does not match the COMPANY_MONITORING_WORKER_SECRET environment variable (compared with a timing-safe SHA-256 comparison), or when that environment variable is unset/empty. This gates all worker-facing mutations so only trusted workers holding the secret can claim work or finalize results.","triggerScenarios":"Calling a worker-gated mutation without the secret, with the wrong secret, or when COMPANY_MONITORING_WORKER_SECRET is not configured in the Convex deployment.","commonSituations":"Secret not deployed to the Convex environment; worker using a stale secret after rotation; secret omitted from local dev config; secret leaked/mis-typed.","solutions":["Set COMPANY_MONITORING_WORKER_SECRET in the Convex deployment environment to a strong shared value.","Configure the worker to send the same secret and rotate both ends together.","Verify the secret is present via the deployment dashboard (never log its value)."],"exampleFix":"// before — secret missing from Convex env, worker unauthorized\n\n// after\n# set in Convex deployment (do not commit the value)\nnpx convex env set COMPANY_MONITORING_WORKER_SECRET=<strong-random-secret>\n# then configure the worker with the identical secret","handlingStrategy":"validation","validationCode":"// ensure the env var is set and the worker sends the same secret\nif (!process.env.COMPANY_MONITORING_WORKER_SECRET) {\n  throw new Error(\"COMPANY_MONITORING_WORKER_SECRET not deployed\");\n}","typeGuard":null,"tryCatchPattern":"try { await workerMutation(...); }\ncatch (err) {\n  if (err instanceof ConvexError && err.message === \"COMPANY_MONITORING_WORKER_UNAUTHORIZED\") {\n    // halt worker and alert; do not retry with the same secret\n  } else throw err;\n}","preventionTips":["Deploy COMPANY_MONITORING_WORKER_SECRET in the Convex environment.","Rotate secret and worker config together.","Verify by exit code/response, never by printing the secret."],"tags":["convex","security","authentication","secrets","worker","company-monitoring"],"backgroundTag":null,"analyzedSha":"ffec79ac339946fd2d24e85845da5755dcaa534b","analyzedAt":"2026-08-12T11:24:56.012Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}