-- Chat Switchboard — 013 Files (SQLite) -- Unified files table replacing attachments. -- Handles both upgrade (attachments exists) and fresh install. CREATE TABLE IF NOT EXISTS files ( id TEXT PRIMARY KEY, channel_id TEXT REFERENCES channels(id) ON DELETE CASCADE, message_id TEXT REFERENCES messages(id) ON DELETE SET NULL, user_id TEXT REFERENCES users(id) ON DELETE SET NULL, project_id TEXT REFERENCES projects(id) ON DELETE SET NULL, origin TEXT NOT NULL DEFAULT 'user_upload' CHECK (origin IN ('user_upload', 'tool_output', 'system')), filename TEXT NOT NULL, content_type TEXT NOT NULL DEFAULT 'application/octet-stream', size_bytes INTEGER NOT NULL DEFAULT 0, storage_key TEXT NOT NULL, display_hint TEXT NOT NULL DEFAULT 'download' CHECK (display_hint IN ('inline', 'download', 'thumbnail')), extracted_text TEXT, metadata TEXT DEFAULT '{}', created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')) ); -- Ensure attachments table exists so the INSERT is always valid. -- Upgrade: no-op (table already has data). Fresh install: empty table. CREATE TABLE IF NOT EXISTS attachments ( id TEXT PRIMARY KEY, channel_id TEXT, user_id TEXT, message_id TEXT, project_id TEXT, filename TEXT, content_type TEXT, size_bytes INTEGER, storage_key TEXT, extracted_text TEXT, metadata TEXT, created_at TEXT ); INSERT OR IGNORE INTO files ( id, channel_id, message_id, user_id, project_id, origin, filename, content_type, size_bytes, storage_key, display_hint, extracted_text, metadata, created_at, updated_at ) SELECT id, channel_id, message_id, user_id, project_id, 'user_upload', filename, content_type, size_bytes, storage_key, CASE WHEN content_type LIKE 'image/%' THEN 'inline' WHEN content_type LIKE 'video/%' THEN 'inline' WHEN content_type LIKE 'audio/%' THEN 'inline' WHEN content_type = 'application/pdf' THEN 'thumbnail' WHEN content_type LIKE 'text/%' THEN 'inline' ELSE 'download' END, extracted_text, metadata, created_at, created_at FROM attachments; DROP TABLE IF EXISTS attachments; CREATE INDEX IF NOT EXISTS idx_files_channel ON files(channel_id); CREATE INDEX IF NOT EXISTS idx_files_message ON files(message_id); CREATE INDEX IF NOT EXISTS idx_files_user ON files(user_id); CREATE INDEX IF NOT EXISTS idx_files_project ON files(project_id); CREATE INDEX IF NOT EXISTS idx_files_origin ON files(origin); CREATE INDEX IF NOT EXISTS idx_files_orphan ON files(created_at) WHERE message_id IS NULL AND origin = 'user_upload';