-- user status enum values DO $$ BEGIN CREATE TYPE user_status AS ENUM ('online', 'idle', 'dnd', 'offline', 'invisible'); EXCEPTION WHEN duplicate_object THEN null; END $$; -- main users table CREATE TABLE users ( id BYTEA PRIMARY KEY NOT NULL CHECK(length(id) = 26), username TEXT NOT NULL CHECK (char_length(username) BETWEEN 1 AND 32), discriminator TEXT NOT NULL DEFAULT '0000' CHECK (discriminator ~ '^\d{4}$'), avatar_hash BYTEA CHECK(length(id) = 26), -- null if no avatar email TEXT UNIQUE CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'), email_verified BOOLEAN NOT NULL DEFAULT FALSE, password_hash TEXT NOT NULL, -- bcrypt/argon2 hash, never plaintext mfa_enabled BOOLEAN NOT NULL DEFAULT FALSE, mfa_secret TEXT CHECK (mfa_enabled = FALSE OR char_length(mfa_secret) > 0), -- encrypted if present status user_status NOT NULL DEFAULT 'offline', public_flags BIGINT NOT NULL DEFAULT 0, -- bitmask for flags locale TEXT NOT NULL DEFAULT 'en-US' CHECK (locale ~ '^[a-z]{2}(-[A-Z]{2})?$'), -- BCP 47 pattern premium_since TIMESTAMPTZ, -- e.g., Premium subscription start premium_end TIMESTAMPTZ, bot BOOLEAN NOT NULL DEFAULT FALSE, bot_oauth_scopes JSONB NOT NULL DEFAULT '[]'::jsonb, -- e.g., ['bot', 'guilds.join'] preferences JSONB NOT NULL DEFAULT '{}'::jsonb, -- theme, sound, etc. created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() );