-- Curator accounts and audit log (auth migration) CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(64) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), last_login_at TIMESTAMPTZ ); CREATE TABLE IF NOT EXISTS curator_audit_log ( id BIGSERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, action VARCHAR(64) NOT NULL, resource_type VARCHAR(32) NOT NULL, resource_id INTEGER NOT NULL, details JSONB, ip_address VARCHAR(45), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_curator_audit_log_user_id ON curator_audit_log(user_id); CREATE INDEX IF NOT EXISTS idx_curator_audit_log_created_at ON curator_audit_log(created_at DESC); CREATE INDEX IF NOT EXISTS idx_curator_audit_log_resource ON curator_audit_log(resource_type, resource_id); -- Session store for express-session (connect-pg-simple) CREATE TABLE IF NOT EXISTS "session" ( "sid" VARCHAR NOT NULL COLLATE "default", "sess" JSON NOT NULL, "expire" TIMESTAMP(6) NOT NULL ); DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'session_pkey' ) THEN ALTER TABLE "session" ADD CONSTRAINT session_pkey PRIMARY KEY ("sid"); END IF; END $$; CREATE INDEX IF NOT EXISTS "IDX_session_expire" ON "session" ("expire");