- Hexagonal identity module: domain ports, use cases, argon2id hasher, pg repos - Migration 002_identity: identity_users + identity_sessions (token hash only) - Opaque 512-bit session tokens; DB stores SHA-256 hash; 7-day TTL in SQL - Cookie HttpOnly + Secure (COOKIE_SECURE, default true) + SameSite=Lax - LoginRateLimiter: 10 failures -> 429 + Retry-After, 15-min cooldown - Anti-enumeration: identical generic 401 + dummy-hash timing equalization - buildApp gains optional pool/cookieSecure; foundation-only app preserved - 47 unit + 14 integration tests; live smoke covers all acceptance criteria
34 lines
1.9 KiB
Markdown
34 lines
1.9 KiB
Markdown
# 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).
|