key($ip), self::DECAY_SECONDS); } public function isBlocked(?string $ip): bool { return RateLimiter::tooManyAttempts($this->key($ip), self::MAX_FAILURES); } public function availableIn(?string $ip): int { return RateLimiter::availableIn($this->key($ip)); } private function key(?string $ip): string { return 'login-failures-ip|'.($ip ?? 'unknown'); } }