fix(emails): BCC scrape-alert recipients — never a shared cross-tenant To: line

Merged
SW
3mo ago
+59-1

Summary

The "{artist} has new posts on Instagram" alert resolved every watcher of a social across all customer accounts into a single visible To: line — live evidence on the tracking issue shows a customer manager, an internal account, and a label contact (sam.palm@wmg.com) all mutually visible on one send. This PR hard-codes the privacy boundary: to is always our own from-address (Resend requires non-empty to), all recipients ride bcc.

Tracking issue: recoupable/chat#1855 (PR #1 of 6 — ships first and alone; nothing gates it).

What changed

  • lib/apify/sendApifyWebhookEmail.ts: to: [RECOUP_FROM_EMAIL] + bcc: emails (the Resend wrapper already passes bcc through natively — no wrapper change).
  • lib/apify/__tests__/sendApifyWebhookEmail.test.ts (new): asserts recipients land in bcc, and a guard-rail test that to/cc never contain more than our own address regardless of recipient count — so a future platform copy-paste can't reintroduce the leak.

Tests

RED→GREEN: 2 new assertions failed against the old implementation (to: emails), pass after (3/3). eslint clean.

🤖 Generated with Claude Code


Summary by cubic

Fixes a privacy leak in Instagram scrape-alert emails by moving all recipients to BCC and setting To to our own sender address. Prevents cross-tenant addresses from being visible to each other (recoupable/chat#1855).

  • Bug Fixes
    • Update sendApifyWebhookEmail to use to: [RECOUP_FROM_EMAIL] and bcc: emails.
    • Add tests enforcing BCC-only recipients, to/cc limited to our address, and no send when recipient list is empty.