{"record":{"id":"a990e0c1fb8f2868","repo":"koala73/worldmonitor","slug":"createprolaunchbroadcast-pro-launch-physical-add","errorCode":null,"errorMessage":"[createProLaunchBroadcast] PRO_LAUNCH_PHYSICAL_ADDRESS is still a placeholder (\"${PRO_LAUNCH_PHYSICAL_ADDRESS}\"). Set the real CAN-SPAM postal address in convex/broadcast/proLaunchEmailContent.ts before sending.","messagePattern":"\\[createProLaunchBroadcast\\] PRO_LAUNCH_PHYSICAL_ADDRESS is still a placeholder \\(\"(.+?)\"\\)\\. Set the real CAN-SPAM postal address in convex/broadcast/proLaunchEmailContent\\.ts before sending\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"convex/broadcast/sendBroadcast.ts","lineNumber":81,"sourceCode":"    nameSuffix: v.optional(v.string()),\n  },\n  handler: async (_ctx, { segmentId, nameSuffix }) => {\n    const apiKey = process.env.RESEND_API_KEY;\n    if (!apiKey) {\n      throw new Error(\"[createProLaunchBroadcast] RESEND_API_KEY not set\");\n    }\n\n    // Hard-gate: refuse to ship the placeholder physical address.\n    // CAN-SPAM requires a valid postal address in every commercial\n    // email footer; sending the literal \"physical address TBD\" string\n    // is non-compliant and embarrassing. Edit\n    // `PRO_LAUNCH_PHYSICAL_ADDRESS` in proLaunchEmailContent.ts to the\n    // real postal address before invoking this action.\n    if (\n      PRO_LAUNCH_PHYSICAL_ADDRESS.includes(\"TBD\") ||\n      PRO_LAUNCH_PHYSICAL_ADDRESS.includes(\"placeholder\")\n    ) {\n      throw new Error(\n        `[createProLaunchBroadcast] PRO_LAUNCH_PHYSICAL_ADDRESS is still a placeholder (\"${PRO_LAUNCH_PHYSICAL_ADDRESS}\"). ` +\n          \"Set the real CAN-SPAM postal address in convex/broadcast/proLaunchEmailContent.ts before sending.\",\n      );\n    }\n\n    const name =\n      nameSuffix && nameSuffix.length > 0\n        ? `PRO Launch — ${nameSuffix}`\n        : `PRO Launch — ${new Date().toISOString().slice(0, 10)}`;\n\n    const res = await fetch(`${RESEND_API_BASE}/broadcasts`, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        Authorization: `Bearer ${apiKey}`,\n        \"User-Agent\": USER_AGENT,\n      },\n      body: JSON.stringify({","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/koala73/worldmonitor/blob/ffec79ac339946fd2d24e85845da5755dcaa534b/convex/broadcast/sendBroadcast.ts#L63-L99","documentation":"Hard-gate thrown by createProLaunchBroadcast when PRO_LAUNCH_PHYSICAL_ADDRESS (imported from proLaunchEmailContent.ts) still contains the substring 'TBD' or 'placeholder'. The guard exists because CAN-SPAM requires a valid postal address in every commercial email footer; shipping the literal placeholder string would be non-compliant. It is a deliberate pre-flight check that fires before any Resend API call is made.","triggerScenarios":"Invoking createProLaunchBroadcast via `npx convex run broadcast/sendBroadcast:createProLaunchBroadcast '{\"segmentId\":\"seg_xxx\"}'` while PRO_LAUNCH_PHYSICAL_ADDRESS in convex/broadcast/proLaunchEmailContent.ts is set to a value containing 'TBD' or 'placeholder' (e.g. 'physical address TBD'). Also fires if a future edit reintroduces either substring.","commonSituations":"A developer clones the repo and the address constant is still the placeholder default. An operator reverts proLaunchEmailContent.ts during a merge conflict resolution and the placeholder comes back. The address was intentionally set to a temporary string during content drafting and never replaced before the send window.","solutions":["Edit PRO_LAUNCH_PHYSICAL_ADDRESS in convex/broadcast/proLaunchEmailContent.ts to the real company postal address (currently 'WorldMonitor FZ LLC, Dubai - United Arab Emirates' — confirm it is still correct).","Ensure the new value contains neither 'TBD' nor 'placeholder' as a substring (the check is case-sensitive on those exact lowercase strings).","Re-run createProLaunchBroadcast after redeploying the Convex function so the updated constant is loaded."],"exampleFix":"// before\nexport const PRO_LAUNCH_PHYSICAL_ADDRESS = \"physical address TBD\";\n// after\nexport const PRO_LAUNCH_PHYSICAL_ADDRESS = \"WorldMonitor FZ LLC, Dubai - United Arab Emirates\";","handlingStrategy":"validation","validationCode":"import { PRO_LAUNCH_PHYSICAL_ADDRESS } from \"./proLaunchEmailContent\";\n\nfunction assertPhysicalAddressReady(): void {\n  if (PRO_LAUNCH_PHYSICAL_ADDRESS.includes(\"TBD\") || PRO_LAUNCH_PHYSICAL_ADDRESS.includes(\"placeholder\")) {\n    throw new Error(\"PRO_LAUNCH_PHYSICAL_ADDRESS is a placeholder — set the real CAN-SPAM address first.\");\n  }\n}\n// call before createProLaunchBroadcast","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat proLaunchEmailContent.ts as a locked content file — change it only in a dedicated PR, not inline with operational work.","Add a CI lint that greps PRO_LAUNCH_PHYSICAL_ADDRESS for 'TBD'/'placeholder' and fails the build.","Run createProLaunchBroadcast in a dry-run/staging Convex deployment before production."],"tags":["compliance","can-spam","email-broadcast","config","convex"],"backgroundTag":null,"analyzedSha":"ffec79ac339946fd2d24e85845da5755dcaa534b","analyzedAt":"2026-08-12T11:24:56.012Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}