1.8 KiB
1.8 KiB
Task 02: Client Identity for Rate Limiting
Assigned to: Antigravity (Implementation Orchestrator)
Priority: HIGH (availability)
Date: 2026-08-21
Base SHA: 92f6d1922500791ef221cc11ed63f606afc01b53
Scope
- User-scoped rate limiting for authenticated routes (
/api/giveaways*):- Scope rate limit key by
sessionUser.idinstead of IP (draw:${sessionUser.id}:${id},snapshot-lock:${sessionUser.id}:${id},participants:${sessionUser.id}:${id},giveaways:${sessionUser.id}). - Order of execution:
requireAuthenticatedUser/requireGiveawayOwnerauthenticates the request and extractssessionUser, then user-scoped rate limiter runs. Unauthenticated requests fail with 401 immediately and cannot exhaust organizer rate limit buckets.
- Scope rate limit key by
- Anonymous route rate limiting (
/api/auth/vk/start,/api/posts/preview):- When IP cannot be resolved (empty
req.ipandTRUST_PROXY !== 'true'), use a dedicated anonymous fallback bucket (anon:direct-clientor similar) separate from user buckets.
- When IP cannot be resolved (empty
- Production configuration guard & documentation:
- In
docs/PRODUCTION_GUARDS.md, document proxy configuration and IP resolution behavior.
- In
- Concurrency & Isolation tests in
tests/rate-limit-identity.test.ts:- Two authenticated organizers with empty
req.ipdo not affect each other's rate limits. - Exhausting anonymous rate limit does not affect authenticated organizers.
- Unauthenticated requests cannot bypass authentication or drain organizer limits.
- Existing
TRUST_PROXY=truebehavior and tests remain green.
- Two authenticated organizers with empty
- Verification:
npm ci,npx prisma generate,npm test,npm run lint,npm run build,npx tsc --noEmit.
- Output report in
agents/antigravity/done/TASK-2026-08-21-02-rate-limit-client-identity.md.