LoginRateLimiter uses two Caffeine LoadingCaches of Bucket4j buckets — one keyed on IP:email (10 attempts/15 min) and one on IP alone (20/15 min backstop). Exceeding either throws DomainException(TOO_MANY_LOGIN_ATTEMPTS) and emits LOGIN_RATE_LIMITED audit. Successful login invalidates both buckets via invalidateOnSuccess. Buckets expire after windowMinutes of inactivity (no clock advance needed — Caffeine handles eviction). AuthService integrates it as an optional @Autowired field so non-web test contexts still work without a Caffeine dependency. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
11 KiB
11 KiB