The onboarding flow had been silently skipped for every new user since AuthController::handleLogin started redirecting to /feed instead of /dashboard — the onboarding check only lived inside DashboardController::showDashboard.
- Fix: enforcement moved into
AuthMiddleware, next to the existing 2FA-setup gate. Any authenticated request withonboarding_completed_at IS NULLredirects to/onboarding. Allowlist:/onboarding,/onboarding/skip,/logout,/account/2fa/*. - 2FA still runs first for role ≥ 3 accounts — admin who hasn't set up 2FA gets sent to
/account/2fa/setupbefore onboarding kicks in. - Backfill: users registered during the broken window have
onboarding_completed_at IS NULLand will see the wizard on their next login.
Post-wizard intro nudge
After the interests picker (or Skip), users now land on /onboarding/complete before /feed. Single primary CTA: Introduce yourself, deep-linked to the New Member Intros new-thread form with a pre-filled "Hi, I'm @user" title. Secondary link: Skip to my feed. No enforcement — stamp is already set when this page renders.