Ingress Canônico de Webhooks WhatsApp na Borda VPS (Traefik v3)
1. Topologia e Isolamento de Rede
Para eliminar o acoplamento no runtime serverless e mitigar AMQP connection churn, o serviço yzex-worker-service opera como Ingress Gateway de Borda nativo em Node.js (porta 3001), conectado diretamente à rede privada interna yzex-network.
INTERNET
│ :443 (TLS Let's Encrypt)
▼
[Traefik v3 (Container Docker em yzex-network)]
│ Middleware: body-limit (10MB)
│ Middleware: rate-limit (100 req/s, burst 50)
▼ HTTP Privado (DNS Docker: http://yzex-worker-service:3001)
[yzex-worker-service (Container Docker em yzex-network)]
│ 1. Header Auth (Constant-Time crypto.timingSafeEqual)
│ 2. Guardrails (POST, Content-Type, Stream < 10MB)
│ 3. Fast-Path Deduplication (IN_FLIGHT -> CONFIRMED)
│ 4. Publisher Confirms (mandatory: true, deliveryMode: 2)
▼ AMQP 0-9-1 Persistente (Zero Churn)
[RabbitMQ 4.1.8 Cluster (yzex-rabbitmq:5672)]
│ Exchange: yzex.events (Topic, Durable)
▼ Routing Key: yzex.events.connect.whatsapp.legacy_forward
[Queue: yzex-connect-whatsapp-legacy-forward-queue]
2. Resoluções Canônicas SRE (P0/P1)
2.1 Desacoplamento de Boot & Healthchecks Semânticos (P0-2)
-
O servidor HTTP sobe de forma 100% síncrona e independente da conectividade com RabbitMQ ou Temporal.
-
/healthz(Liveness Probe): Responde200 OKimediatamente no boot do Node.js, prevenindo reinícios destrutivos pelo orquestrador enquanto o broker reconecta. -
/readyz(Readiness Probe): Responde503 Service Unavailableenquanto a conexão AMQP não estiver pronta. Comuta para200 OKassim que o canal de publicação com confirmação é estabelecido.
2.2 Máquina de Estados de Deduplicação Fast-Path (P0-3 / P1-3)
-
Memória LRU Local: Retém até 20.000 entradas com TTL de 30 minutos para absorver picos de rajada e retentativas imediatas do provedor.
-
Ciclo de Estados:
-
Requisição inédita: Registrada como
IN_FLIGHT. -
Requisição concorrente com chave idêntica em
IN_FLIGHT: Retorna429 Too Many Requestscom headerRetry-After: 2. -
Falha de publicação (Timeout, NACK,
basic.return): A chave é imediatamente expurgada da tabela de deduplicação, permitindo que o provedor tente novamente sem falsos positivos. -
Confirmação do Broker (ACK durável): Comuta para
CONFIRMED. -
Retry posterior com estado
CONFIRMED: Retorna200 OKcom{"status": "ALREADY_PROCESSED"}.
-
-
Segregação Epistêmica: O Ingress atua como Fast-Path Local. A autoridade definitiva de idempotência contra falhas concorrentes de longo prazo é mantida no banco relacional
rocketz.webhookse no consumidor assíncrono.
2.3 Tratamento Rigoroso de Mensagens Não Roteáveis (P0-4)
-
Confirmação formal:
\$PUBLISHED\_CONFIRMED = publisher\_confirm(ACK) \land \neg basic.return \land \neg timeout\$ -
Um listener dedicado monitora eventos de
channel.on('return'). Mensagens devolvidas pelo broker por falta de filas correspondentes são classificadas comoUNROUTABLE_MESSAGE, resultando emHTTP 503e expurgo da chave para reprocessamento.
2.4 Ordem Estrita de Encerramento Gracioso (P0-5)
-
setIngressReady(false): O endpoint/readyzpassa a responder503, fazendo o Traefik desviar novas conexões. -
server.close(): Listener TCP interrompe o aceite de novos sockets. -
Dreno de Requisições HTTP Ativas: Aguardo das requisições em voo com teto de 5.000 ms.
-
Dreno de Confirms AMQP: Confirmação das mensagens pendentes no canal RabbitMQ.
-
Fechamento de Workers, Canais e Pools de Banco.
2.5 Defesa em Profundidade de Tamanho e Autenticação (P1-1 / P1-2)
-
Limite de Payload: Middleware Traefik
body-limit(10 MB) na borda, headerContent-Length > 10MBrecusado com413no Node.js e monitoramento intra-stream abortando a requisição caso ultrapasse 10 MB. -
Autenticação em Tempo Constante: Prioridade estrita (
Authorization: Bearer>X-Webhook-Token>apikey> query fallback). Rejeição com401em caso de múltiplos métodos ambíguos. Comparação dos digests SHA-256 viacrypto.timingSafeEqual.
3. Contrato Formal da API HTTP
3.1 Endpoints HTTP Homologados
-
Endpoint Canônico Padronizado:
POST /v1/webhooks/integrations/whatsapp -
Endpoint Legado de Compatibilidade:
POST /api/integrations/whatsapp/webhook -
FQDN Público:
https://api.connect.yzex.com.br/v1/webhooks/integrations/whatsapp
| Status | Código Semântico | Condição / Significado |
|---|---|---|
|
|
Mensagem validada, persistida em fila durável com ACK do broker e sem devoluções. |
|
|
Requisição duplicada com estado prévio |
|
|
JSON malformado ou payload vazio. |
|
|
Credenciais ausentes, inválidas ou ambíguas. |
|
|
Verbo diferente de |
|
|
Corpo da requisição excede 10 MB. |
|
|
Content-Type diferente de |
|
|
Evento idêntico em voo sendo processado no momento. |
|
|
Broker desconectado, timeout de confirm (3.000 ms) ou mensagem não roteável ( |
4. Telemetria e SLIs/SLOs de Confiabilidade
O Ingress expõe métricas nativas em /metrics no formato Prometheus:
-
webhook_ingress_requests_total{status}: Totalizadores por desfecho operacional. -
webhook_ingress_latency_ms{type="http_total_avg"}: Latência total de borda (SLO: p95 < 60 ms). -
webhook_ingress_latency_ms{type="amqp_confirm_avg"}: Tempo exclusivo de confirmação de escrita em disco do RabbitMQ. -
webhook_ingress_dedup_hits_total{state="CONFIRMED"}: Taxa de absorção de requisições duplicadas. -
webhook_ingress_unroutable_total: Alertas de desvio de topologia AMQP. -
webhook_ingress_inflight_current: Gauge de saturação de conexões em tempo real.