Sign-up attribution + Cloudflare Turnstile bot protection
- signup_attribution (migration nifty_chameleon): first-visit referrer, landing path, utm_* (client, via
x-bp-attribution from sessionStorage/bp_attr cookie) + request Referer, CF-Connecting-IP, cf.country/asn/
asOrganization, user agent; sanitized and length-capped (src/lib/attribution.ts); deleted with the account.
- middleware/03-signup.ts: Turnstile siteverify before Better Auth creates the account (400 CAPTCHA_REQUIRED /
403 CAPTCHA_INVALID / 503 unavailable); sign-in asks for a check after 3 failures per email in 15 min
(auth_failures). Enabled only when TURNSTILE_SITE_KEY + TURNSTILE_SECRET_KEY are set; optional
TURNSTILE_SMOKE_BYPASS for @example.com smoke sign-ups. GET /v1/signup-config serves the site key.
- Web: managed widget (explicit render, flexible size, app theme) on sign-up and on sign-in when asked.
- Tests: test/attribution.test.ts (10), scripts/signup.mjs e2e (added to CI e2e with Turnstile test keys);
scripted sign-ups send the dummy test token. DESIGN.md.