refactor(api): drop dead password-era ResetMailer, reconcile passkey-unbind docs

The passwordless migration left ResetMailer (SendPasswordReset) and its API field with zero callers and no wiring; the web console authenticates via email-OTP and passkey only. Remove both, plus the now-orphaned context import that the interface was the last user of in handlers_users.go.

Reconcile the DeleteAllPasskeyCredentialsForUser docs in repo.go and pgrepo.go: they claimed there was no production caller, but 2f22027 wired the owner-tier DELETE /users/{id}/passkeys. Both now note that a complete authenticator remediation pairs the unbind with a session revoke (unbinding alone leaves the live hijacked session; revoking alone leaves a re-enrollable credential), and the OpenAPI operation carries the same guidance in a new description. Reword the stale local-password test-fake header, since the passwordless fakes carry no must_change_password field.

No behavior change. gofmt, build, and the full test tree are green; OpenAPI parity and passkey-unbind tests pass; a grep confirms ResetMailer/SendPasswordReset are gone from the Go tree.
This commit is contained in:
flyemoji committed 2026-07-04 21:47:13 +09:00
1 parent 4f59d5128a
commit c20b12c655
6 files changed
+19 -24

No files matched your search

+6 -5
View File
@@ -354,11 +354,12 @@ type Repo interface {
DeletePasskeyCredential(ctx context.Context, userID, id string) error
// DeleteAllPasskeyCredentialsForUser unbinds every passkey a user holds — the
// remediation that stops a passkey planted via a transiently-hijacked session from
// surviving as a standing login foothold. Its original caller, the change-password
// flow, was removed in the passwordless migration, so it currently has no production
// caller; it is retained for the account-remediation/reset path (P5, #78). Removing
// zero rows is success, not an error — an account with no passkeys is the intended
// post-condition either way.
// surviving as a standing login foothold. Its production caller is the owner-tier
// DELETE /users/{id}/passkeys (handleUnbindUserPasskeys); a complete remediation
// pairs it with a session revoke, since unbinding the credential without revoking
// live sessions leaves the hijacked session itself, and revoking sessions without
// unbinding leaves a re-enrollable credential. Removing zero rows is success, not an
// error — an account with no passkeys is the intended post-condition either way.
DeleteAllPasskeyCredentialsForUser(ctx context.Context, userID string) error
// ---- player game-login: username-collision reclaim (spec §B3) ----