+++ title = "quotesdb/infra: Cloudflare rate limiting (WAF rules or Workers rate limiting per IP)" priority = 5 status = "done" ticket_type = "feature" dependencies = [] +++ ## Summary Investigate and implement rate limiting for the quotesdb API and frontend using Cloudflare's native tooling. ## Options to Evaluate ### 1. Cloudflare WAF Rate Limiting Rules (Recommended starting point) - Available on free tier with limits; full control on Pro+ - Rules can match on IP, path, method - Configure via OpenTofu (cloudflare_ruleset resource, phase: http_ratelimit) - Example: max 10 POST/PUT/DELETE requests per IP per minute to /api/* ### 2. Cloudflare Workers Rate Limiting API - workers-rs has bindings for the Rate Limiting API (available on paid plans) - More fine-grained: can key on IP + user-defined keys (e.g., quote ID) - Useful for per-resource rate limits (e.g., max N reports per IP per quote) ### 3. KV-based rate limiting in the Worker - Manual implementation using Cloudflare KV as a counter store - Works on free tier but adds latency and KV cost - Last resort if WAF rules are insufficient ## Suggested Limits (to start) - POST /api/quotes (create): 5 per IP per 10 minutes - POST /api/quotes/:id/report: 3 per IP per hour - POST /api/quotes/:id (update): 10 per IP per minute - DELETE /api/quotes/:id: 10 per IP per minute - GET endpoints: more generous or no limit (Cloudflare CDN caches anyway) ## Tasks - [ ] Research which Cloudflare plan features are available for this project - [ ] Implement WAF rate limiting rules in OpenTofu (infra/main.tf or new infra/rate-limits.tf) - [ ] If Workers Rate Limiting API is needed, add workers-rs bindings and implement in api/main.rs - [ ] Document the approach and any plan requirements in docs/ARCHITECTURE.md - [ ] Verify rules are applied with a test script (curl loop) ## Notes - CAPTCHA on the report endpoint (ticket 354276) provides an additional layer of bot protection - Rate limiting should complement, not replace, CAPTCHA ## Validation ```sh # from infra/ tofu validate tofu plan ```