-- Migration 142: Persistent thread key for reliable inbound case routing ALTER TABLE email_messages ADD COLUMN IF NOT EXISTS thread_key VARCHAR(500); -- Backfill thread_key for existing rows. -- Priority: -- 1) First token from References (root message id) -- 2) In-Reply-To -- 3) Message-ID UPDATE email_messages SET thread_key = LOWER( REGEXP_REPLACE( COALESCE( NULLIF( SPLIT_PART( REGEXP_REPLACE(COALESCE(email_references, ''), '^[\s<>,]+', ''), ' ', 1 ), '' ), NULLIF(in_reply_to, ''), NULLIF(message_id, '') ), '[<>\s]', '', 'g' ) ) WHERE (thread_key IS NULL OR TRIM(thread_key) = '') AND ( COALESCE(NULLIF(email_references, ''), NULLIF(in_reply_to, ''), NULLIF(message_id, '')) IS NOT NULL ); CREATE INDEX IF NOT EXISTS idx_email_messages_thread_key ON email_messages(thread_key) WHERE thread_key IS NOT NULL; COMMENT ON COLUMN email_messages.thread_key IS 'Stable normalized thread key (root message-id/in-reply-to) for case routing';