Area: Account (re-run) (audit p1r) · Surface: /account/security (AccountController@securityIndex), templates/account/security.php · Dimension: competitor-gap · Severity: major
Every major competitor surfaces 2FA setup inside their own product UI: Circle, Skool, Zendesk, Intercom, and Teachable all let members enable MFA / passkeys without leaving the app. Bouncing a community member to a raw Zitadel admin console (`/ui/console/` — an IdP operator surface, not a consumer self-service screen) is jarring, off-brand, and a drop-off point: most users will not complete enrollment through an unfamiliar third-party console. The result is a community that effectively has no 2FA for ordinary members. The fix doesn't require rebuilding auth — Zitadel exposes session/account self-service that can be embedded or deep-linked to the specific enrollment flow, or an in-app TOTP/passkey enrollment can be brokered through the existing ZitadelManagementClient.
Evidence
AccountController::securityIndex() is 6 lines — it only renders the static template. templates/account/security.php tells the user MFA lives elsewhere: "Your password, two-factor enrollment, recovery options... are managed there — not in this app" with a button to `https://id.mobieus.io/ui/console/`. The only local control is a 'Sign out everywhere on this tenant' panic button. `grep` confirms all /account/2fa/* routes were retired (templates/profile/settings.php:771 'Two-Factor Authentication card removed 2026-05-22').
Suggested fix. Build an in-app Security page that shows current MFA status (via ZitadelManagementClient) and offers in-context 'Add authenticator app' and 'Add passkey' actions that deep-link to the exact Zitadel self-service flow (not the operator console root), returning the user to /account/security on completion. Show recovery-code status too.
Filed by the automated tenant-app audit and adversarially evidence-verified. Status: verified. Open — not yet actioned.
Patrick Bass
@mobieus