docs(newwhats): tarefas, wasabi/mídias, ativação inteligente e regra bidirecional
- tarefas.md: checklist mestre de pendências (fases 3-5, wasabi, ativação) - wasabi-midias.md: estado + index/delete em lote (DB↔Wasabi, retenção) - ativacao-whatsapp.md: trajeto inteligente de provisionamento no motor - integracao-satelites.md: regra de registro bidirecional + plugin único por projeto Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
# newwhats.clube67.com — Ativação do WhatsApp (trajeto inteligente)
|
||||||
|
|
||||||
|
> Estado atual + desenho do "trajeto" desejado. Meta: cada ativação de um WhatsApp
|
||||||
|
> **cria e configura uma conta no motor de forma inteligente**, com o plugin
|
||||||
|
> satélite atuando como **braço inteligente do motor**. Última revisão: 28/jun/2026.
|
||||||
|
|
||||||
|
## Como funciona hoje (mínimo)
|
||||||
|
1. `POST /api/instances/` `{ name }` → cria a instância (`repo.create(tenantId, name)`).
|
||||||
|
2. `POST /api/instances/:id/connect` → `manager.connect` emite **QR via Socket.IO**.
|
||||||
|
3. `GET /api/instances/:id/qr` → QR em base64 (Dragonfly `instance:{id}:qr`).
|
||||||
|
4. Pareamento de plugin (separado): `PairService` (OTP por email → `PluginPair`
|
||||||
|
com `integration_key`), valida o satélite via `verify(integration_key)`.
|
||||||
|
|
||||||
|
**Limitação:** a instância nasce "crua" (só `name`). Setor, secretária, webhook,
|
||||||
|
engine e detecção Business são passos manuais/dispersos.
|
||||||
|
|
||||||
|
## Trajeto desejado (provisionamento guiado e idempotente)
|
||||||
|
Ao ativar um WhatsApp, o motor (orquestrado pelo satélite) deve executar, em ordem
|
||||||
|
e **idempotente** (re-rodar não duplica):
|
||||||
|
|
||||||
|
1. **Conta/tenant** — garantir tenant + `PluginPair` (se ativação vem de satélite,
|
||||||
|
usa `integration_key`; senão cria pelo admin).
|
||||||
|
2. **Instância** — criar com `name`, `engine` default (baileys7 = "API estável") e
|
||||||
|
flags (`isBusiness` será detectada no connect).
|
||||||
|
3. **Conexão** — `connect` → QR; ao conectar, **detectar Conta Business** e gravar
|
||||||
|
`isBusiness`; avisar que trocar de API exige re-escanear QR.
|
||||||
|
4. **Setor + Secretária default** — criar setor padrão e um agente de Secretária
|
||||||
|
base (persona/regras mínimas) já ligado à instância.
|
||||||
|
5. **Webhook** — registrar o webhook do satélite (`webhook_secret`/HMAC) p/
|
||||||
|
`message.new` e `session.status`.
|
||||||
|
6. **Conhecimento inicial** — disparar `sync-knowledge` do satélite (Fase 4) para o
|
||||||
|
RAG nascer populado.
|
||||||
|
7. **Resumo** — devolver ao operador o estado final (conectado, Business?, setor,
|
||||||
|
secretária, webhook ok) — "trajeto" visível, não caixa-preta.
|
||||||
|
|
||||||
|
## Papel do satélite (braço inteligente)
|
||||||
|
- O satélite **não duplica** o motor: ele dispara o trajeto, fornece dados do
|
||||||
|
negócio (`/nw/*`, `sync-knowledge`) e consome inbox/secretária via proxy.
|
||||||
|
- Toda configuração persiste **no motor** (fonte da verdade). O satélite guarda só
|
||||||
|
as chaves de conexão (`plugin_configs`).
|
||||||
|
- Qualquer passo novo do trajeto deve ser refletido nos dois lados (ver regra de
|
||||||
|
registro bidirecional em [integracao-satelites.md](integracao-satelites.md)).
|
||||||
|
|
||||||
|
## Pendência / implementação
|
||||||
|
- [ ] Endpoint de provisionamento (`POST /api/instances/provision`) que encapsula os
|
||||||
|
passos 1–7 de forma idempotente, com resposta de "trajeto".
|
||||||
|
- [ ] Detecção Business no `connect` gravando `isBusiness`.
|
||||||
|
- [ ] Setor + Secretária default automáticos.
|
||||||
|
- [ ] Registro de webhook automatizado a partir do pair.
|
||||||
|
- [ ] Gatilho de `sync-knowledge` no fim do trajeto.
|
||||||
|
</content>
|
||||||
@@ -5,6 +5,21 @@
|
|||||||
> `newwhats` v2.1.0) consome o motor e fornece dados do seu negócio.
|
> `newwhats` v2.1.0) consome o motor e fornece dados do seu negócio.
|
||||||
> Fonte da verdade do contrato (auditado em 28/jun/2026).
|
> Fonte da verdade do contrato (auditado em 28/jun/2026).
|
||||||
|
|
||||||
|
## ⚠️ Regra de registro bidirecional
|
||||||
|
- **Cada plugin satélite é ÚNICO do projeto onde está instalado** — o `newwhats`
|
||||||
|
do `mercado.clube67.com` pode divergir do de outro projeto. Não copiar cego.
|
||||||
|
- **Toda mudança no plugin** que toque o contrato deve ser registrada **no motor**
|
||||||
|
e nesta doc; **toda mudança no motor** que afete o contrato deve ser refletida no
|
||||||
|
doc do plugin (`INTEGRACAO-MOTOR.md`, dentro de cada plugin).
|
||||||
|
- O plugin é um **braço inteligente do motor**: consome, alimenta e configura — não
|
||||||
|
duplica lógica do motor.
|
||||||
|
|
||||||
|
## Docs relacionadas
|
||||||
|
- [tarefas.md](tarefas.md) — checklist mestre de pendências.
|
||||||
|
- [wasabi-midias.md](wasabi-midias.md) — storage, index e delete em lote.
|
||||||
|
- [ativacao-whatsapp.md](ativacao-whatsapp.md) — trajeto inteligente de ativação.
|
||||||
|
- `INTEGRACAO-MOTOR.md` — dentro de cada plugin satélite (lado do satélite).
|
||||||
|
|
||||||
## Config do satélite (plugin_configs, manifest `newwhats`)
|
## Config do satélite (plugin_configs, manifest `newwhats`)
|
||||||
`newwhats_url` (URL do motor) · `integration_key` (x-nw-key, rotas `/nw/*`) ·
|
`newwhats_url` (URL do motor) · `integration_key` (x-nw-key, rotas `/nw/*`) ·
|
||||||
`api_token` (Bearer, envio de mensagens) · `webhook_secret` (HMAC do webhook).
|
`api_token` (Bearer, envio de mensagens) · `webhook_secret` (HMAC do webhook).
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# newwhats.clube67.com — Tarefas / Pendências (checklist)
|
||||||
|
|
||||||
|
> Lista mestra de pendências do motor ↔ satélites. Sincronizada com a task list
|
||||||
|
> da sessão. Atualizar marcando `[x]` ao concluir e mover detalhes para a doc de
|
||||||
|
> estado correspondente. Última revisão: 28/jun/2026.
|
||||||
|
|
||||||
|
## Regra de ouro (registro bidirecional)
|
||||||
|
- Cada **plugin satélite é único do projeto onde está instalado** (ex.: o
|
||||||
|
`newwhats` do `mercado.clube67.com` ≠ o de outro projeto).
|
||||||
|
- **Toda mudança no plugin deve ser registrada no motor, e toda mudança no motor
|
||||||
|
que afete o contrato deve ser registrada em cada plugin.** Ver
|
||||||
|
[integracao-satelites.md](integracao-satelites.md) (contrato central) e o
|
||||||
|
`INTEGRACAO-MOTOR.md` dentro de cada plugin.
|
||||||
|
- O **plugin é um braço inteligente do motor** — não duplica lógica; consome,
|
||||||
|
alimenta e configura o motor.
|
||||||
|
|
||||||
|
## Integração satélite ↔ motor (faseado)
|
||||||
|
- [x] **Fase 1** — Contrato documentado (`integracao-satelites.md`).
|
||||||
|
- [x] **Fase 2** — Compatibilidade de API: alias `GET /secretaria/numbers` no ext-api.
|
||||||
|
- [ ] **Fase 3** — Validar config/conexão (`newwhats_url`, `integration_key`,
|
||||||
|
`api_token`, `webhook_secret`) do satélite → motor (dev/prod) + HMAC do webhook.
|
||||||
|
_Bloqueado: requer credenciais reais._
|
||||||
|
- [ ] **Fase 4** — Rodar `sync-knowledge` end-to-end (satélite → motor) e validar RAG.
|
||||||
|
_Bloqueado: requer satélite rodando + Fase 3._
|
||||||
|
- [ ] **Fase 5** — Satélite consumir `messages.transcription` do motor e **remover
|
||||||
|
`media-transcribe.js`** redundante. Unificar fonte da chave Gemini
|
||||||
|
(`cfg.gemini_key` vs `process.env.GEMINI_API_KEY`).
|
||||||
|
|
||||||
|
## Wasabi / mídias
|
||||||
|
- [x] Upload fire-and-forget + proxy público de leitura (avatares e mídias).
|
||||||
|
- [x] `StorageProvider.deletePrefix(prefix)` (delete por prefixo).
|
||||||
|
- [ ] **Index de mídias** — listagem por tenant/instância/chat/período (auditoria + UI).
|
||||||
|
- [ ] **Delete em lote** — por instância, período ou chat, coordenado **DB ↔ Wasabi**
|
||||||
|
(sem órfãos). Endpoint admin seguro. Ver [wasabi-midias.md](wasabi-midias.md).
|
||||||
|
- [ ] Política de retenção (arquivar/descartar áudio após transcrição salva).
|
||||||
|
|
||||||
|
## Ativação do WhatsApp (trajeto inteligente)
|
||||||
|
- [ ] Transformar `POST /` + `POST /:id/connect` em um **trajeto guiado e idempotente**
|
||||||
|
que cria e configura a conta no motor automaticamente (instância, pair/tenant,
|
||||||
|
setor + secretária default, webhook, engine, detecção Business). Ver
|
||||||
|
[ativacao-whatsapp.md](ativacao-whatsapp.md). O satélite orquestra como braço do motor.
|
||||||
|
|
||||||
|
## Inbox / Secretária (já entregue nesta frente)
|
||||||
|
- [x] Transcrição/descrição no motor (Gemini) → `messages.transcription`.
|
||||||
|
- [x] Exibição da transcrição no inbox (🎤 áudio / 👁 imagem) + socket `message:transcription`.
|
||||||
|
- [x] Memória de longo prazo por contato (`sec_contact_memory`).
|
||||||
|
- [ ] Ritmo humano da Secretária (typing + delay + quebra em 2–3 msgs).
|
||||||
|
- [ ] Resposta em áudio (TTS) — opcional.
|
||||||
|
|
||||||
|
## Validações pendentes de ambiente
|
||||||
|
- [ ] Pareamento do WhatsApp dev (avatares/fixados) quando o aparelho voltar.
|
||||||
|
</content>
|
||||||
|
</invoke>
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# newwhats.clube67.com — Wasabi & mídias (index + delete em lote)
|
||||||
|
|
||||||
|
> Estado atual + desenho do que falta. Storage = **Wasabi (S3-compatível)** via
|
||||||
|
> `StorageProvider` (`backend/src/core/StorageProvider.ts`). Última revisão: 28/jun/2026.
|
||||||
|
|
||||||
|
## Como funciona hoje
|
||||||
|
- **Upload** (`uploadFile`): fire-and-forget após receber a mídia/avatar; grava no
|
||||||
|
bucket e salva no DB **apenas o path relativo** (ex.: avatar →
|
||||||
|
`contact.avatarUrl`; mídia de mensagem → caminho no `messages`).
|
||||||
|
- **Leitura**: proxy público no `server.ts` (sem authMiddleware, pois `<img>/<audio>/
|
||||||
|
<video>` não mandam header) → busca bytes no Wasabi; se não houver, faz fallback
|
||||||
|
ao CDN do WhatsApp e re-persiste.
|
||||||
|
- **Delete**: só `StorageProvider.deletePrefix(prefix)` → `{ deleted }`. Apaga por
|
||||||
|
**prefixo** (ex.: tudo de uma instância). Não há listagem nem delete seletivo.
|
||||||
|
|
||||||
|
### Convenção de path (prefixos)
|
||||||
|
Os paths são hierárquicos por `tenant/instância/...`, o que permite delete em lote
|
||||||
|
por prefixo. Confirmar o layout exato no `StorageProvider` antes de implementar
|
||||||
|
(avatar usa `avatarWasabiPath(tenantId, instanceId, jid)`).
|
||||||
|
|
||||||
|
## O que falta (pendência)
|
||||||
|
|
||||||
|
### 1. Index de mídias
|
||||||
|
Listagem/auditoria das mídias por **tenant / instância / chat / período**:
|
||||||
|
- Fonte primária: tabela `messages` (path + metadados) — evita `listObjects` caro.
|
||||||
|
- Endpoint admin: `GET /admin/media?instanceId=&chatId=&from=&to=` → paginação,
|
||||||
|
tamanho total, contagem por tipo.
|
||||||
|
- Reconciliação opcional DB ↔ bucket para achar **órfãos** (no bucket sem registro).
|
||||||
|
|
||||||
|
### 2. Delete em lote
|
||||||
|
- Por **instância** (offboarding), por **período** (retenção), por **chat** (LGPD).
|
||||||
|
- Coordenado **DB ↔ Wasabi**: apagar registro e objeto na mesma operação lógica;
|
||||||
|
nunca deixar órfão nem link quebrado.
|
||||||
|
- Implementar `deleteObjects` em lote (S3 aceita até 1000/req) além do `deletePrefix`.
|
||||||
|
- Endpoint admin protegido + dry-run (retorna contagem antes de apagar).
|
||||||
|
|
||||||
|
### 3. Retenção
|
||||||
|
- Após `messages.transcription` salva, o **áudio pode ser arquivado/descartado**
|
||||||
|
(a Secretária já "entende" pelo texto). Job de retenção por idade/tamanho.
|
||||||
|
|
||||||
|
## Cuidados
|
||||||
|
- Delete é destrutivo e externo (Wasabi) — **sempre dry-run + confirmação**.
|
||||||
|
- Não apagar avatar/mídia ainda referenciada por outra mensagem (dedup por path).
|
||||||
|
- Operações em lote: throttle para não estourar limites do S3.
|
||||||
|
</content>
|
||||||
Reference in New Issue
Block a user