Public Access
Unknown email, wrong password and disabled account now all return 401 INVALID_CREDENTIALS; unknown emails still run bcrypt against a dummy hash so timing does not leak them. After 5 failures per email or 20 per client IP, login returns 429 with Retry-After for 15 minutes. LoginRequest is now validated.