-- Migration 023 — auth-related user timestamps + idempotent dev user. -- -- See docs/superpowers/specs/2026-05-27-auth-system-design.md -- -- password_updated_at + last_login_at are operator visibility, no logic depends on them yet. -- The dev user is seeded with a fixed UUID so FK-bearing routes (api_tokens, -- future audit fields) keep working when AUTH_ENABLED=false. The seeded -- password_hash is a placeholder that no bcrypt.compare will accept, so the -- dev row cannot be used to log in even if AUTH_ENABLED is later flipped on. -- -- password_updated_at is backfilled with NOW() for existing rows at migration time; -- treat values from before this deploy as approximate. ALTER TABLE users ADD COLUMN IF NOT EXISTS password_updated_at TIMESTAMPTZ DEFAULT NOW(); ALTER TABLE users ADD COLUMN IF NOT EXISTS last_login_at TIMESTAMPTZ; INSERT INTO users (id, username, password_hash, display_name, role) VALUES ( '00000000-0000-4000-8000-000000000000', 'dev', '!disabled-no-login!', 'Dev (AUTH_ENABLED=false)', 'admin' ) ON CONFLICT DO NOTHING;