ACCEPTANCE CRITERIA (38/38)
☑ Migration SQL cria a tabela com schema exato definido na arquitetura
☑ Campos: `id` (BIGINT GENERATED ALWAYS), `event_date` (DATE), `campaign_ref` (TEXT), `ad_ref` (TEXT), `event_type` (TEXT — enum: `conversation_started`, `lead_qualified`, `handoff`, `deal_created`, `order_confirmed`), `count` (INTEGER DEFAULT 1), `metadata` (JSONB DEFAULT `{}`), `synced_at` (TIMESTAMPTZ DEFAULT NOW())
☑ Constraint UNIQUE em `(event_date, campaign_ref, ad_ref, event_type)` para idempotência
☑ Índices em `(event_date DESC)`, `(campaign_ref)`, `(event_type)`, `(event_date, campaign_ref)`
☑ RLS habilitado: `service_role` tem acesso total; `authenticated` pode SELECT; `anon` sem acesso
☑ Agente: @data-engineer
☑ Script criado em `squads/traffic-ads/scripts/sync-traffic-events.js`
☑ Conecta ao PostgreSQL local (`propek_bot`) em modo read-only (sem INSERT/UPDATE/DELETE)
☑ Executa 5 queries de agregação (uma por `event_type`) para a data corrente
☑ Faz upsert no Supabase (tabela `traffic_events`) via REST API (stdlib https, ZERO deps externas)
☑ Zero PII no payload — apenas contadores agrupados por `campaign_ref + event_date + event_type`
☑ Suporta argumento de data: `node sync-traffic-events.js --date 2026-04-01` (default: ontem)
☑ Log local em `/var/log/sync-traffic-events.log` com resultado de cada run (linhas inseridas/atualizadas)
☑ Cron entries documentadas em `squads/traffic-ads/docs/vps-cron.md` (08:00 e 20:00 BRT = 11:00 e 23:00 UTC)
☑ Agente: @dev
☑ Nenhum campo com dado pessoal (nome, telefone, CPF, email) é lido pelas queries de agregação
☑ Todas as queries usam `COUNT(*)` — sem SELECT de campos de identificação
☑ `metadata` só contém: `{avg_deal_value: N}` para `order_confirmed` — valor médio sem rastreabilidade
☑ @cyber-chief confirma LGPD compliance antes do Task 5
☑ Nova função `loadConversionData(date)` lê `traffic_events` do Supabase para a data
☑ Nova função `calcNCAC(spend, ordersCount)` retorna nCAC ou `null` se ordersCount = 0
☑ Regras de decisão implementadas usando constante `NCAC_RULES`:
☑ Relatório diário inclui campo `nCAC Real` por campanha (ex: `3 pedidos | nCAC R$18,00`)
☑ Se sem dados de conversão: campo exibe `"sem dados de conversão"` (sem erro)
☑ Agente: @dev
☑ Busca `traffic_events` dos últimos 7 dias por campanha via Supabase
☑ Monta bloco de texto "Funil de Conversão por Campanha" no prompt para a IA
☑ Bloco inclui: conversas iniciadas, leads qualificados, handoffs, deals criados, pedidos confirmados, nCAC real, CPC WhatsApp, taxa de conversão funil
☑ IA recebe contexto suficiente para identificar qual campanha traz lead bom vs ruim
☑ Agente: @dev
☑ weekly-ai-analysis.js inclui instrução explícita no prompt para comparar campanhas por `order_confirmed / conversation_started` (taxa de conversão funil completo)
☑ Relatório semanal gerado inclui seção "Qualidade de Lead por Campanha"
☑ Agente: @dev
☑ Zero PII no Supabase confirmado (nenhum campo de identificação pessoal na tabela `traffic_events`)
☑ Credenciais PostgreSQL VPS (`DB_*`) ficam APENAS no `.env` do VPS — nunca no repositório
☑ `SUPABASE_SERVICE_KEY` no VPS é chave diferente das usadas pelos scripts de tráfego no repo
☑ RLS correto valida que anon não acessa `traffic_events`
☑ Emitir gate PASS/FAIL antes de @qa