Repository Public MIT
1# ADR-0004 — In-process rate limiting and PostgreSQL-backed state, no Redis23Status: accepted for V1, 2026-11-09.45## Context67The brief allows a durable PostgreSQL job table instead of Redis-backed queues for V1. Validation and scanning of a 20 MiB archive take well under a second, so there is no queue at all: finalize is synchronous.89## Decision1011- No Redis. Durable state (sessions, tokens, uploads, idempotency keys, download counters) is in PostgreSQL.12- Rate limits are fixed windows held in process memory (`ratelimit.ts`), keyed by token id, user id or client IP depending on the caller. Buckets and limits are listed in `docs/PERMISSIONS.md`.13- Repeated authentication failures from one IP (20 in 10 minutes) lock that IP out of bearer authentication until the window ends, including for valid tokens.14- Client IP is the last hop of `X-Forwarded-For`, which the Caddy gateway appends. The app is only reachable through that gateway.15- Housekeeping (expired uploads, old idempotency keys, old sessions, download dedupe hashes) is a console command, `pnpm admin cleanup`, to be scheduled by the operator.1617## Consequences1819- Counters reset when the process restarts and are not shared between instances. Running more than one instance requires moving the limiter to PostgreSQL or Redis first.20- No background worker to operate.21- A finalize request holds the archive in memory while it is validated; the 20 MiB cap bounds this.22