feat(emails): log every POST /api/emails attempt (email_send_log, 7-day observability)
What
Records every POST /api/emails attempt — sent, send_failed, rejected (empty/malformed) — in email_send_log, so a send is debuggable days later without the ephemeral agent sandbox.
Why
The empty footer-only emails reached customers and we could not recover what the API received (malformed bodies swallowed, route logged nothing, sandbox ephemeral). This is the instrument that makes the rest of the issue measurable.
Change
lib/emails/logEmailAttempt.ts— best-effort writer (never throws), inserts the 5 settable columns:account_id, chat_id, status, resend_id, raw_body. Stores the full raw body (no truncation).lib/emails/sendEmailHandler.ts— captures the raw body viarequest.clone()(validation still reads the original) and logs on every outcome; rejected attempts keep the raw body, so a malformed/empty send is visible after the fact.lib/supabase/email_send_log/insertEmailSendLog.ts— typed insert.types/database.types.ts— regenerated from the live schema (supabase gen typesequivalent); adds the 7-columnemail_send_log(id, created_at, account_id, chat_id, status, resend_id, raw_body).
The table + RLS ship in the database repo — #37 (create) and #38 (drop error, enable RLS), both merged. Schema reviewed down to the minimal 7 columns (KISS).
Tests
logEmailAttempt unit (fields + full-body + swallow-errors) and sendEmailHandler (sent/rejected/send_failed log calls). Full lib/emails suite: 149 passing. tsc + lint clean.
Part of recoupable/chat#1829. Base main.
🤖 Generated with Claude Code