Files
pad/docs
xarmian 66b4a9d477 fix(auth): disabling an account ends every credential, and a disabled account gets no new one (BUG-3349) (#1741)
(b) Admin disable deleted sessions only, so the account's PATs and MCP
grants kept working. DisableUserAndRevokeAccess does all of it in one
transaction:
- disables the account;
- deletes its sessions and API tokens;
- deactivates every OAuth access and refresh token (by subject), and every
  unexchanged authorization code (through its connection's request id);
- deletes its PKCE and OAuth connection rows.
EnableUser restores none of them.

(c) A disabled account acts nowhere and gets no credential:
- requireActiveUserTx is the one gate every credential insert passes. It
  reads the user row in the insert's own transaction, FOR SHARE on
  Postgres, and refuses a disabled or missing account with ErrUserDisabled.
  It covers sessions, API tokens, OAuth codes, access and refresh tokens,
  and OAuth connections. FOR SHARE conflicts with the disable's row lock,
  so a mint admitted before a disable cannot land after it.
  TestBUG3349_MintWaitsForAConcurrentDisable_Postgres proves the wait with
  two connections.
  TestEveryCredentialInsertRequiresAnActiveUser fails on any new credential
  insert that skips the gate.
- RequireAuth checks disabled status before the /api/v1/auth/* exemption.
  Only POST /auth/logout and GET /auth/session stay open, and the session
  check answers account_disabled.
- The MCP door, /oauth/token, /oauth/authorize and /authorize/decide, 2FA
  login-verify, and email verification (before its token is spent) refuse
  a disabled account. The login page shows "Your account has been
  disabled".
- Share links the account created are suspended (lead's ruling):
  byte-identical to an unknown token while it is disabled, serving again
  once it is re-enabled.

Webhooks are unchanged by design; they belong to the workspace. This is
documented in docs/deployment.md, "Disabling an account".

Part (a) shipped in BUG-3336. codex review: two rounds, eleven findings, all
fixed.

Claude-Session: https://claude.ai/code/session_01H63zaWhkb5pAafx2WGjrVC
2026-10-02 18:34:56 -04:00
..