FOUNDRY
C8 Platform
← Tasks

Supabase tables for Estafeta sessions

completedcode_genP1

Description

Create estafeta_sessions and estafeta_messages tables in Supabase. Track conversation state, classification results, and user interactions.
Assignee
-
Claimed By
AG Lu
Created
21d ago
Completed
2d ago

Quality

Overall
79%
Pass
PASS
Graded By
-
Graded At
-

Cost

Input Tokens
-
Output Tokens
-
Est. USD
-

Result

{
  "code": "Supabase Tables for Estafeta Sessions — Migration SQL provided.\n\nCurrently the WhatsApp conversational engine (whatsapp_conversational.py line 399) uses an in-memory dict: `conversations: Dict[str, ConversationState] = {}`. This needs migration to Supabase for persistence across Cloud Run instances.\n\n## Migration SQL\n\n```sql\n-- Migration: Estafeta WhatsApp Sessions\n-- Replaces in-memory conversation state with persistent Supabase storage\n\nCREATE TABLE IF NOT EXISTS estafeta_sessions (\n    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    phone_number TEXT NOT NULL,           -- E.164 format, e.g. +5215551234567\n    client_id TEXT DEFAULT 'estafeta',    -- White-label client identifier\n    state TEXT NOT NULL DEFAULT 'greeting',  -- greeting, awaiting_product, classifying, presenting_result, awaiting_confirmation, completed\n    language TEXT DEFAULT 'es',           -- Detected language (es/en)\n    context JSONB DEFAULT '{}',          -- Accumulated classification context\n    product_description TEXT,             -- Current product being classified\n    last_hts_code TEXT,                  -- Last classification result\n    last_confidence FLOAT,              -- Confidence of last classification\n    turn_count INT DEFAULT 0,           -- Number of messages in session\n    created_at TIMESTAMPTZ DEFAULT NOW(),\n    updated_at TIMESTAMPTZ DEFAULT NOW(),\n    expires_at TIMESTAMPTZ DEFAULT (NOW() + INTERVAL '30 minutes'),\n    \n    -- Index for fast lookup by phone (most common query)\n    CONSTRAINT estafeta_sessions_phone_idx UNIQUE (phone_number, client_id)\n);\n\nCREATE TABLE IF NOT EXISTS estafeta_messages (\n    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    session_id UUID NOT NULL REFERENCES estafeta_sessions(id) ON DELETE CASCADE,\n    direction TEXT NOT NULL CHECK (direction IN ('inbound', 'outbound')),\n    message_type TEXT NOT NULL DEFAULT 'text',  -- text, image, audio, document, template, interactive\n    content TEXT,                         -- Message text or media description\n    media_url TEXT,                      -- Supabase Storage URL for media\n    meta_message_id TEXT,               -- WhatsApp message ID from Meta API\n    classification_result JSONB,        -- If this message triggered a classification\n    created_at TIMESTAMPTZ DEFAULT NOW()\n);\n\n-- Indexes\nCREATE INDEX IF NOT EXISTS idx_estafeta_messages_session \n    ON estafeta_messages(session_id, created_at DESC);\n\nCREATE INDEX IF NOT EXISTS idx_estafeta_sessions_active \n    ON estafeta_sessions(expires_at) \n    WHERE expires_at > NOW();\n\n-- RLS\nALTER TABLE estafeta_sessions ENABLE ROW LEVEL SECURITY;\nALTER TABLE estafeta_messages ENABLE ROW LEVEL SECURITY;\n\n-- Service role has full access\nCREATE POLICY estafeta_sessions_service ON estafeta_sessions\n    FOR ALL USING (true) WITH CHECK (true);\nCREATE POLICY estafeta_messages_service ON estafeta_messages\n    FOR ALL USING (true) WITH CHECK (true);\n\n-- Auto-update updated_at\nCREATE OR REPLACE FUNCTION update_estafeta_session_timestamp()\nRETURNS TRIGGER AS $$\nBEGIN\n    NEW.updated_at = NOW();\n    NEW.expires_at = NOW() + INTERVAL '30 minutes';\n    RETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE TRIGGER estafeta_session_updated\n    BEFORE UPDATE ON estafeta_sessions\n    FOR EACH ROW\n    EXECUTE FUNCTION update_estafeta_session_timestamp();\n```\n\n## Session States\n- `greeting` → Initial state, send welcome message\n- `awaiting_product` → Waiting for product description or image\n- `classifying` → Processing classification (show typing indicator)\n- `presenting_result` → Showing HTS code + duty rate, awaiting confirmation\n- `awaiting_confirmation` → User asked follow-up question\n- `completed` → Session ended (timeout or explicit goodbye)\n\n## Integration Point\nIn whatsapp_conversational.py, replace:\n```python\n# Line 399: conversations: Dict[str, ConversationState] = {}\n# With Supabase queries:\n# GET session: supabase.table('estafeta_sessions').select('*').eq('phone_number', from_number).eq('client_id', client_id).single()\n# UPSERT session: supabase.table('estafeta_sessions').upsert({...}, on_conflict='phone_number,client_id')\n# INSERT message: supabase.table('estafeta_messages').insert({session_id, direction, content, ...})\n```\n\nNote: File not created as migration — needs `supabase migration new estafeta_sessions` to get proper timestamp prefix.",
  "content": "Supabase Tables for Estafeta Sessions — Migration SQL provided.\n\nCurrently the WhatsApp conversational engine (whatsapp_conversational.py line 399) uses an in-memory dict: `conversations: Dict[str, ConversationState] = {}`. This needs migration to Supabase for persistence across Cloud Run instances.\n\n## Migration SQL\n\n```sql\n-- Migration: Estafeta WhatsApp Sessions\n-- Replaces in-memory conversation state with persistent Supabase storage\n\nCREATE TABLE IF NOT EXISTS estafeta_sessions (\n    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    phone_number TEXT NOT NULL,           -- E.164 format, e.g. +5215551234567\n    client_id TEXT DEFAULT 'estafeta',    -- White-label client identifier\n    state TEXT NOT NULL DEFAULT 'greeting',  -- greeting, awaiting_product, classifying, presenting_result, awaiting_confirmation, completed\n    language TEXT DEFAULT 'es',           -- Detected language (es/en)\n    context JSONB DEFAULT '{}',          -- Accumulated classification context\n    product_description TEXT,             -- Current product being classified\n    last_hts_code TEXT,                  -- Last classification result\n    last_confidence FLOAT,              -- Confidence of last classification\n    turn_count INT DEFAULT 0,           -- Number of messages in session\n    created_at TIMESTAMPTZ DEFAULT NOW(),\n    updated_at TIMESTAMPTZ DEFAULT NOW(),\n    expires_at TIMESTAMPTZ DEFAULT (NOW() + INTERVAL '30 minutes'),\n    \n    -- Index for fast lookup by phone (most common query)\n    CONSTRAINT estafeta_sessions_phone_idx UNIQUE (phone_number, client_id)\n);\n\nCREATE TABLE IF NOT EXISTS estafeta_messages (\n    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    session_id UUID NOT NULL REFERENCES estafeta_sessions(id) ON DELETE CASCADE,\n    direction TEXT NOT NULL CHECK (direction IN ('inbound', 'outbound')),\n    message_type TEXT NOT NULL DEFAULT 'text',  -- text, image, audio, document, template, interactive\n    content TEXT,                         -- Message text or media description\n    media_url TEXT,                      -- Supabase Storage URL for media\n    meta_message_id TEXT,               -- WhatsApp message ID from Meta API\n    classification_result JSONB,        -- If this message triggered a classification\n    created_at TIMESTAMPTZ DEFAULT NOW()\n);\n\n-- Indexes\nCREATE INDEX IF NOT EXISTS idx_estafeta_messages_session \n    ON estafeta_messages(session_id, created_at DESC);\n\nCREATE INDEX IF NOT EXISTS idx_estafeta_sessions_active \n    ON estafeta_sessions(expires_at) \n    WHERE expires_at > NOW();\n\n-- RLS\nALTER TABLE estafeta_sessions ENABLE ROW LEVEL SECURITY;\nALTER TABLE estafeta_messages ENABLE ROW LEVEL SECURITY;\n\n-- Service role has full access\nCREATE POLICY estafeta_sessions_service ON estafeta_sessions\n    FOR ALL USING (true) WITH CHECK (true);\nCREATE POLICY estafeta_messages_service ON estafeta_messages\n    FOR ALL USING (true) WITH CHECK (true);\n\n-- Auto-update updated_at\nCREATE OR REPLACE FUNCTION update_estafeta_session_timestamp()\nRETURNS TRIGGER AS $$\nBEGIN\n    NEW.updated_at = NOW();\n    NEW.expires_at = NOW() + INTERVAL '30 minutes';\n    RETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE TRIGGER estafeta_session_updated\n    BEFORE UPDATE ON estafeta_sessions\n    FOR EACH ROW\n    EXECUTE FUNCTION update_estafeta_session_timestamp();\n```\n\n## Session States\n- `greeting` → Initial state, send welcome message\n- `awaiting_product` → Waiting for product description or image\n- `classifying` → Processing classification (show typing indicator)\n- `presenting_result` → Showing HTS code + duty rate, awaiting confirmation\n- `awaiting_confirmation` → User asked follow-up question\n- `completed` → Session ended (timeout or explicit goodbye)\n\n## Integration Point\nIn whatsapp_conversational.py, replace:\n```python\n# Line 399: conversations: Dict[str, ConversationState] = {}\n# With Supabase queries:\n# GET session: supabase.table('estafeta_sessions').select('*').eq('phone_number', from_number).eq('client_id', client_id).single()\n# UPSERT session: supabase.table('estafeta_sessions').upsert({...}, on_conflict='phone_number,client_id')\n# INSERT message: supabase.table('estafeta_messages').insert({session_id, direction, content, ...})\n```\n\nNote: File not created as migration — needs `supabase migration new estafeta_sessions` to get proper timestamp prefix."
}

Audit Trail (2)

2d agotask_completedAG Lu
2d agotask_claimedAG Lu
Task ID: 24cf771a-2206-47bf-9619-22dec9d34cff