-- ========================================== -- Chat Switchboard — 013 Files -- ========================================== -- Unified files table. Fresh install — no legacy attachments migration. -- Consolidated v0.28.0: removes attachments→files migration dance. -- ========================================== CREATE TABLE IF NOT EXISTS files ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), channel_id UUID REFERENCES channels(id) ON DELETE CASCADE, message_id UUID REFERENCES messages(id) ON DELETE SET NULL, user_id UUID REFERENCES users(id) ON DELETE SET NULL, project_id UUID REFERENCES projects(id) ON DELETE SET NULL, origin VARCHAR(20) NOT NULL DEFAULT 'user_upload' CHECK (origin IN ('user_upload', 'tool_output', 'system')), filename VARCHAR(255) NOT NULL, content_type VARCHAR(127) NOT NULL DEFAULT 'application/octet-stream', size_bytes BIGINT NOT NULL DEFAULT 0, storage_key TEXT NOT NULL, display_hint VARCHAR(20) NOT NULL DEFAULT 'download' CHECK (display_hint IN ('inline', 'download', 'thumbnail')), extracted_text TEXT, metadata JSONB DEFAULT '{}'::jsonb, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); 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) WHERE project_id IS NOT NULL; 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';