feat(web): forced post-registration onboarding (BUNYIP-206) #228
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/bunyip-206-onboarding-page"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Forced post-registration onboarding (BUNYIP-206). A new user lands on
/onboardingand cannot reach the dashboard or any app surface until they have provided a first + last name and (when email delivery is configured) verified their email. Replaces the passive BUNYIP-139 dashboard name banner with a hard gate at the single bunyip-web chokepoint.How
handlers/mod.rs):needs_onboarding(st, user)blocks while the name is missing, or - only whensetup_status.email_enabledis true - while the email is unverified. Applied inguard()after the admin 2FA-setup gate (which keeps precedence and is let through on its own page so the two gates never fight) and skipped for an allowlist (/onboarding,/settings/verify-email,/settings/verify-email/resend,/logout,/assets). Bootstrap admins (already named + verified) skip it entirely.handlers/onboarding.rs, new; routes inmain.rs):GET/POST /onboardingin the authenticated shell. Name step saves via the existingPUT /v1/users/me/profile; email step shows verification state + a Resend control. Auto-sends the verification email on first arrival only, cookie-gated bybunyip_onboard_verify_sent.register_post->/onboarding; the emailed verification-link success card forwards to/dashboard(the gate routes a still-nameless user back to/onboarding) instead of dumping the user on settings;settings_resend_verificationguards with its real route path so the allowlist admits it; the dashboard name banner +profile_emptyremoved.Two root-cause decisions worth calling out
email_verifiedis always required. Butemail.enabled = (is_production && has_smtp) || EMAIL_ENABLED(config.rs), so email is OFF in local dev by default. An unconditional email-verification gate would permanently trap any dev-registered user (no email -> can never verify -> stuck on/onboardingforever). The gate therefore treats email verification as not-required when delivery is off. On prod (email on) the issue's AC holds exactly.setup_statusis only queried for the rare name-present-but-unverified case, so the common already-onboarded path adds no API call.request_email_verification"idempotent / re-send safe". It is not: it mints a fresh token and sends a new mail on every call, capped at 3/hour (services/auth.rs). A literal send-on-every-GET would spam the inbox and wall at the rate limit (the POST-name -> redirect -> GET cycle alone would double-send). The cookie (bunyip_onboard_verify_sent, 1h) makes it fire once per arrival; the send result is swallowed so a rate-limit or disabled-email never breaks the page.Migration note
Existing users who never verified their email (or have no name) will be routed through
/onboardingon their next protected request. That is the intended "forced" behaviour, but it is a visible change for that cohort.Test
just check-containergreen (fmt + clippy-D warnings+cargo test --workspace --lib). New unit tests covernames_present(both-names / whitespace) and theonboarding_allowedallowlist. The email-driven leg is exercised by the e2e suite on staging (mail sink, BUNYIP-150); the e2eauth/signupspec remainstest.fixme(BUNYIP-150) and will assert the/onboardinglanding when it is un-fixmed.Docs
KB DEV-A-40 (Login / Authentication system) updated: the onboarding flow, gate ordering, the email-disabled exemption, and the non-idempotent-verify gotcha.
🤖 Generated with Claude Code