From 513044de5824d55607b80e9c55a5fe6572353e74 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Thu, 14 May 2026 21:51:37 +0200 Subject: [PATCH] feat(02-01): add 0002_auth.sql migration with users + sessions tables - citext extension + pgcrypto for gen_random_uuid() - users: id uuid PK, email citext UNIQUE, password_hash, created_at, updated_at (D-01) - sessions: id text PK (SHA-256 hex), user_id FK ON DELETE CASCADE, created_at, expires_at (D-04) - indexes on sessions(user_id) and sessions(expires_at) - no deleted_at, email_verified_at, user_agent, ip_address columns (D-02, D-03, D-04) - goose Up/Down round-trip verified against compose Postgres --- backend/migrations/0002_auth.sql | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 backend/migrations/0002_auth.sql diff --git a/backend/migrations/0002_auth.sql b/backend/migrations/0002_auth.sql new file mode 100644 index 0000000..4e89572 --- /dev/null +++ b/backend/migrations/0002_auth.sql @@ -0,0 +1,29 @@ +-- migrations/0002_auth.sql +-- Phase 2: Authentication — users + sessions tables. + +-- +goose Up +CREATE EXTENSION IF NOT EXISTS citext; +CREATE EXTENSION IF NOT EXISTS pgcrypto; + +CREATE TABLE 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() +); + +CREATE TABLE sessions ( + id text PRIMARY KEY, + user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE, + created_at timestamptz NOT NULL DEFAULT now(), + expires_at timestamptz NOT NULL +); + +CREATE INDEX sessions_user_id_idx ON sessions(user_id); +CREATE INDEX sessions_expires_at_idx ON sessions(expires_at); + +-- +goose Down +DROP TABLE IF EXISTS sessions; +DROP TABLE IF EXISTS users; +-- citext + pgcrypto left in place — extensions are cheap and shared across migrations.