Some checks failed
Test / test (pull_request) Has been cancelled
isBlocked was checked synchronously but recordFailure ran only AFTER the bcrypt awaits, so N concurrent /mcp Basic requests for one email all slipped past the threshold. Add FailedLoginLimiter.tryReserve (atomic synchronous check+increment) + release (undo), and reserve all 3 keys BEFORE any await so the (threshold+1)-th concurrent attempt is rejected before its bcrypt runs. The reservation IS the failure record (post-await recordFailure removed -> counted exactly once). Non- credential early throws (missing workspace, SSO/MFA gate) and business errors release the reservation so they don't burn a victim's budget; success clears. Tests prove login() runs exactly threshold times under concurrency and that gate/config rejects don't consume budget. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>