9874eb4345
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
71 lines
4.2 KiB
Markdown
71 lines
4.2 KiB
Markdown
# Integração NewWhats (satélite) — scoreodonto.com ↔ Motor
|
|
|
|
> **Único deste projeto** (scoreodonto.com). Clonado e **adaptado ao domínio
|
|
> odonto** a partir do satélite do `mercado.clube67.com`. Backend **ESM** — sem o
|
|
> host de plugins do mercado; é um módulo registrado no `server.js`. v1.0.0.
|
|
|
|
## ⚠️ Regra de registro bidirecional (obrigatória)
|
|
- Toda mudança que toque o contrato (rotas, payloads, auth, webhook) **deve ser
|
|
registrada no motor** e na doc central
|
|
`documentos-unicos/projetos/newwhats.clube67.com/integracao-satelites.md`.
|
|
- Toda mudança no motor que afete o contrato **deve ser refletida aqui**.
|
|
- O satélite é um **braço inteligente do motor** — consome/alimenta, não duplica.
|
|
|
|
## Diferenças vs o satélite do mercado
|
|
- **ESM** (não CommonJS) e **sem PluginManager** — registrado via
|
|
`registerNewwhats(app, pool)` no `server.js`.
|
|
- **Config por ENV** (não tabela `plugin_configs`): `NEWWHATS_URL`,
|
|
`NEWWHATS_INTEGRATION_KEY`, `NEWWHATS_WEBHOOK_SECRET`, `NEWWHATS_CLINICA_ID`.
|
|
- **Negócio adaptado ao odonto**: `/nw/*` e `sync-knowledge` usam
|
|
clínica/especialidades/dentistas/procedimentos/planos (multi-tenant por
|
|
`clinica_id`), no lugar de clubes/sorteio/vagas.
|
|
- **Removidos** (não úteis aqui): `media-transcribe` (o motor já transcreve —
|
|
ver Fase 5), `smart-router`, `personas`, `follow-up-detector`, `context-builder`
|
|
(heurísticas específicas do mercado). Reavaliar se necessário.
|
|
|
|
## Arquivos
|
|
| Arquivo | Papel |
|
|
|---|---|
|
|
| `config.js` | lê a config da integração das ENV |
|
|
| `auth.js` | `nwAuth` — valida `x-nw-key`/Bearer nas rotas `/nw/*` |
|
|
| `routes.js` | `/nw/*` odonto: `/ping`, `/clinica`, `/especialidades`, `/dentistas`, `/procedimentos`, `/planos` |
|
|
| `sync-knowledge.js` | `buildKnowledgeText(pool, clinicaId)` + `syncKnowledge(pool)` → motor `/api/secretaria/*` |
|
|
| `webhook-receiver.js` | `POST /api/webhook/newwhats` (HMAC) — `message.new`, `session.status` (enxuto) |
|
|
| `proxy.js` | `/api/nw/v1/*` → motor `/api/ext/v1/*` (injeta `x-nw-key`) |
|
|
| `index.js` | `registerNewwhats(app, pool)` — registra tudo |
|
|
| `manifest.json` | metadados + `config_env` |
|
|
|
|
## Contrato (resumo)
|
|
- **Satélite → Motor**: proxy `/api/nw/v1/*` → ext-api `/api/ext/v1/*` (Bearer/x-nw-key);
|
|
`sync-knowledge` → `/api/secretaria/*`.
|
|
- **Motor → Satélite**: webhook `POST /api/webhook/newwhats` (HMAC `webhook_secret`);
|
|
Secretária consulta `/nw/*` (`integration_key`).
|
|
|
|
## Frontend (React SPA)
|
|
- Plugin `newwhats` registrado em `frontend/views/PluginsView.tsx` (catálogo
|
|
PLUGINS) — **config exclusiva do superadmin** (a view `plugins` já é gateada em
|
|
`App.tsx isViewAllowed`).
|
|
- `ALWAYS_ON` em `pluginRegistry.ts` → Inbox/Secretária aparecem para **todos** os
|
|
usuários (a ativação por plugin é localStorage e não propaga entre contas).
|
|
- Views: `frontend/views/WaInboxView.tsx` (conversas/thread/envio) e
|
|
`WaSecretariaView.tsx` (ask) — consomem `/api/nw/v1/*`. **Estágio 1** (funcional,
|
|
visual aproximado do motor; refinar para ficar idêntico).
|
|
- Sidebar: itens WHATSAPP + SECRETÁRIA IA (gated por `isPluginActive('newwhats')`).
|
|
|
|
## Pendências / TODO
|
|
- [ ] **Segurança**: gatear o proxy `/api/nw/v1/*` com a auth do scoreodonto (hoje
|
|
aberto — qualquer um que alcance a rota é proxiado ao motor).
|
|
- [x] **Ponte de config** (feito): config persiste na tabela `settings`
|
|
(`id=newwhats_config`); backend lê do DB com fallback ENV
|
|
(`config.js loadConfigFromDb`). UI dedicada (`NewwhatsConfigModal`) com
|
|
**dropdown de clínicas**, secrets que mantêm valor se em branco e **Testar
|
|
conexão** (`GET /api/nw/status`). Endpoints superadmin: `GET/PUT /api/nw/config`,
|
|
`GET /api/nw/clinicas`, `GET /api/nw/status`.
|
|
- [ ] `webhook message.new`: capturar lead / acionar fluxo (hoje só loga).
|
|
- [ ] Proxy WS (`/api/nw/v1/stream`) — só o REST foi portado (Inbox sem tempo real).
|
|
- [ ] Parear scoreodonto com o motor (criar apiKey/pair + agente) e preencher as ENV.
|
|
- [ ] Endpoint/admin para disparar `syncKnowledge` (hoje exportado, sem rota).
|
|
- [ ] Refinar Inbox/Secretária para ficarem idênticas ao motor.
|
|
|
|
> Fonte da verdade do contrato: `documentos-unicos/projetos/newwhats.clube67.com/`.
|