Documenta arquitectura, mapeamento de IDs e contratos API para ponte bidireccional entre portal wizard, Desk ops e FOSSBilling Support. Co-authored-by: Cursor <cursoragent@cursor.com>
203 lines
6.8 KiB
Markdown
203 lines
6.8 KiB
Markdown
# Spec 041 — Central Operacional (Operational Feed)
|
||
|
||
**Criado:** 2026-06-29
|
||
**Solicitado por:** Roger
|
||
**Status:** Implementado v0.13.0 — **fase mock/simulação**
|
||
**Prioridade:** P1 (integrações reais = fases futuras)
|
||
**Versão Desk:** `0.13.0-design-system`
|
||
**Substitui:** Aba Desk **`Mensagens`** (`data-view="messages"`)
|
||
**UI label:** **Central Operacional** (vocabulário: *Operational feed* — nunca «Mensagens»)
|
||
**Spec UI geral:** [Spec 040](../040-desk-design-system-v013/spec.md) (tokens, principles)
|
||
**Host:** VM122 · `desk.ligbox.com.br`
|
||
|
||
---
|
||
|
||
## 1. Problema
|
||
|
||
A aba «Mensagens» mostrava apenas **pedidos de cadastro** (`/api/v1/auth/registration-requests`).
|
||
|
||
Roger definiu **Central Operacional** (mockup img 3): inbox unificada omnicanal com canais, KPIs, feed de eventos, painel conversa, SLA.
|
||
|
||
**Decisão:** construir UI completa + **banco simulação** até webhooks/APIs reais (WhatsApp, email inbound, telefonia, etc.).
|
||
|
||
Pedidos de cadastro: preservados em `renderRegistrationRequestsLegacy()` — reintegrar via link no Controle de acesso (Spec 040).
|
||
|
||
---
|
||
|
||
## 2. Escopo
|
||
|
||
| Fase | Estado |
|
||
|------|--------|
|
||
| **Fase A (actual)** | Mock SQLite + seed 6 eventos + API REST |
|
||
| **Fase B** | Webhook email inbound → `ops_inbox_events` |
|
||
| **Fase C** | WhatsApp Business API, Telegram, SMS |
|
||
| **Fase D** | Integração tickets Desk + agentes A0–A7 |
|
||
|
||
---
|
||
|
||
## 3. Arquitetura — Aba Desk
|
||
|
||
```text
|
||
Nav: «Central Operacional» (#nav-messages, data-view=messages)
|
||
View: #view-messages
|
||
Host: #messages-content
|
||
Module: messages (Spec 015 modules registry)
|
||
|
||
app.staging.js
|
||
└── renderMessages()
|
||
└── DeskOperationalFeed.paint(#messages-content) [OF-FE-001]
|
||
|
||
DeskOperationalFeed
|
||
├── Sidebar canais (stats.channels)
|
||
├── KPI row (stats)
|
||
├── Feed entity cards (GET /events)
|
||
└── Right panel
|
||
├── Tabs: Conversa | Detalhes | Histórico
|
||
├── Chat (GET event.messages + POST messages)
|
||
└── SLA bar + acções (PATCH event)
|
||
```
|
||
|
||
**View ID legacy:** `messages` — mantido por compatibilidade módulos/URL; **label UI** = Central Operacional.
|
||
|
||
---
|
||
|
||
## 4. Registo de ficheiros (referência futura)
|
||
|
||
Código interno: **`OF-{tipo}-{nnn}`**
|
||
|
||
### 4.1 Frontend
|
||
|
||
| Código | Ficheiro | Global JS | Função |
|
||
|--------|----------|-----------|--------|
|
||
| **OF-FE-001** | `frontend/assets/operational-feed.js` | `window.DeskOperationalFeed` | UI Central Operacional (layout 3 colunas) |
|
||
| **OF-FE-002** | `frontend/assets/ligbox-ds.css` | — | Partilhado Spec 040 — classes `.lb-ops-*` |
|
||
| **OF-FE-010** | `frontend/index.html` | — | Script `operational-feed.js?v=20260629v013` |
|
||
| **OF-FE-011** | `frontend/assets/app.staging.js` | `renderMessages()` | Delegação para `DeskOperationalFeed.paint` |
|
||
| **OF-FE-012** | `frontend/assets/app.staging.js` | `titles.messages` | «Central Operacional» |
|
||
| **OF-FE-013** | `frontend/assets/app.staging.js` | `subtitles.messages` | «Spec 041 · Operational feed…» |
|
||
|
||
### 4.2 API — Backend
|
||
|
||
| Código | Ficheiro | Router | Função |
|
||
|--------|----------|--------|--------|
|
||
| **OF-API-001** | `api/app/ops_inbox_store.py` | — | Schema + seed + queries SQLite |
|
||
| **OF-API-002** | `api/app/ops_inbox_routes.py` | `/api/v1/ops-inbox` | REST endpoints |
|
||
| **OF-API-003** | `api/app/main.py` | — | `include_router(ops_inbox_router)` + `init_inbox_schema` |
|
||
|
||
### 4.3 Contratos
|
||
|
||
| Código | Ficheiro | Função |
|
||
|--------|----------|--------|
|
||
| **OF-CTR-001** | `specs/041-desk-operational-feed/contracts/ops-inbox-api.md` | Contrato endpoints |
|
||
| **OF-CTR-002** | `contracts/stack-services.yaml` | Serviço `vm122-ops-inbox-api` |
|
||
|
||
---
|
||
|
||
## 5. Endpoints — arquitectura
|
||
|
||
Contrato detalhado: [contracts/ops-inbox-api.md](contracts/ops-inbox-api.md)
|
||
|
||
| Código | Método | Path | Descrição |
|
||
|--------|--------|------|-----------|
|
||
| **OF-EP-001** | GET | `/api/v1/ops-inbox/stats` | KPIs + contadores por canal |
|
||
| **OF-EP-002** | GET | `/api/v1/ops-inbox/events` | Lista eventos (filtros) |
|
||
| **OF-EP-003** | GET | `/api/v1/ops-inbox/events/{id}` | Detalhe + mensagens |
|
||
| **OF-EP-004** | POST | `/api/v1/ops-inbox/events/{id}/messages` | Resposta / nota interna |
|
||
| **OF-EP-005** | PATCH | `/api/v1/ops-inbox/events/{id}` | status, assignee, priority |
|
||
|
||
**Auth:** Bearer JWT · `can_manage_users` (fase mock — alinhar RBAC dedicado em fase B).
|
||
|
||
---
|
||
|
||
## 6. Modelo de dados (SQLite — fase mock)
|
||
|
||
### `ops_inbox_events`
|
||
|
||
| Coluna | Tipo | Descrição |
|
||
|--------|------|-----------|
|
||
| id | TEXT PK | ex. `evt-wa-001` |
|
||
| channel | TEXT | `whatsapp`, `email`, `tickets`, … |
|
||
| event_type | TEXT | `message`, `ticket`, `alert`, `missed_call` |
|
||
| priority | TEXT | `normal`, `high`, `critical` |
|
||
| title, preview | TEXT | Card feed |
|
||
| tags_json | TEXT | JSON array |
|
||
| assignee | TEXT | nullable |
|
||
| status | TEXT | `open`, `pending`, `resolved` |
|
||
| contact_* | TEXT | empresa, CNPJ, client_id |
|
||
| sla_minutes, sla_remaining_sec | INT | Barra SLA UI |
|
||
| created_at, updated_at | TEXT | ISO8601 |
|
||
|
||
### `ops_inbox_messages`
|
||
|
||
| Coluna | Tipo | Descrição |
|
||
|--------|------|-----------|
|
||
| event_id | TEXT FK | |
|
||
| author_type | TEXT | `user`, `agent`, `operator`, `internal`, `system` |
|
||
| author_label | TEXT | |
|
||
| body | TEXT | |
|
||
|
||
**Seed:** 6 eventos em `init_inbox_schema()` quando tabela vazia.
|
||
|
||
---
|
||
|
||
## 7. Canais (sidebar)
|
||
|
||
| ID | Label UI |
|
||
|----|----------|
|
||
| all | Todos os canais |
|
||
| email | Email |
|
||
| whatsapp | WhatsApp API |
|
||
| voice | Telefonia / Voz |
|
||
| sms | SMS |
|
||
| telegram | Telegram |
|
||
| tickets | Tickets |
|
||
| agents | Agentes IA |
|
||
| internal | Solicitações internas |
|
||
| clients | Clientes |
|
||
| alerts | Alertas sistema |
|
||
|
||
---
|
||
|
||
## 8. Integrações futuras (stubs)
|
||
|
||
| Canal | Endpoint futuro | Notas |
|
||
|-------|-----------------|-------|
|
||
| Email | `POST /api/v1/ops-inbox/webhooks/email` | Inbound parse → event |
|
||
| WhatsApp | `POST /api/v1/ops-inbox/webhooks/whatsapp` | Meta Cloud API |
|
||
| Tickets | Link `desk_tickets` | Sync bidireccional — **[Spec 044](../044-foss-desk-ticket-sync/spec.md)** |
|
||
| Agentes | `agents/routes.py` threads | Unificar inbox agentes |
|
||
| Cadastro | `registration-requests` | Link desde Spec 040 hub |
|
||
|
||
---
|
||
|
||
## 9. KPIs (header)
|
||
|
||
| KPI | Fonte |
|
||
|-----|-------|
|
||
| Eventos hoje | COUNT events |
|
||
| Pendentes | status open/pending |
|
||
| Críticos | priority=critical |
|
||
| Aguardando você | assignee NOT NULL + open |
|
||
| SLA médio | Mock 96% (fase A) — calcular fase B |
|
||
|
||
---
|
||
|
||
## 10. Validação
|
||
|
||
```bash
|
||
curl -s -H "Authorization: Bearer $TOKEN" \
|
||
https://desk.ligbox.com.br/api/v1/ops-inbox/stats
|
||
|
||
curl -s -H "Authorization: Bearer $TOKEN" \
|
||
"https://desk.ligbox.com.br/api/v1/ops-inbox/events?channel=whatsapp"
|
||
```
|
||
|
||
UI: Menu **Central Operacional** → feed com 6 cards seed → painel conversa.
|
||
|
||
---
|
||
|
||
## 11. Deploy
|
||
|
||
Mesmo procedimento Spec 040 — ficheiros **OF-API-001/002** + **OF-FE-001**.
|
||
|
||
Health API: `"version": "0.13.0-design-system"`
|