Corporate mail scanners (Microsoft Defender SafeLinks) follow links in
auth emails and burn the one-shot recovery token before the user sees
the mail (#1099, first hit: Deepgrid 2026-07-21, verify from an Azure
IP 23s after send).
/reset-password now has three entry modes:
- set-password: recovery session exists (legacy /auth/callback links
keep working unchanged)
- confirm-link: the email link carries ?token_hash= and verification
runs ONLY on an explicit button click; scanners render pages but do
not click buttons, so the token survives scanning
- enter-code: email + 6-digit {{ .Token }} code typed manually, the
fallback when no link works at all
The Supabase recovery email template switches to
{{ .SiteURL }}/reset-password?token_hash={{ .TokenHash }} + {{ .Token }}
AFTER this deploys (template content in the PR); the link then never
touches gotrue's GET /verify endpoint, leaving nothing to detonate.
Fixes#1099.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>