feat(auth)!: go fully passwordless and fix cross-check review findings
Remove password authentication everywhere; the only session doors are passkey (WebAuthn), email OTP, in-game bind codes, QR scan-login, and op-login vouching. Remediates the 33-finding cross-check review across backend, CLI, panel, plugins, and docs. Backend/CLI: - Drop password routes and fields from account/user/onboard/auth handlers; align tests (new account subtests, naming reserves "console", op-login/onboard/qr-login test updates). - Add migrations 0016_op_login.sql and 0017_drop_password.sql. - Thread panel/admin hostnames from hostcfg through api.go, setup_panel.go, tui_root.go and tui_preflight.go instead of hardcoding; bootstrap.sh writes panel-hostname/admin-hostname into felis.toml. - Reword breakglass and TUI copy for passwordless flows. Panel: - Delete the ChangePassword page and all password UI; align login/auth/api/types with the passwordless contract; add the migration and op-login approval flows. - i18n: convert ImageBuildPage durations/status badges and ServerLuckPerms strings to translation keys; drop 72 orphan keys per locale; unify the title as "Felis - Console". Plugins (all six rebuilt): - Velocity waiting router returns 503 at_capacity during wake; MOTD/control-channel copy and config comments. - Paper zh menu title; Limbo bind-code TTL 600s with panel_url preference; unified /link lines in fabric/forge/neoforge; shared link-client javadoc contract fixes. Docs: openapi.yaml, sequence-diagrams.md, deploy/limbo/README.md and plugins/README.md aligned with the implementation. BREAKING CHANGE: migration 0017 irreversibly drops users.password_hash and users.must_change_password; password login cannot be restored after migrating.
This commit is contained in:
97 files changed
+1923
-1444
No files matched your search
@@ -818,10 +818,11 @@ func (p *PGRepo) IsUsernameBlacklisted(ctx context.Context, mcUUID string) (bool
|
||||
// who authenticates through the third-party Yggdrasil — the admin-on-Yggdrasil reclaim
|
||||
// exception (spec §B3). The EXISTS joins account_links to users on exactly three
|
||||
// conjuncts: the UUID is linked, that link authenticated via 'thirdparty', and the
|
||||
// linked user is an admin. It intentionally does not test password_hash: an Operator
|
||||
// who signs in via SSO (Cloudflare Access, §14) carries role='admin' with a NULL hash
|
||||
// and must be protected just the same — the hash is orthogonal to "is staff" and "logs
|
||||
// in via the Login Server". Keyed by UUID, the only identity velocity holds.
|
||||
// linked user is an admin. It intentionally does not test HOW the account signs in:
|
||||
// an Operator may authenticate via SSO (Cloudflare Access, §14) or any local
|
||||
// passwordless door and must be protected just the same — the sign-in method is
|
||||
// orthogonal to "is staff" and "logs in via the Login Server". Keyed by UUID, the
|
||||
// only identity velocity holds.
|
||||
func (p *PGRepo) IsProtectedAdminLink(ctx context.Context, mcUUID string) (bool, error) {
|
||||
var ok bool
|
||||
err := p.db.QueryRowContext(ctx,
|
||||
|
||||
Reference in new issue
Block a user