-- Chat Switchboard — 018 Auth Abstraction (v0.24.0) ALTER TABLE users ADD COLUMN IF NOT EXISTS auth_source VARCHAR(20) NOT NULL DEFAULT 'builtin' CHECK (auth_source IN ('builtin', 'mtls', 'oidc')); ALTER TABLE users ADD COLUMN IF NOT EXISTS external_id TEXT; ALTER TABLE users ADD COLUMN IF NOT EXISTS handle VARCHAR(100); ALTER TABLE users ALTER COLUMN password_hash DROP NOT NULL; UPDATE users SET handle = LOWER(REPLACE(REPLACE(username, ' ', '-'), '_', '-')) WHERE handle IS NULL; ALTER TABLE users ALTER COLUMN handle SET NOT NULL; CREATE UNIQUE INDEX IF NOT EXISTS idx_users_handle ON users(LOWER(handle)); CREATE UNIQUE INDEX IF NOT EXISTS idx_users_external_id ON users(auth_source, external_id) WHERE external_id IS NOT NULL;