Repository navigation
feat(auth): step up risky signups to Google or Apple - #7766
Conversation
Send the signup method and email domain to signup-decide, accept the signup_step_up branch with its methods, add the signup:busy and signup:domain flags, and raise the flag cap to 8.
A validated signup_step_up verdict returns SIGNUP-STEP-UP and creates no Stripe customer, user, or auth provider. Web redirects to sign-in with the allowed methods; the native token route returns them with HTTP 403.
SIGNUP-STEP-UP names the Apple or Google button when Bouncer allows it and the screen shows it, and otherwise points to the browser sign-in options.
Subdomains of one registrable domain now share Bouncer's domain counter. A public suffix such as my.id keeps the full host.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryReviewed the risky-signup step-up feature end to end — the Bouncer signup-decide client schema, Cloud settlement mapping, web redirect and notification, the native token route, mobile messaging, and the 87 locale catalogs — and found no defects on the changed lines; the untrusted Files Reviewed (110 files)Non-locale source and docs (23):
Locale catalogs (87): all Reviewed by deepseek-v4.1-flash · Input: 123.9K · Output: 25.7K · Cached: 3.4M Review guidance: REVIEW.md from base branch |


Summary
Risky signups now get a step-up instead of a hard block: Bouncer's new
signup_step_upverdict asks the user to finish with Google or Apple.signupDecidesends optionalmethod(the auth provider ID) andemailDomain(the registrable domain of the normalized email's host, viatldts, so subdomains share one counter). An invalid value is omitted whole, so Bouncer falls back to its method-less policy.{ enforced: true, code: "signup_step_up", methods, flags }(methods: 1–8 strings of^[a-z0-9-]{1,32}$), adds thesignup:busyandsignup:domainflags, and raises the flag cap to 8.createOrUpdateUsermaps a validated step-up to the newSIGNUP-STEP-UPerror with the known methods (google,apple, in that order). It creates no Stripe customer, user, or auth-provider row.methods=<comma-separated>. The notification renders only Google and Apple from that untrusted query and never names a signal.{ error: "SIGNUP-STEP-UP", methods }on the email and Apple/Google paths. The email-code reservation is released.SIGNUP-STEP-UPis added everywhereSIGNUP-RATE-LIMITEDis handled:useSignInFlow,sso.ts, the expected-error list, andAuthErrorType.ENVIRONMENT.mddocuments the change.Deploy order
Deploy after Kilo-Org/bouncer#20, with
enforcement.signupStepUp=false. Old Bouncer builds never send the new branch. A new Bouncer never sends it to old Cloud builds, because those omitmethod.Verification
Run on a Linux VM:
check:unused,check:i18n,check:plurals, andformat:checkpass, andoxfmtreports no differences.createOrUpdateUser, native routes, auth components, redirect URLs, and next-auth options. Mobilevitest src/lib/authpasses 26 files (556 tests).next buildkept failing on unrelated module-level environment requirements, one variable per build. A throwaway script ran the realcreateOrUpdateUserwithNODE_ENV=productionagainst local Postgres and the local Bouncer. An email signup from an IP past the burst limit returnedSIGNUP-STEP-UPwith["google","apple"]and created no user, Stripe customer, or auth-provider row. An email signup from a quiet IP created the account; Bouncer loggeddomainKey: "domain:example.test"for the hostquiet.example.test. The sign-in page screenshots formethods=google,appleandmethods=applecome fromnext dev.