-- Chat server schema (pre-1.0 consolidated) PRAGMA foreign_keys = ON; -- Sessions: each session is a user identity (nick + optional password + signing key) CREATE TABLE IF NOT EXISTS sessions ( id INTEGER PRIMARY KEY AUTOINCREMENT, uuid TEXT NOT NULL UNIQUE, nick TEXT NOT NULL UNIQUE, username TEXT NOT NULL DEFAULT '', hostname TEXT NOT NULL DEFAULT '', ip TEXT NOT NULL DEFAULT '', is_oper INTEGER NOT NULL DEFAULT 0, password_hash TEXT NOT NULL DEFAULT '', signing_key TEXT NOT NULL DEFAULT '', away_message TEXT NOT NULL DEFAULT '', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, last_seen DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_sessions_uuid ON sessions(uuid); -- Clients: each session can have multiple connected clients CREATE TABLE IF NOT EXISTS clients ( id INTEGER PRIMARY KEY AUTOINCREMENT, uuid TEXT NOT NULL UNIQUE, session_id INTEGER NOT NULL REFERENCES sessions(id) ON DELETE CASCADE, token TEXT NOT NULL UNIQUE, ip TEXT NOT NULL DEFAULT '', hostname TEXT NOT NULL DEFAULT '', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, last_seen DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_clients_token ON clients(token); CREATE INDEX IF NOT EXISTS idx_clients_session ON clients(session_id); -- Channels CREATE TABLE IF NOT EXISTS channels ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, topic TEXT NOT NULL DEFAULT '', topic_set_by TEXT NOT NULL DEFAULT '', topic_set_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); -- Channel members CREATE TABLE IF NOT EXISTS channel_members ( id INTEGER PRIMARY KEY AUTOINCREMENT, channel_id INTEGER NOT NULL REFERENCES channels(id) ON DELETE CASCADE, session_id INTEGER NOT NULL REFERENCES sessions(id) ON DELETE CASCADE, joined_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE(channel_id, session_id) ); -- Messages: IRC envelope format CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, uuid TEXT NOT NULL UNIQUE, command TEXT NOT NULL DEFAULT 'PRIVMSG', msg_from TEXT NOT NULL DEFAULT '', msg_to TEXT NOT NULL DEFAULT '', params TEXT NOT NULL DEFAULT '[]', body TEXT NOT NULL DEFAULT '[]', meta TEXT NOT NULL DEFAULT '{}', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_messages_to_id ON messages(msg_to, id); CREATE INDEX IF NOT EXISTS idx_messages_created ON messages(created_at); -- Per-client message queues for fan-out delivery CREATE TABLE IF NOT EXISTS client_queues ( id INTEGER PRIMARY KEY AUTOINCREMENT, client_id INTEGER NOT NULL REFERENCES clients(id) ON DELETE CASCADE, message_id INTEGER NOT NULL REFERENCES messages(id) ON DELETE CASCADE, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE(client_id, message_id) ); CREATE INDEX IF NOT EXISTS idx_client_queues_client ON client_queues(client_id, id);