Files
mercadodevida/project/migrations/002_identity.js
rikrdo 75293f39bc feat(identity): F-005 register/login/logout with argon2 sessions and rate limiting
- 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
2026-08-14 22:58:32 +02:00

35 lines
1.1 KiB
JavaScript

/**
* Identity module tables. Module-owned naming: identity_<table>.
* Sessions store only the SHA-256 hash of the opaque cookie token.
*/
/** @param {import('node-pg-migrate').MigrationBuilder} pgm */
export const up = (pgm) => {
pgm.sql(`
CREATE TABLE identity_users (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
email citext NOT NULL UNIQUE,
password_hash text NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
)
`);
pgm.sql(`
CREATE TABLE identity_sessions (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid NOT NULL REFERENCES identity_users(id) ON DELETE CASCADE,
token_hash text NOT NULL UNIQUE,
created_at timestamptz NOT NULL DEFAULT now(),
expires_at timestamptz NOT NULL,
revoked_at timestamptz
)
`);
pgm.sql('CREATE INDEX identity_sessions_user_id_idx ON identity_sessions (user_id)');
};
/** @param {import('node-pg-migrate').MigrationBuilder} pgm */
export const down = (pgm) => {
pgm.sql('DROP TABLE IF EXISTS identity_sessions');
pgm.sql('DROP TABLE IF EXISTS identity_users');
};