Bot and abuse protection
The first-party login surface is gated by a policy built on signals the edge attaches to every request — country, bot score, geolocation — plus an interactive challenge. The outcome is one of three actions.
| Action | Result |
|---|---|
allow | Proceed. |
challenge | A valid Turnstile token is required to continue. |
block | Refused outright with 403 login_blocked. |
What escalates
Section titled “What escalates”Country. Two configurable lists: countries that are blocked outright, and countries that must pass a challenge. Blocking wins over challenging.
Bot score. Where the zone has bot management, a score from 1 (definitely automated) to 99:
| Score | Action |
|---|---|
| < 10 | Block |
| 10–29 | Challenge |
| ≥ 30 | Allow |
Verified bots — declared, well-behaved crawlers — are exempt from scoring entirely, so a legitimate crawler is not treated as an attacker.
Challenges
Section titled “Challenges”A challenged request gets a 403 naming the challenge and the site key to render:
{ "error": "challenge_required", "challenge": "turnstile", "site_key": "0x4AAA…"}Retry the login call with the resulting token:
POST /login/email/start{ "email": "ada@acme.com", "turnstile_token": "…" }Tokens are verified server-side against the challenge provider, including the client IP.
Configure Turnstile before enabling any challenged country, or logins from those countries will fail in production.
Disposable email addresses
Section titled “Disposable email addresses”Throwaway-inbox domains are refused at social just-in-time signup, matching both the domain and one level of subdomain nesting. This blunts scripted signup, but it is a filter, not a defence — rate limits and challenges are what actually hold the line.
Post-login anomaly signals
Section titled “Post-login anomaly signals”After a successful login, two signals are recorded without gating the login:
new_device— a first-ever device for this user. The device fingerprint is derived from the user agent and accepted languages, deliberately excluding IP and geolocation so that a user who travels is not flagged as a new device every trip.impossible_travel— the distance from the previous login’s location implies a speed above 900 km/h, faster than a commercial flight.
Both land as login_anomaly audit events, and therefore reach any
SIEM stream you have configured.
They are recorded rather than enforced on purpose. Whether a new device warrants a step-up prompt, a notification email, or nothing at all is a product decision, and the data is where you can act on it.
Rate limits are the other half
Section titled “Rate limits are the other half”The login buckets are the tightest on the platform: 10 per minute per IP for one-time codes and magic links (which also caps outbound email), 30 for passwords. Password failures are additionally capped per email address at ten attempts, so grinding one account trips the account lockout rather than a generic IP throttle. See errors and rate limits.
What is recorded
Section titled “What is recorded”| Event | When |
|---|---|
login_blocked | A request was refused by policy, with the reasons and country. |
login_challenged | A challenge was required and not satisfied. |
login_challenge_skipped | A challenge was needed but unavailable — includes whether it failed closed. |
login_anomaly | A post-login signal fired. |
Alert on login_challenge_skipped with fail_closed: true: it means real users are being turned
away because the challenge provider is not configured.