# Architect — F-005 Identity: register, login, sessions done -> work/artifacts/F-005/architect.md ## Deliverables - specs/F-005-identity/SPEC.md, DESIGN.md, TASKS.md, TESTS.md ## Key decisions 1. **Server-side opaque sessions in PostgreSQL**, never JWT/client-trusted tokens: the cookie carries 512 bits of randomness; the DB stores only the SHA-256 hash. A DB leak yields no usable sessions; logout is a real revocation. 2. **Hexagonal identity module** (domain/application/infrastructure/api) as the ticket demands. Domain knows no framework; ports live in domain; infra implements them. This module is the template for catalog/inventory/orders later. 3. **argon2id with OWASP 2024 params** (m=19456 KiB, t=2, p=1) behind a PasswordHasher port. Timing equalization via dummy-hash verify on unknown email. 4. **Rate limiting behind a LoginRateLimiter interface**, in-memory implementation for the single-instance monolith: 10 consecutive failures per email, 15-min cooldown, reset on success, Retry-After on 429. Redis-backed swap later without touching use cases. 5. **Cookie policy**: HttpOnly + SameSite=Lax always; Secure via `COOKIE_SECURE` (default true — production-safe; .env.example sets false for local http). 6. **Foundation touchpoints kept minimal**: createPool(connectionString), COOKIE_SECURE in config, buildApp gains optional pool dep (foundation-only app preserved when absent). ## Security posture - No plaintext or reversible passwords anywhere (argon2 PHC strings only). - Generic 401 for both unknown email and wrong password (no enumeration). - Parameterized SQL only; citext unique email enforced in DB (race-safe). - Session expiry + revocation enforced in the DB query, not in app memory. ## Risks - argon2 native build (toolchain verified present; fallback @node-rs/argon2 behind port). - In-memory limiter is per-instance (documented; acceptable for monolith slice).