Domain email and MFA
Why Gmail cannot be the From address
Resend only sends from a domain you verify. yonahmartinez30@gmail.com can still be where a human reads mail. It cannot be EMAIL_FROM_ADDRESS.
Same Resend API key, three jobs
- Send. Verify YOUR-DOMAIN in Resend. Set
EMAIL_FROM_ADDRESS=Invince <hello@YOUR-DOMAIN>andRESEND_API_KEY. Signup confirmation, Watch, invites, and error mail use this. - Public support address. Set
NEXT_PUBLIC_SUPPORT_EMAIL=support@YOUR-DOMAINandEMAIL_SUPPORT_ADDRESSto the same value. In-app Support tickets go there. - Receive. In Resend, enable receiving on that domain, add the MX record they show, create a webhook for
email.receivedpointing athttps://YOUR-DOMAIN/api/webhooks/resend, and put the signing secret inRESEND_WEBHOOK_SECRET. Optional:EMAIL_SUPPORT_FORWARDis your Gmail. The webhook stores the message and forwards it from hello@YOUR-DOMAIN with Reply-To set to the customer.
If YOUR-DOMAIN already has MX records for a real inbox, use a subdomain such as mail.YOUR-DOMAIN so you do not steal existing mail.
Confirm signup mail
A first confirmation from Invince <noreply@YOUR-DOMAIN> with subject Confirm your email address and a “Confirm email address” link is Supabase’s default SMTP template. That often works once, then Auth rate-limits later sends.
Do not leave production on that path. Point Authentication → Hooks → Send Email at https://YOUR-DOMAIN/api/auth/send-email, put the hook secret in SEND_EMAIL_HOOK_SECRET (starts with v1,whsec_), and redeploy Cloud Run. Site URL must be https://YOUR-DOMAIN, not localhost.
Custom SMTP (smtp.resend.com) is an alternative, but it still sits behind Supabase’s Auth send limits.
MFA login verify
- Profile → Two-factor authentication → scan the QR → type the 6-digit code → Verify.
- Save the backup codes shown once.
- Next password sign-in goes to
/mfa-challenge. Enter the 6-digit code. If you lost the app, use a backup code. That turns the authenticator off so you can enroll again. - After you enroll, workspace pages and Watch require that extra step (aal2). Ingest keys, webhooks, and public Check do not. If the assurance API is down, Invince fails open so you are not locked out.
Backup codes need CREDENTIAL_ENCRYPTION_KEY and the SQL in supabase/manual/apply_support_inbound_and_mfa_backup.sql.
On-call paging
Workspace Settings stores on-call emails and an optional Slack Incoming Webhook. When an alert opens an incident, those channels fire, then repeat on the 15-minute cron until someone acknowledges or the max page count is reached. Email still needs Resend. This is not phone, SMS, or a PagerDuty schedule.