# WA-AKG Setup — PX3 Lab

Self-hosted WhatsApp Gateway (Baileys + Next.js 15 + Prisma + MySQL),
instalado via docker-compose em `/opt/mia/services/wa-akg/`. Vai ser usado
inicialmente pela **Monique (PX3 Lab, 5511934313883)**.

> **Status atual:** infra 100% pronta. Nenhum WhatsApp conectado ainda.

---

## URLs e credenciais

- Dashboard: **https://wa-akg.agentesclimb.us**
- Swagger (API docs): **https://wa-akg.agentesclimb.us/docs**
- Login SuperAdmin:
  - email: `renato@agenciaclimb.com.br`
  - senha: `hEZ5sxZmx3d0yhBASNSfCA`
- Swagger basic auth (quando pedir):
  - user: `admin`
  - pass: `sF1zPU4u8g26FOxz12Xggg`

> **Fonte canônica dos secrets:** `/opt/mia/config/wa_akg.env` (chmod 600).
> O compose consome `/opt/mia/services/wa-akg/.env` (mesmo conteúdo).

---

## Arquitetura

```
Internet
   │ https://wa-akg.agentesclimb.us
   ▼
Traefik (EasyPanel, :443)   ──► http://172.18.0.1:8970
                                    │
                                    ▼
                           wa-akg-app (Next.js 15, Baileys)
                                    │  TCP interno
                                    ▼
                           wa-akg-db (MySQL 8.0, só rede do compose)

Webhook de evento (WhatsApp recebeu msg etc.) sai do wa-akg-app
   │
   ▼
wa-akg-receiver (Flask, 127.0.0.1:8971)  ──► /opt/mia/logs/wa_akg_<slug>.jsonl
```

- Porta externa do app: **8970** (bind em `172.18.0.1`, só a bridge do Docker).
- MySQL: **não exposto no host**, só rede interna do compose.
- DNS: `wa-akg.agentesclimb.us A 72.61.51.166` (Cloudflare, proxy OFF, TTL 300).
- TLS: Let's Encrypt automático via Traefik (`certResolver: letsencrypt`).

---

## Como mexer no serviço

Tudo via docker compose (precisa `sudo`):

```bash
cd /opt/mia/services/wa-akg

# status
sudo docker compose ps

# logs do app
sudo docker compose logs -f app

# logs do mysql
sudo docker compose logs -f db

# restart só do app
sudo docker compose restart app

# derrubar tudo (dados persistem nos volumes)
sudo docker compose down

# subir
sudo docker compose up -d

# rebuild (quando atualizar o repo WA-AKG)
sudo docker compose build --pull && sudo docker compose up -d
```

Volumes persistentes (dados nunca somem num `down`):
- `wa-akg_mysql_data`  → banco MySQL
- `wa-akg_app_data`    → sessões Baileys (auth state)
- `wa-akg_uploads_data`→ mídia enviada/recebida

---

## Criar uma instância WhatsApp (quando o cliente for conectar)

1. Logar no dashboard: https://wa-akg.agentesclimb.us
2. Menu **Sessions** → **New Session**
3. Dar nome que identifique o cliente (ex: `monique-px3`)
4. Clicar em **Connect** → aparece QR code
5. No celular do cliente, abrir WhatsApp → Aparelhos conectados → Conectar aparelho → escanear
6. Status muda pra **Connected** em ~5s

**Tempo pra Monique conectar:** ~1 min. Precisa ter o número 5511934313883
logado no WhatsApp mobile dela.

> **Atenção anti-ban:** mesma categoria do Evolution/Baileys em geral — API não-oficial,
> cuidado com broadcast em massa pra números frios, delays randomizados, warmup.
> O próprio WA-AKG já traz anti-ban com delays 10-30s em broadcasts.

---

## Configurar webhook pro receiver

Após conectar o WhatsApp, no dashboard:

1. Menu **Webhooks** → **Add Webhook**
2. URL: `http://172.18.0.1:8971/webhook/monique?secret=<WA_AKG_WEBHOOK_SECRET>`
   - Pegar `<WA_AKG_WEBHOOK_SECRET>` de `/opt/mia/config/wa_akg.env`
3. Eventos: marcar pelo menos `message.received`, `message.status`, `connection.update`
4. Salvar e testar com botão **Test Webhook**

> O receiver escuta em `127.0.0.1:8971`, mas o container do WA-AKG resolve
> `172.18.0.1` como gateway da bridge → chega no host → chega no receiver.
> Pra isso funcionar, o receiver precisa estar bindado em `0.0.0.0` ou escutar
> na interface `docker0`/`172.18.0.1`. **Hoje bindamos só 127.0.0.1** (não
> ativado em systemd ainda) — ao subir pra produção, trocar o bind no
> `app.py:124` ou mudar o Flask pra `host="172.18.0.1"`.

---

## Receiver (prep básica, não ativo ainda)

- Código: `/opt/mia/workspace/clientes/px3lab/wa_akg_receiver/app.py`
- Deps: Flask (venv local)
- Systemd template: `wa_akg_receiver.service.template` (nessa pasta)
- Loga em: `/opt/mia/logs/wa_akg_<slug>.jsonl`

**Smoke test manual já rodou com sucesso:**
- `GET /health` → 200
- `POST /webhook/monique` sem secret → 401
- `POST /webhook/monique?secret=...` com payload → 200 + JSONL gravado

Pra ativar em systemd quando a Monique conectar:

```bash
sudo cp /opt/mia/workspace/clientes/px3lab/wa_akg_receiver/wa_akg_receiver.service.template \
        /etc/systemd/system/wa_akg_receiver.service
# ajustar bind host no app.py pra "172.18.0.1" se o WA-AKG precisar bater via docker0
sudo systemctl daemon-reload
sudo systemctl enable --now wa_akg_receiver
systemctl status wa_akg_receiver
```

---

## Integração futura com Linkia PX3 (TODO)

Hoje o receiver só armazena em JSONL. Pra espelhar como nota no GHL:

1. Ler payload do evento `message.received`
2. Normalizar `from` (JID → E.164)
3. Buscar contato no Linkia PX3 por `phone` (API `GET /contacts/?query=...`)
4. Criar nota: `POST /contacts/{id}/notes` com `body = conteudo da msg`

Credenciais Linkia PX3: `/opt/mia/workspace/clientes/px3lab/config_ghl.py`
(location `W7PGxpfbsFaEEUoQOtUb`, token `PX3_TOKEN`).

---

## Gotchas / limitações encontradas

1. **Repo usa MySQL, não PostgreSQL.** O brief falava "Postgres", mas o Prisma
   schema está travado em `provider = "mysql"`. Trocar exigiria regerar schema,
   patches de migrations e risco de quebrar funcionalidade. Mantivemos MySQL
   8.0, isolado em container próprio.

2. **Node 26 alpine (bleeding edge).** O Dockerfile oficial usa `node:26-alpine`.
   Já apareceram community issues sobre isso. Se der problema de build, baixar
   pra `node:22-alpine` no `Dockerfile:1` e reconstruir.

3. **Primeiro boot demora.** Prisma `db push` roda no `CMD` da imagem, então o
   `wa-akg-app` só fica saudável depois do MySQL subir + schema criar + Next.js
   iniciar. Esperar 60-90s antes de bater no HTTPS. Olhar `docker compose logs -f app`.

4. **AUTH_SECRET imutável.** Se trocar o `AUTH_SECRET` depois de ter sessões
   ativas, todo mundo é deslogado e sessões Baileys podem precisar re-pareamento.

5. **Sem Redis.** Diferente do Evolution, WA-AKG não usa Redis — tudo passa pelo
   MySQL. Simplifica mas pode gargalar com muitas sessões simultâneas (10+).

6. **Bind no 172.18.0.1.** Expomos a porta 8970 só na bridge do Docker, não em
   `0.0.0.0`. Significa que **só o Traefik (que mora na mesma bridge) chega
   nela**. Direto do host via `curl http://localhost:8970` **não funciona** —
   use `curl http://172.18.0.1:8970` ou passe pelo HTTPS.

7. **Risco de ban.** API não-oficial Baileys. Não usar o número do Renato nem
   contas corporativas no primeiro teste. Começar com número descartável
   (Monique OK porque é número de atendimento, não pessoal).

---

## Arquivos relevantes

| Caminho | O que é |
|---|---|
| `/opt/mia/services/wa-akg/` | Código fonte + docker-compose |
| `/opt/mia/services/wa-akg/.env` | Env consumida pelo compose |
| `/opt/mia/config/wa_akg.env` | **Fonte canônica dos secrets (chmod 600)** |
| `/etc/easypanel/traefik/config/custom.yaml` | Routers + service wa-akg (linhas 1075-1088 e 1350-1353) |
| `/opt/mia/workspace/clientes/px3lab/wa_akg_receiver/app.py` | Receiver Flask |
| `/opt/mia/logs/wa_akg_*.jsonl` | Logs de eventos (um JSONL por slug) |

---

## Changelog

- **2026-10-09** — infra criada: DNS + Traefik + docker-compose + receiver.
  Nenhuma instância WhatsApp conectada ainda. Aguardando Renato autorizar
  Monique a escanear QR.
