Replace the per-Vercel-instance in-memory Map rate-limit cache with an atomic shared store backed by the existing Turso RateLimit table, so limits hold across all instances/redeploys and cannot be bypassed by distributing brute-force attempts across instances (audit finding p8-010, MEDIUM). - checkRateLimit now performs a single atomic round-trip: INSERT ... ON CONFLICT(identifier) DO UPDATE ... RETURNING count, reset_at with window-reset semantics (CASE WHEN reset_at < now THEN 1 ELSE count+1). - The DB is now the primary source of truth (no longer a fire-and-forget fallback). The per-instance Map is reduced to a short-TTL local cache used ONLY to fast-fail already-blocked identifiers (cuts DB load during brute- force storms); it can never let a request bypass the limit. - ensureRateLimitSchema() creates the table + a UNIQUE identifier index so ON CONFLICT upserts are well-defined; added RateLimit to db/create.ts. - resetLoginRateLimits / clearRateLimitStore invalidate the local cache. - getClientIP now trusts proxy headers in non-development environments (production + test); local dev stays strict against header spoofing. - bunfig.toml defines import.meta.env.SSR=true so the server-only env guard loads under 'bun test'. - Tests: await clearRateLimitStore in beforeEach (fixes a race where an un-awaited clear let leftover rows corrupt the next upsert); unique test identifiers; realistic remote-shared-store perf bounds; new p8-010 distributed-store tests (restart-survival, multi-instance aggregation, no bypass by alternating instances).
40 B
40 B