Pular para conteúdo

Conformidade com Diretrizes da Meta

Status: Documento de referencia, atualizado em 2026-06-02

Aplicacao: Sistema ChatBot Survey integrado com Meta WhatsApp Business Cloud API v22.0

Este documento descreve como o sistema se alinha com as regras da Meta para mensageria via WhatsApp Business API, e quais lacunas ainda precisam ser endereçadas.


Regras Fundamentais da Meta

1. Janela de Atendimento de 24h (Customer Service Window)

Quando um usuario envia mensagem para o numero comercial, abre uma janela de 24 horas durante a qual o negocio pode enviar mensagens de texto livres (nao templates).

  • Dentro da janela: texto livre, audio, video, imagem, documento
  • Fora da janela: apenas templates aprovados

2. Templates Aprovados (Business-Initiated)

Para iniciar conversas (sem ter recebido msg do cliente nas ultimas 24h), o negocio deve usar templates pre-aprovados.

Categorias: - MARKETING - promocional (exige opt-out) - UTILITY - transacional (confirmacao, lembrete) - AUTHENTICATION - 2FA

3. Quality Rating

A Meta atribui um quality rating ao numero comercial baseado em: - Volume de bloqueios pelos usuarios - Reports de spam - Frequencia de envio

Rating pode ser: GREEN, YELLOW, RED, FLAGGED, RESTRICTED.


Alinhamento Atual do Sistema

✅ Janela de 24h respeitada

Implementacao: backend/chat/services.py:ChatService._validate_can_send()

Python
last_incoming = MessageLog.objects.filter(
    phone=phone, direction='in'
).order_by('-created_at').first()

if last_incoming:
    hours_since = (now - last_incoming.created_at).total_seconds() / 3600
    if hours_since > 24:
        raise ValueError(
            'Janela de 24 horas expirada. ...Use um template aprovado pela Meta.'
        )

Cobertura: - Operador no chat livre: bloqueado se passou 24h sem msg IN do cliente - Bot durante pesquisa: regra C (in_progress expira em 24h) garante que o bot nao continue tentando responder fora da janela

✅ Templates para iniciar conversa

Implementacao: MetaGraphService.send_initial_survey_message() em backend/whatsapp/services/meta_graph_service.py

Survey configurada com:

Python
1
2
3
4
5
6
use_whatsapp_template = True
whatsapp_template_name = 'highlas'  # nome do template aprovado
whatsapp_template_language = 'pt_BR'
whatsapp_template_params = [
    {'type': 'header', 'field': 'first_name', 'index': 0, 'paramType': 'text'}
]

O sistema so envia template para iniciar conversa. Apos o cliente responder SIM (entrando em in_progress), as proximas perguntas sao enviadas como mensagens regulares dentro da janela de 24h.

✅ Bloqueio de reenvio responsavel

Implementacao: backend/surveys/views.py:start_survey()

Antes de criar nova run, verifica se ha run ativa para o mesmo (survey, contact). Se houver e nao expirou, bloqueia o disparo com payload estruturado informando o tempo restante.

Isso evita: - Spam de templates para o mesmo contato - Duplicacao de execucoes - Custos desnecessarios (cada template envia paga)

✅ Opt-out via botao

Implementacao: backend/whatsapp/services/survey_service.py

Cliente pode recusar a pesquisa respondendo "NAO" no botao de confirmacao. A run e marcada como opt_out e nao recebe mais mensagens.

✅ Expiracao automatica = nao "esperar eternamente"

Implementacao: task expire_stale_runs (ver expiracao-pesquisas.md)

Apos as janelas configuradas (24h/72h/24h), runs sao automaticamente marcadas como expired, liberando o reenvio futuro.


⚠️ Gaps Conhecidos

Gap 1: HMAC do Webhook Pendente

Risco: MEDIO-ALTO

A Meta recomenda validar a assinatura HMAC-SHA256 do webhook usando o App Secret. Sem isso, terceiros podem enviar webhooks falsos para a aplicacao.

Status: aguardando META_APP_SECRET do cliente Highlas (vide memory project_hmac_pending.md).

Acao: implementar middleware/decorator que valida X-Hub-Signature-256 header antes de processar webhook.

Python
# Esqueleto sugerido
import hmac, hashlib
def verify_meta_signature(request) -> bool:
    signature = request.headers.get('X-Hub-Signature-256', '')
    expected = 'sha256=' + hmac.new(
        META_APP_SECRET.encode(),
        request.body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

Gap 2: Cooldown de Reenvio Apos Expiracao

Risco: MEDIO

Atualmente, assim que uma run expira (ou e cancelada manualmente), o operador pode disparar nova pesquisa imediatamente para o mesmo contato. Em volume, isso pode: - Degradar quality rating se cliente final marcar como spam - Gerar custos repetitivos - Irritar contatos que ja optaram por nao participar

Acao sugerida: adicionar campo cooldown_until ou usar completed_at + janela minima (ex: 7 dias). Validar em start_survey:

Python
1
2
3
4
5
6
7
8
9
if existing_completed_run := SurveyRun.objects.filter(
    survey=survey, contact=contact, status='expired',
    completed_at__gt=now - timedelta(days=7)
).first():
    failed_results.append({
        'error_code': 'recent_expiration_cooldown',
        'cooldown_ends_at': existing_completed_run.completed_at + timedelta(days=7),
        ...
    })

Gap 3: Opt-out por Palavra-Chave

Risco: BAIXO (mas critico se template for MARKETING)

Templates de categoria MARKETING exigem mecanismo de opt-out por texto. Hoje so capturamos opt-out via botao "NAO".

Acao sugerida: em survey_service.process_incoming_message(), detectar palavras como PARAR, STOP, CANCELAR, SAIR, DESCADASTRAR e marcar contato como opt-out global (impede futuros disparos para esse numero).

Gap 4: Janela 24h durante in_progress pode estourar silenciosamente

Risco: BAIXO

Cenario: 1. Cliente responde SIM ao template 2. Bot envia pergunta 1 3. Cliente leva > 24h para responder 4. Cliente responde 5. Bot tenta enviar pergunta 2 -> a Meta rejeita (fora da janela)

Hoje a rejeicao seria logada como failed no MessageLog, mas a run continua in_progress ate a regra C marcar como expired (mais 24h depois). Cliente final fica em limbo.

Acao sugerida: ao detectar erro 131047 da Meta (re-engagement message), marcar a run como expired imediatamente e logar o motivo.

Gap 5: Codigos de Erro Especificos Nao Tratados

Risco: BAIXO

A Meta retorna codigos de erro especificos que poderiam alimentar decisoes automaticas:

Codigo Significado Acao sugerida
131026 Mensagem nao entregavel (numero invalido) mark_as_expired() + flag no Contact
131047 Re-engagement needed (fora da janela 24h) mark_as_expired()
131056 Rate limit do par (sender, recipient) hit Aguardar e retry com backoff
131051 Tipo de mensagem nao suportado Log e descarta

Hoje todos os erros sao logados de forma generica em meta_graph_service.py mas nao geram acoes diferenciadas.

Gap 6: Quality Rating Nao Monitorado

Risco: BAIXO

A Meta envia webhooks com account_update e phone_number_quality_update. Hoje o sistema ignora silenciosamente esses webhooks (so processa messages e statuses).

Acao sugerida: criar handler para account_update. Se rating cair para RED, FLAGGED ou RESTRICTED, enviar email de alerta para o admin.


Auditoria e Logs

Toda mensagem trocada e registrada em MessageLog:

Python
MessageLog(
    direction='in' | 'out',
    phone='5511999999999',
    source='survey' | 'chat' | 'system',
    payload={...},  # JSON do payload Meta original
    status='sent' | 'delivered' | 'read' | 'failed',
    wa_message_id='wamid....',
    run=<SurveyRun>,           # se aplicavel
    operator=<User>,            # se enviada manualmente pelo chat
)

Permite reconstruir o historico completo de comunicacao com qualquer contato para fins de auditoria, disputa ou debugging.


Roadmap de Conformidade

Priorizacao sugerida (vide roadmap-gaps.md):

Prioridade Item
🔴 ALTA HMAC do webhook (assim que receber App Secret)
🟡 MEDIA Cooldown de reenvio (Gap 2)
🟡 MEDIA Tratamento de 131026 e 131047 (Gap 5 parcial)
🟢 BAIXA Opt-out por keyword (Gap 3)
🟢 BAIXA Quality rating monitoring (Gap 6)

Referencias Externas