-- 003_users.sql — local accounts + session cookies. -- -- Password hashes are argon2id in PHC string format: all params live in the -- hash itself so we can bump time/memory costs without migrating. -- -- Roles are coarse for now — admin (full control) / user (read-only). Fine- -- grained per-resource ACL is a later migration layered on top. CREATE TABLE users ( id BIGSERIAL PRIMARY KEY, email TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'admin', disabled BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE sessions ( token TEXT PRIMARY KEY, -- 32 bytes hex; random via crypto/rand user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), expires_at TIMESTAMPTZ NOT NULL, last_seen_ip TEXT, last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_sessions_user ON sessions(user_id); CREATE INDEX idx_sessions_expires ON sessions(expires_at);