Client SaaS
TypeScript
Pull Request Opened
PR #196 opened: feat: capture Resend email delivery events (PR8)
Logs email delivery events from Resend so we can see what was sent and how it landed — the analytics layer for the newsletter + drip.
What
POST /api/resend/webhook— verified with the officialResend\WebhookSignature(Svix), not hand-rolled crypto. Records events for our own sending domain only (config services.resend.tracked_domain); other domains are acked (200, no retry) + ignored.email_eventstable +EmailEventmodel — storesdelivered / opened / clicked / bounced / complained, retaining the full payload (click/bounce metadata +tags/broadcast_idfor future campaign segmentation).- Admin aggregate page
/admin/emails— counts by type (last 30 days) + recent events table. New "Emails" nav item. - Per-user email events on the admin user screen — backfills the comms-log gap flagged in PR4a.
Fixtures — verified against the docs
tests/Fixtures/resend/*.json match the real Resend payload shape. I checked the live Resend docs: clicked + bounced exact (incl. broadcast_id, template_id, tags, click.{ipAddress,link,timestamp,userAgent}, bounce.{message,subType,type}); delivered/opened/complained share the confirmed common data structure. (Initial drafts were from memory and missing broadcast_id/template_id/tags — corrected.)
Notes
- Opens are unreliable post-Apple-Mail-Privacy-Protection (inflated) — the UI says so; treat clicks as the real signal.
- The
resend-laravelpackage auto-registers an unverified/resend/webhookroute that nothing listens to (harmless). Ours is the verified one your Resend webhook points at (/api/resend/webhook). RESEND_WEBHOOK_SIGNING_SECRETalready set on prod (Coolify). Activates on deploy.
Tests (10 new)
Real-fixture round-trip for all 5 event types, invalid-signature → 401, other-domain dropped, admin aggregate counts, non-admin forbidden.
+705
additions
-0
deletions
21
files changed