- In-memory IP rate limiter: 5 attempts / 5min window - 15 min block on exceed, HTTP 429 + Retry-After header - Applied rate_limit_middleware on portal_server.py - Tests: TestLoginRateLimit added (conflict resolved: keep both test classes) Co-Authored-By: Paperclip <noreply@paperclip.ing>