Files

619 lines
28 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Turbinar Secretária Virtual — Plano Mestre Integrado
> **Versão 3** — Questões arquiteturais respondidas. Módulo Inbox Interna adicionado.
> Regra de ouro: **auditar → reaproveitar → corrigir → completar → criar novo somente se necessário.**
---
## VISÃO ESTRATÉGICA
Transformar a Secretária Virtual de um bot único em uma
**plataforma operacional inteligente** onde:
- A IA resolve o que sabe com seu cérebro em camadas
- Quando não sabe, **consulta o humano certo via Human API**
- Cada humano tem cargo, setor, permissões e um cérebro próprio
- Todo atendimento vira protocolo rastreável com SLA e satisfação final
- O sistema aprende com cada resposta humana e reduz dependência futura
- A equipe interna se comunica pela **Inbox Interna** (canal separado do cliente)
```
EMPRESA
├── Número Oficial (WhatsApp / Inbox Central)
│ └── Secretária IA
│ ├── Cérebro Global
│ ├── Cérebro do Setor
│ ├── Contexto do Cliente
│ └── Human API (quando IA não sabe)
├── Equipe Humana (hierarquia real)
│ ├── Dono
│ ├── Gerente
│ ├── Encarregados de Setor
│ ├── Secretárias
│ └── Atendentes / Especialistas
├── Inbox Interna (NOVO)
│ ├── Comunicação entre equipe
│ ├── Consultas da Human API
│ ├── Pedidos de ajuda colaborativos
│ └── Aceitar / transferir protocolos
└── Motor de Conhecimento
├── Base Global (sec_brain_nodes — já existe)
├── Base por Setor (sector_brain_nodes — novo)
├── Respostas Humanas Aprendidas (knowledge_learning — novo)
└── Score de Eficiência (escalation_logs — novo)
```
---
## HIERARQUIA HUMANA
```
Dono
└── Gerente
└── Encarregado de Setor
├── Secretária
└── Atendente / Especialista
```
| Papel | Inbox Externa | Inbox Interna | Configurações | Setores visíveis | Pode escalar |
|------------------|--------------|---------------|---------------|------------------|--------------|
| `owner` | Tudo | Tudo | Total | Todos | Sim |
| `manager` | Tudo | Tudo | Parcial | Todos | Sim |
| `supervisor` | Seu setor | Seu setor | Nenhuma | Próprio + sub | Sim |
| `secretary` | Triagem | Tudo (leitura)| Nenhuma | Todos (leitura) | Sim |
| `agent` | Seu setor | Seu setor | Nenhuma | Próprio | Não |
| `viewer` | Leitura | Leitura | Nenhuma | Próprio | Não |
> ⚠️ **Auditoria prévia:** verificar se o sistema alemão já tem algum modelo de permissões,
> roles ou usuários no banco antes de criar tabelas novas.
---
## DECISÕES ARQUITETURAIS (RESPONDIDAS)
### 1. Contas têm login na interface?
**Modelo híbrido — ambos.**
Cada colaborador pode operar de duas formas:
- **Login próprio na plataforma** (email + senha / sessão individual)
- **Somente número pessoal cadastrado** para receber consultas da IA via Human API
```
Usuário interno entra no sistema
Acessa Inbox Interna (novo ícone na ThinSidebar)
Recebe chamados / consultas / protocolos
```
### 2. Multi-equipe?
**Equipe única por tenant agora.** Arquitetura preparada com `team_id` opcional para virar multi-equipe depois sem quebrar o schema.
### 3. Setor: quem identifica?
**IA tenta, humano corrige (modelo C).**
```
Mensagem chega → IA classifica setor provável → Humano pode corrigir se necessário
```
### 4. Human API — número pessoal?
**Modelo misto (A + B):**
| Situação | Comportamento |
|----------|---------------|
| Número conectado ao motor | Especialista responde diretamente no sistema |
| Número não conectado | Recebe pergunta na Inbox Interna / responde pelo painel |
```
Se conectado → recebe no WA pessoal, responde no sistema
Se não conectado → recebe e responde na Inbox Interna
```
### 5. Timeout sem resposta?
**5 minutos com reescalação inteligente.**
```
5 min sem retorno
IA procura outro humano do mesmo setor
Mensagem automática: "Não encontrei [nome]. Alguém do setor pode assumir?"
Se nenhum disponível → handoff completo para humano
```
Botão interno adicional: **"Sou [nome], preciso de ajuda"** → abre pedido colaborativo na Inbox Interna.
### 6. O que é um Protocolo?
Registro formal de que uma solicitação do cliente **foi iniciada e depois encerrada**.
**Ciclo:**
```
Cliente solicita → Sistema abre protocolo → Equipe trabalha → Cliente confirma → Sistema encerra
```
**Campos mínimos:**
`número | cliente | assunto | setor | responsável | SLA | status | iniciado_em | encerrado_em | satisfação`
---
## BLOCO A — ThinSidebar Atualizada
```
[ThinSidebar 60px]
● Conversas (MessageCircle) — Inbox Externa WhatsApp
● Sessões (Smartphone)
● Secretária (Bot)
● Equipe ◄ NOVO (Users)
● Inbox Interna ◄ NOVO (MessagesSquare ou Inbox)
─────────────────
● Configurações (Settings)
```
- **Equipe** → EquipeTab (Contas, Setores, Membros, Cérebros, Performance)
- **Inbox Interna** → InboxInternaTab (comunicação entre equipe + Human API + protocolos)
- Ambas abas visíveis conforme cargo (owner/manager/supervisor veem Equipe; todos veem Inbox Interna dentro das permissões)
---
## BLOCO B — Modelo de Dados
> ⚠️ **Auditoria prévia obrigatória** — analisar schema atual do alemão para detectar
> tabelas de usuários, permissões, setores, equipes ou chats internos já existentes.
> Reaproveitar antes de criar novo.
### B1 — `accounts` — Contas internas de colaboradores
| Campo | Tipo | Descrição |
|------------------|-----------|--------------------------------------------------------|
| id | UUID PK | |
| tenant_id | FK | Isolamento por empresa |
| name | VARCHAR | Nome completo |
| email | VARCHAR | Login único (nullable se acesso só via WA) |
| password_hash | VARCHAR | Bcrypt — nullable se sem acesso à interface |
| role | ENUM | `owner` `manager` `supervisor` `secretary` `agent` `viewer` |
| phone | VARCHAR | Número pessoal WA (usado na Human API) |
| phone_connected | BOOLEAN | Se o número pessoal está conectado ao motor |
| availability | ENUM | `online` `busy` `offline` |
| avatar_url | VARCHAR | |
| active | BOOLEAN | |
| created_at | TIMESTAMP | |
### B2 — `sectors` — Setores operacionais
| Campo | Tipo | Descrição |
|-------------|-----------|------------------------------------------------------------------|
| id | UUID PK | |
| tenant_id | FK | |
| name | VARCHAR | Ex: "Clube de Benefícios", "Financeiro", "Alemão Premium" |
| description | TEXT | O que este setor atende |
| icon | VARCHAR | Nome lucide-react |
| color | VARCHAR | Hex |
| sla_minutes | INTEGER | Tempo máximo de resposta (SLA) |
| sort_order | INTEGER | |
| active | BOOLEAN | |
> **Exemplos de setores:** Financeiro, Comercial, Alemão, Alemão Premium, Alemão Vendas, Urgência, Pós-venda
### B3 — `team_members` — Conta ↔ Setor com função
| Campo | Tipo | Descrição |
|--------------------|-----------|--------------------------------------------------------|
| id | UUID PK | |
| account_id | FK | |
| sector_id | FK | |
| function | VARCHAR | Ex: "Encarregado", "Especialista financeiro" |
| is_primary | BOOLEAN | Setor principal do colaborador |
| notify_escalation | BOOLEAN | Recebe alerta WA de escalação neste setor |
| notify_human_api | BOOLEAN | Recebe consultas da Human API neste setor |
| on_duty | BOOLEAN | Está em turno agora (toggle manual ou horário) |
### B4 — `sector_brain_nodes` — Cérebro por setor
| Campo | Tipo | Descrição |
|------------|---------|--------------------------------------------------------|
| id | UUID PK | |
| sector_id | FK | |
| type | ENUM | `knowledge` `rules` `escalation` `persona` |
| content | TEXT | Conhecimento específico do setor |
| sort_order | INTEGER | |
| active | BOOLEAN | |
### B5 — `human_api_requests` — Consultas IA → Humano (Human API)
| Campo | Tipo | Descrição |
|-----------------|-----------|----------------------------------------------------|
| id | UUID PK | |
| conversation_id | FK | Protocolo em aberto |
| sector_id | FK | Setor consultado |
| account_id | FK | Especialista acionado |
| question | TEXT | Resumo enviado ao especialista |
| answer | TEXT | Resposta recebida (null se ainda aguardando) |
| status | ENUM | `pending` `answered` `timeout` `ignored` |
| delivery_mode | ENUM | `whatsapp` `inbox_interna` — como foi entregue |
| asked_at | TIMESTAMP | |
| answered_at | TIMESTAMP | |
| timeout_at | TIMESTAMP | Se não responder até aqui → próximo especialista |
### B6 — `knowledge_learning` — Respostas humanas que viram conhecimento
| Campo | Tipo | Descrição |
|-----------------|-----------|-------------------------------------------------|
| id | UUID PK | |
| sector_id | FK | |
| account_id | FK | Quem respondeu |
| question | TEXT | Pergunta original |
| answer | TEXT | Resposta validada |
| promoted | BOOLEAN | Foi promovido para sector_brain_nodes |
| promoted_at | TIMESTAMP | |
| use_count | INTEGER | Quantas vezes a IA reutilizou esta resposta |
### B7 — `protocols` — Protocolo de atendimento enriquecido
> ⚠️ **Auditoria prévia:** verificar se `sec_conversations` já supre estas necessidades.
> Se sim, apenas adicionar colunas faltantes — não criar tabela nova.
| Campo | Tipo | Descrição |
|------------------|-----------|---------------------------------------------------|
| id | UUID PK | |
| conversation_id | FK | Liga ao sec_conversations existente |
| sector_id | FK | Setor responsável |
| account_id | FK | Responsável atual |
| subject | VARCHAR | Assunto / tema central |
| summary_ia | TEXT | Resumo gerado pela IA ao abrir |
| sla_deadline | TIMESTAMP | Prazo baseado no SLA do setor |
| status | ENUM | `open` `in_progress` `waiting` `resolved` `closed`|
| satisfaction | INTEGER | 15 (confirmação do cliente) |
| opened_at | TIMESTAMP | |
| closed_at | TIMESTAMP | |
### B8 — `escalation_logs` — Histórico de escalações e scores
| Campo | Tipo | Descrição |
|-----------------|-----------|-----------------------------------------------|
| id | UUID PK | |
| conversation_id | FK | |
| account_id | FK | Quem recebeu a escalação |
| sector_id | FK | |
| response_ms | INTEGER | Tempo de resposta em milissegundos |
| resolved | BOOLEAN | Resolveu sem redirecionar? |
| satisfaction | INTEGER | Nota do cliente |
| escalated_at | TIMESTAMP | |
### B9 — `internal_messages` — Inbox Interna (NOVO)
| Campo | Tipo | Descrição |
|--------------|-----------|------------------------------------------------------------------------|
| id | UUID PK | |
| tenant_id | FK | |
| thread_id | UUID | Agrupa mensagens de um mesmo assunto/protocolo |
| from_account | FK | Quem enviou (null = sistema/IA) |
| to_account | FK | Destinatário (null = broadcast do setor) |
| sector_id | FK NULL | Setor associado (quando mensagem vai para o setor inteiro) |
| type | ENUM | `human_api` `escalation` `collaboration` `system` `help_request` |
| content | TEXT | Conteúdo da mensagem |
| ref_id | UUID NULL | Referência ao human_api_requests ou sec_conversations relacionado |
| read_at | TIMESTAMP | Quando foi lida pelo destinatário |
| created_at | TIMESTAMP | |
---
## BLOCO C — Interface: EquipeTab
### Sub-aba 1 — Contas
- Cards de colaboradores: avatar, nome, papel (badge colorido), disponibilidade (bolinha verde/cinza)
- Filtro por papel / setor / disponibilidade
- Botão "Nova conta" → modal completo (nome, email, senha, telefone, papel)
- Editar | Suspender | Redefinir senha
- Toggle de disponibilidade rápido (on_duty)
- Badge "WA conectado" ou "só notificação"
### Sub-aba 2 — Setores
- Cards com ícone colorido, nome, descrição, SLA e contador de membros
- Exemplos pré-cadastrados: Financeiro, Comercial, Alemão, Urgência, Pós-venda
- Botão "Novo setor" → modal: nome, ícone, cor, SLA em minutos
- Clique no setor → drawer lateral com membros e link direto para o cérebro
- Drag-to-reorder
### Sub-aba 3 — Membros
- Tabela: avatar | nome | setor | função | on_duty | notif. escalação | notif. Human API | modo WA
- "+ Vincular membro" → selecionar conta existente + setor + função
- Toggles inline para notificações e disponibilidade
- Desvincular sem excluir a conta
### Sub-aba 4 — Cérebros por Setor
- Selector de setor no topo
- Editor de nodes idêntico ao da Secretária (reaproveitar componente existente)
- Tipos: `knowledge` `rules` `escalation` `persona`
- Badge com quantidade de nodes ativos por setor
- Preview do bloco que será injetado no prompt
### Sub-aba 5 — Performance
- Métricas por colaborador e setor:
- Tempo médio de resposta na Human API
- Taxa de resolução (resolveu vs redirecionou)
- Satisfação média (15)
- Consultas recebidas via Human API
- Respostas promovidas para base de conhecimento
- Período: hoje / semana / mês
- Ranking de especialistas mais acionados pela IA
---
## BLOCO D — Interface: Inbox Interna (NOVO)
> ⚠️ **Auditoria prévia:** verificar se existe algum chat interno, sala ou thread
> já implementado no sistema antes de criar novo.
### Propósito
Canal interno separado completamente do canal com o cliente. Aqui a equipe:
- Recebe consultas da Human API
- Pede ajuda a colegas
- Aceita / transfere protocolos
- Vê escalações do setor
- Responde às perguntas da IA (quando número não está conectado)
### Layout sugerido
```
[Painel esquerdo — threads] [Painel direito — mensagens]
───────────────────────────── ───────────────────────────
🤖 Human API (3) Thread: Human API #001
👤 Fulano pediu ajuda IA: "Cliente perguntou sobre
📋 Protocolo #123 escalado cancelamento do clube..."
───────────────────────────── [Digite sua resposta...]
[Enviar] [Recusar] [Redirecionar]
```
### Tipos de thread
| Tipo | Ícone | Quem cria | Quem vê |
|------|-------|-----------|---------|
| `human_api` | 🤖 | Sistema/IA | Especialistas do setor |
| `help_request` | 🆘 | Qualquer membro | Setor + supervisores |
| `escalation` | ⚠️ | Sistema/IA | Setor + manager |
| `collaboration` | 💬 | Qualquer membro | Destinatário(s) |
| `system` | ⚙️ | Sistema | Owner + manager |
### Badge de notificação
- Ícone na ThinSidebar exibe bolinha vermelha com número de mensagens não lidas
- Atualização em tempo real via WebSocket (mesmo canal já existente)
---
## BLOCO E — Fluxo de Atendimento com Protocolo
```
Cliente envia mensagem (WhatsApp)
webhook-receiver.js recebe
context-builder.js → { cliente, plano, pedidos, promoções }
Verifica handoff_mode: humano? → não chama IA
↓ (modo IA)
ProtocolEngine.chat()
Cria/retoma protocolo automaticamente
Tool: identificar_setor → detecta setor provável
Injeta cérebro do setor no prompt
IA responde ou...
├─ Sabe a resposta → responde cliente diretamente
└─ Não sabe
[Human API ativada]
Resume o problema (12 linhas)
Busca especialista on_duty do setor
Se número conectado → envia WA ao número pessoal
Se não conectado → cria thread na Inbox Interna
Aguarda 5 min
Respondeu? → IA formula resposta ao cliente
Não respondeu? → tenta próximo do setor
Nenhum disponível? → handoff humano completo
Salva em knowledge_learning
```
### Estrutura do protocolo final
```
Protocolo #XYZ
├── Cliente: João Silva
├── Assunto: Cobrança duplicada do clube
├── Setor: Financeiro
├── Responsável: Ana (Encarregada)
├── Resumo IA: "Cliente questiona cobrança duplicada em abril"
├── SLA: 30 min (prazo: 14h30)
├── Status: Em andamento
├── Histórico cliente ↔ IA (canal externo)
├── Histórico interno (Human API queries — canal interno)
└── Satisfação: ⭐⭐⭐⭐⭐ (após resolução)
```
---
## BLOCO F — Human API (diferencial principal)
### Conceito
Quando a IA não tem resposta confiável, em vez de escalar para atendimento humano
**completo** (handoff), ela faz uma **consulta pontual** ao especialista certo
e mantém o controle da conversa. O cliente não percebe a diferença.
### Fluxo técnico (modelo misto)
```
brain.chat() → não confiante na resposta
tool: consultar_especialista({
setor: "financeiro",
pergunta: "Qual o prazo para cancelamento sem multa?"
})
Motor:
1. Busca especialista on_duty do setor (team_members.on_duty = true)
2. Insere human_api_requests (status=pending, timeout_at = agora+5min)
3. Verifica delivery_mode:
├─ phone_connected=true → envia WA via Baileys ao número pessoal
└─ phone_connected=false → cria thread na Inbox Interna
4. BullMQ job com delay 5 min
5. Job dispara → ainda pending? → tenta próximo do setor
6. Todos timeout? → handoff completo
7. Respondeu → atualiza human_api_requests (status=answered)
8. brain.chat() recebe resposta → formula resposta ao cliente
9. Salva em knowledge_learning
```
### Botão de ajuda colaborativo
Qualquer colaborador dentro da Inbox Interna pode clicar:
```
[Sou Fulano, preciso de ajuda]
→ abre thread tipo `help_request` visível para o setor + supervisores
```
### Aprendizado contínuo
```
knowledge_learning.use_count aumenta a cada reutilização
Admin vê painel: "5 respostas sobre cancelamento — promover para base?"
Um clique → vira sector_brain_node
IA resolve sozinha na próxima vez
```
---
## BLOCO G — Cérebro em Camadas (atualizado)
```
System prompt final =
[DATA E HORA ATUAL] ← já existe ✅
+ [PROTOCOLO ATIVO] ← já existe ✅
+ [CÉREBRO GLOBAL — sec_brain_nodes] ← já existe ✅
+ [CÉREBRO DO SETOR — sector_brain_nodes] ← NOVO (B4)
+ [CONHECIMENTO APRENDIDO — top 3 relevantes] ← NOVO (B6)
+ [CONTEXTO DO CLIENTE — context-builder] ← já existe ✅
+ [ESTADO DA CONVERSA — summary] ← já existe ✅
```
### Tools disponíveis (atualizado)
| Tool | Status | Descrição |
|-------------------------|----------|---------------------------------------------------|
| `listar_horarios` | ✅ Existe | Lista slots de agenda |
| `agendar_horario` | ✅ Existe | Reserva slot |
| `escalar_humano` | ✅ Existe | Handoff completo para atendente |
| `encerrar_protocolo` | ✅ Existe | Fecha conversa com resumo |
| `identificar_setor` | 🔲 NOVO | Registra setor responsável na conversa |
| `consultar_especialista`| 🔲 NOVO | Human API — consulta humano sem perder o controle |
| `registrar_satisfacao` | 🔲 NOVO | Coleta nota do cliente ao final |
---
## BLOCO H — Score Operacional
Medir por colaborador e setor:
- Tempo de resposta (Human API)
- Taxa de solução (resolveu vs redirecionou)
- Satisfação do cliente (15)
- Reincidência (mesmo problema)
- Uso da IA vs humano
- Respostas promovidas para base de conhecimento
---
## FLUXO MESTRE
```
Cliente pergunta
Secretária IA analisa
Existe resposta pronta? ── Sim → Responde cliente
↓ Não
Existe algo em andamento/incompleto? ── Sim → Concluir/aproveitar
↓ Não
Detecta setor (IA classifica, humano pode corrigir)
Aciona especialista humano via Human API
Recebe resposta (WA pessoal ou Inbox Interna)
Responde cliente
Salva aprendizado
```
---
## RESUMO PRIORIZADO DE IMPLEMENTAÇÃO
| # | Bloco | Tarefa | Impacto | Esforço |
|----|-------|---------------------------------------------------------------------|------------|---------|
| 1 | — | **Auditoria do schema atual** (antes de tudo) | 🔴 Crítico | Trivial |
| 2 | B1 | Migration: `accounts` + `sectors` | 🔴 Crítico | Pequeno |
| 3 | B3 | Migration: `team_members` + `sector_brain_nodes` | 🔴 Crítico | Pequeno |
| 4 | B9 | Migration: `internal_messages` (Inbox Interna) | 🔴 Crítico | Pequeno |
| 5 | A | Aba "Equipe" + ícone "Inbox Interna" na ThinSidebar | 🔴 Crítico | Trivial |
| 6 | C1 | Sub-aba Contas: CRUD de colaboradores (login híbrido) | 🔴 Crítico | Médio |
| 7 | C2 | Sub-aba Setores: CRUD de setores + SLA | 🔴 Crítico | Pequeno |
| 8 | C3 | Sub-aba Membros: vincular conta ↔ setor + on_duty | 🟠 Alto | Pequeno |
| 9 | D | Inbox Interna: layout + threads + tipos de mensagem | 🟠 Alto | Médio |
| 10 | D | Inbox Interna: badge de notificação via WebSocket | 🟠 Alto | Pequeno |
| 11 | C4 | Sub-aba Cérebros: editor por setor (reaproveitar componente) | 🟠 Alto | Pequeno |
| 12 | G | Motor: injetar cérebro do setor no prompt | 🟠 Alto | Médio |
| 13 | G | Tool: `identificar_setor` | 🟠 Alto | Pequeno |
| 14 | B5 | Migration: `human_api_requests` | 🟠 Alto | Pequeno |
| 15 | F | Human API: envio de consulta (WA se conectado / Inbox se não) | 🟠 Alto | Médio |
| 16 | F | Human API: captura de resposta + retorno ao brain | 🟠 Alto | Médio |
| 17 | F | Human API: timeout 5 min + rodízio de especialistas (BullMQ) | 🟠 Alto | Médio |
| 18 | F | Botão "Sou [nome], preciso de ajuda" na Inbox Interna | 🟡 Médio | Pequeno |
| 19 | B7 | Migration: `protocols` (se sec_conversations insuficiente) | 🟡 Médio | Pequeno |
| 20 | E | Fluxo completo de protocolo com SLA | 🟡 Médio | Médio |
| 21 | B6 | `knowledge_learning` + promoção para brain | 🟡 Médio | Médio |
| 22 | C5 | Sub-aba Performance: métricas e score | 🟡 Médio | Grande |
| 23 | H | Score operacional: ranking de especialistas | 🟡 Médio | Médio |
| 24 | — | Login próprio por conta (autenticação separada) | 🟡 Médio | Grande |
| 25 | G | Tool: `registrar_satisfacao` (CSAT ao fechar) | 🟢 Futuro | Pequeno |
| 26 | B8 | escalation_logs + ranking de eficiência | 🟢 Futuro | Médio |
---
## REGRA DE OURO
```
Auditar → Reaproveitar → Corrigir → Completar → Criar novo somente se necessário
```
Aplicada a cada bloco antes de qualquer linha de código.
---
## QUESTÕES RESOLVIDAS ✅
Todas as 6 questões abertas da Versão 2 foram respondidas e incorporadas acima.
Nenhuma questão aberta pendente para início da implementação.
> **Próximo passo:** Item #1 — Auditoria do schema atual do alemão
> para detectar tabelas reaproveitáveis antes de criar qualquer migration.