-- kommunikation plugin initial migration: creates all 10 tables CREATE TABLE IF NOT EXISTS comm_conversations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, title VARCHAR(255), title_set_by UUID, is_pinned BOOLEAN NOT NULL DEFAULT FALSE, is_locked BOOLEAN NOT NULL DEFAULT FALSE, locked_by VARCHAR(100), is_direct BOOLEAN NOT NULL DEFAULT FALSE, is_archived BOOLEAN NOT NULL DEFAULT FALSE, created_by UUID, created_by_type VARCHAR(20) NOT NULL DEFAULT 'user', last_msg_at TIMESTAMPTZ, last_msg_preview TEXT, last_msg_sender_type VARCHAR(50), metadata JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ ); CREATE INDEX IF NOT EXISTS ix_comm_conversations_tenant ON comm_conversations(tenant_id); CREATE INDEX IF NOT EXISTS ix_comm_conversations_tenant_pinned ON comm_conversations(tenant_id, is_pinned); CREATE INDEX IF NOT EXISTS ix_comm_conversations_last_msg ON comm_conversations(tenant_id, last_msg_at DESC); CREATE TABLE IF NOT EXISTS comm_participants ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, conversation_id UUID NOT NULL REFERENCES comm_conversations(id) ON DELETE CASCADE, participant_id UUID, participant_type VARCHAR(50) NOT NULL, display_name VARCHAR(255), role VARCHAR(20) NOT NULL DEFAULT 'member', joined_at TIMESTAMPTZ NOT NULL DEFAULT now(), left_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ, UNIQUE(conversation_id, participant_id, participant_type) ); CREATE INDEX IF NOT EXISTS ix_comm_participants_tenant_conv ON comm_participants(tenant_id, conversation_id); CREATE INDEX IF NOT EXISTS ix_comm_participants_tenant_user ON comm_participants(tenant_id, participant_id); CREATE TABLE IF NOT EXISTS comm_messages ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, conversation_id UUID NOT NULL REFERENCES comm_conversations(id) ON DELETE CASCADE, sender_id UUID, sender_type VARCHAR(50) NOT NULL, content TEXT NOT NULL DEFAULT '', content_format VARCHAR(20) NOT NULL DEFAULT 'text', metadata JSONB NOT NULL DEFAULT '{}', reply_to_id UUID REFERENCES comm_messages(id) ON DELETE SET NULL, is_pinned BOOLEAN NOT NULL DEFAULT FALSE, read_at TIMESTAMPTZ, edited_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ ); CREATE INDEX IF NOT EXISTS ix_comm_messages_tenant_conv ON comm_messages(tenant_id, conversation_id, created_at); CREATE INDEX IF NOT EXISTS ix_comm_messages_tenant_sender ON comm_messages(tenant_id, sender_id); CREATE TABLE IF NOT EXISTS comm_message_blocks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, message_id UUID NOT NULL REFERENCES comm_messages(id) ON DELETE CASCADE, block_type VARCHAR(50) NOT NULL, block_data JSONB NOT NULL, sort_order INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ ); CREATE INDEX IF NOT EXISTS ix_comm_blocks_tenant_msg ON comm_message_blocks(tenant_id, message_id); CREATE TABLE IF NOT EXISTS comm_message_attachments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, message_id UUID NOT NULL REFERENCES comm_messages(id) ON DELETE CASCADE, file_id UUID, file_source VARCHAR(10) NOT NULL DEFAULT 'comm', file_name VARCHAR(255) NOT NULL, file_type VARCHAR(255) NOT NULL, file_size INTEGER, thumbnail_path VARCHAR(1024), metadata JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ ); CREATE INDEX IF NOT EXISTS ix_comm_attachments_tenant_msg ON comm_message_attachments(tenant_id, message_id); CREATE TABLE IF NOT EXISTS comm_message_reactions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, message_id UUID NOT NULL REFERENCES comm_messages(id) ON DELETE CASCADE, user_id UUID NOT NULL, emoji VARCHAR(50) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ, UNIQUE(message_id, user_id, emoji) ); CREATE INDEX IF NOT EXISTS ix_comm_reactions_tenant_msg ON comm_message_reactions(tenant_id, message_id); CREATE TABLE IF NOT EXISTS comm_message_reads ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, conversation_id UUID NOT NULL REFERENCES comm_conversations(id) ON DELETE CASCADE, user_id UUID NOT NULL, last_read_msg_id UUID REFERENCES comm_messages(id) ON DELETE SET NULL, last_read_at TIMESTAMPTZ NOT NULL DEFAULT now(), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ, UNIQUE(conversation_id, user_id) ); CREATE INDEX IF NOT EXISTS ix_comm_reads_tenant_user ON comm_message_reads(tenant_id, user_id); CREATE TABLE IF NOT EXISTS comm_conversation_pins ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, conversation_id UUID NOT NULL REFERENCES comm_conversations(id) ON DELETE CASCADE, user_id UUID NOT NULL, pinned_at TIMESTAMPTZ NOT NULL DEFAULT now(), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ, UNIQUE(conversation_id, user_id) ); CREATE INDEX IF NOT EXISTS ix_comm_pins_tenant_user ON comm_conversation_pins(tenant_id, user_id); CREATE TABLE IF NOT EXISTS comm_conversation_mutes ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, conversation_id UUID NOT NULL REFERENCES comm_conversations(id) ON DELETE CASCADE, user_id UUID NOT NULL, muted_at TIMESTAMPTZ NOT NULL DEFAULT now(), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ, UNIQUE(conversation_id, user_id) ); CREATE INDEX IF NOT EXISTS ix_comm_mutes_tenant_user ON comm_conversation_mutes(tenant_id, user_id); CREATE TABLE IF NOT EXISTS comm_message_edits ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, message_id UUID NOT NULL REFERENCES comm_messages(id) ON DELETE CASCADE, old_content TEXT NOT NULL, old_blocks JSONB NOT NULL DEFAULT '[]', edited_by UUID NOT NULL, edited_at TIMESTAMPTZ NOT NULL DEFAULT now(), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ ); CREATE INDEX IF NOT EXISTS ix_comm_edits_tenant_msg ON comm_message_edits(tenant_id, message_id);