diff --git a/docs/superpowers/specs/2026-05-06-rate-limiter-refactor-design.md b/docs/superpowers/specs/2026-05-06-rate-limiter-refactor-design.md new file mode 100644 index 0000000..05965e3 --- /dev/null +++ b/docs/superpowers/specs/2026-05-06-rate-limiter-refactor-design.md @@ -0,0 +1,68 @@ +# Design Spec: Generic Rate Limiter Refactor + +Refactor the current global-state rate limiter into a struct-based implementation that supports multiple instances with different configurations, improving testability and flexibility. + +## 1. Core Architecture + +### Current State +- `pkg/middleware/ratelimit.go` uses global variables (`visitors`, `mu`, `quit`). +- Cleanup logic is started automatically via `init()`. +- Limits are hardcoded (5 attempts per minute). + +### Changes +- **Limiter Struct:** Encapsulate state within a `Limiter` struct. +- **Explicit Configuration:** Pass limits and windows via a `Config` struct. +- **Context-aware Cleanup:** Use `context.Context` to manage the cleanup goroutine lifecycle instead of a global `quit` channel. + +## 2. Component Design + +### `Limiter` Struct +```go +type visitor struct { + attempts int + lastSeen time.Time +} + +type Config struct { + MaxAttempts int + Window time.Duration +} + +type Limiter struct { + mu sync.Mutex + visitors map[string]*visitor + config Config +} +``` + +### Initialization +```go +func NewLimiter(cfg Config) *Limiter { + return &Limiter{ + visitors: make(map[string]*visitor), + config: cfg, + } +} +``` + +### Middleware Methods +- `Middleware(next http.Handler) http.Handler`: Generic rate limiting. +- `AuthMiddleware(next http.Handler) http.Handler`: Specific logic for auth (redirects with error params). + +## 3. Integration Plan + +- Instantiate the `Limiter` in `cmd/server/main.go`. +- Pass the `Limiter` or its middleware to `internal/server/NewRouter`. +- Update `internal/server/routes.go` to use the new instance-based middleware. + +## 4. Verification Plan + +### Automated Checks +- **Unit Tests:** Create `pkg/middleware/ratelimit_test.go` to verify: + - Multiple IPs are tracked independently. + - Limits are enforced correctly. + - Attempts reset after the window expires. +- `go test ./pkg/middleware/...`: Run the new tests. + +### Manual Checks +- Verify that exceeding login attempts still triggers the `rate_limited` redirect.