Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions ENVIRONMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,11 @@ The connection-role migration preserves a sole eligible connection, prefers an u
- Signup calls `/api/v1/signup-decide` only for new users, after account resolution and before Stripe customer creation. Existing sign-in and provider linking never consume signup quotas. The call uses `INTERNAL_API_SECRET` and a 3,000 ms budget.
- Development skips admission. In other environments, signup requires a usable IP and a validated Bouncer verdict. Missing configuration, timeouts, transport errors, HTTP errors, invalid JSON, and unknown response shapes fail closed with `SIGNUP-UNAVAILABLE`.
- An unavailable verdict creates no Stripe customer, user, or auth provider. Web signup shows a retry message. Native token exchange returns HTTP 503 and releases the email-code reservation so the same code can be retried.
- Only a validated enforced `signup_rate_limited` response returns `SIGNUP-RATE-LIMITED`. Cloud accepts at most five merged IP/JA4 flags, including `signup:ja4`, and never exposes internal flags to the user.
- Signup sends `{ operationId, ip, ja4? }`. JA4 comes only from the original request's `x-vercel-ja4-digest` header, not the Cloud-to-Bouncer TLS fingerprint. It is trimmed, lowercased, and bounded to `^[a-z0-9_]{1,128}$`; missing or invalid values are omitted whole, never truncated, and IP admission still runs. `signupOperationId` hashes the existing normalized email with SHA-256 and prefixes the digest with `signup:`.
- A validated enforced `signup_rate_limited` response returns `SIGNUP-RATE-LIMITED`. Cloud accepts at most eight merged IP, domain, and JA4 flags, including `signup:busy`, `signup:domain`, and `signup:ja4`, and never exposes internal flags to the user.
- A validated enforced `signup_step_up` response returns `SIGNUP-STEP-UP` with its `methods` (1 to 8 values of `^[a-z0-9-]{1,32}$`). It creates no Stripe customer, user, or auth provider. Cloud shows only `google` and `apple`, in that order, and ignores other values. Web signup redirects to sign-in with `error=SIGNUP-STEP-UP&methods=<comma-separated>` and asks the user to continue with those methods; the copy never names a signal. Native token exchange returns HTTP 403 `{ error: "SIGNUP-STEP-UP", methods }`; the mobile app names the allowed Apple or Google button when that button is on its screen, and otherwise points to its browser sign-in options.
- Signup sends `{ operationId, ip, ja4?, method?, emailDomain? }`. JA4 comes only from the original request's `x-vercel-ja4-digest` header, not the Cloud-to-Bouncer TLS fingerprint. It is trimmed, lowercased, and bounded to `^[a-z0-9_]{1,128}$`; missing or invalid values are omitted whole, never truncated, and IP admission still runs. `signupOperationId` hashes the existing normalized email with SHA-256 and prefixes the digest with `signup:`.
- `method` is the signup's auth provider ID. `emailDomain` is the registrable domain (`tldts` `getDomain`, private suffixes included) of the normalized email's host, or the full host when it has none, so subdomains of one domain share a counter. It is sent for every method; Bouncer counts it only for email signups. Each field is omitted whole when invalid. Without `method`, Bouncer applies its method-less policy, as for an old Cloud build.
- With `enforcement.signupStepUp` on, Bouncer steps up a risky signup instead of rejecting it: it asks for Google or Apple, and admits Apple and WorkOS on a shared IP. Deploy Bouncer with `enforcement.signupStepUp=false` before this Cloud change, measure the shadow `stepUp` audit field, and only then let Igor turn it on.
- The identity helper lives in `packages/web-shared/src/lib/bouncer/signup.ts`. Live admission and historical import must use the same helper.
- Cloud validates the forwarded first-hop IP. Bouncer canonicalizes addresses and groups IPv6 by /64.
- Bouncer defaults to 3 admissions per canonical IP per rolling 30 days. The shorter 24-hour limit is also 3.
Expand Down
3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/af.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/am.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/ar.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/az.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/be.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/bg.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/bn.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/bs.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/ca.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/ckb.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/cs.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/cy.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/da.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/de.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/el.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions apps/mobile/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3120,6 +3120,9 @@
"ssoError": "Your organization requires SSO. Use '$t(login.moreSignInOptions)'.",
"blocked": "This account has been blocked. Please contact support.",
"signupRateLimited": "Too many attempts. Please try again later.",
"signupStepUp": "To finish creating your account, use '$t(login.moreSignInOptions)'.",
"signupStepUpApple": "To finish creating your account, use '$t(login.signInWithApple)'.",
"signupStepUpGoogle": "To finish creating your account, use '$t(login.signInWithGoogle)'.",
"invalidCode": "That code is incorrect. Please try again.",
"codeInProgress": "Your code is being processed. Wait a moment and try again.",
"tooManyAttempts": "Too many attempts. Please request a new code.",
Expand Down
Loading
Loading