feat(migrations): create email_send_log table

Merged
SW
4mo ago
+30-0

What

Adds email_send_log — a durable record of every POST /api/emails attempt (sent / send_failed / rejected), so a send is debuggable several days back without the ephemeral agent sandbox.

Why

Empty footer-only "Message from Recoup" emails reached customers and we could not recover what the API received (malformed bodies swallowed, route logged nothing, sandbox ephemeral). This table captures it.

Design (KISS — reviewed twice)

Append-only; loose ids, no FKs (like error_logs). 7 columns:

id, created_at, account_id, chat_id, status, resend_id. raw_body (full — bounded by the platform request-size limit), error + (created_at DESC) / (account_id) indexes.

  • chat_id only (TEXT, matching chats.id). chats.session_id reaches the session and sessions.account_id the account, so a separate session_id column would be redundant — and session_id isn't in the /api/emails contract anyway, so dropping it avoids extending that contract.
  • account_id denormalized (free at the API; the main query dimension).
  • Dropped earlier to_count / subject / html_length / text_length (derivable from raw_body).
  • Resend delivery lifecycle (delivered/bounced/opened) is a deliberate future concern — a separate email_events table keyed off resend_id, not more columns here. (A retention/purge job for raw_body (the real size/PII control, since we keep the full body now) and a chat_id index for the verify-the-send lookup are follow-ups alongside that work.)

Pairs with

  • recoupable/api#731 — logEmailAttempt writes this table. This migration lands first; then #731's code is reconciled to match (chat_id, drop the 4 fields) before it merges.

Part of recoupable/chat#1829.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Email send attempts are now recorded with delivery status, sender, chat reference, timestamps, and related message details.
    • Added faster lookup support for recent entries and sender-based views.