Obsidian: Spec 044 FOSS-Desk ticket sync + links cruzados
Sync completo da spec 044, contratos, registry e sidebar no vault VM130. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
e5564c15b9
commit
4e65555abb
11 changed files with 662 additions and 3 deletions
|
|
@ -212,3 +212,10 @@
|
||||||
- [activation-field-mapping.md](specs/043-desk-client-activation-sync/contracts/activation-field-mapping.md) — **fonte única**
|
- [activation-field-mapping.md](specs/043-desk-client-activation-sync/contracts/activation-field-mapping.md) — **fonte única**
|
||||||
- [desk-activate-account-api.md](specs/043-desk-client-activation-sync/contracts/desk-activate-account-api.md)
|
- [desk-activate-account-api.md](specs/043-desk-client-activation-sync/contracts/desk-activate-account-api.md)
|
||||||
- [mail-bundle-api.md](specs/043-desk-client-activation-sync/contracts/mail-bundle-api.md)
|
- [mail-bundle-api.md](specs/043-desk-client-activation-sync/contracts/mail-bundle-api.md)
|
||||||
|
- **044-foss-desk-ticket-sync** ⭐ Portal OB- ↔ Desk ↔ FOSS Support
|
||||||
|
- [📄 spec.md](specs/044-foss-desk-ticket-sync/spec.md)
|
||||||
|
- [tasks.md](specs/044-foss-desk-ticket-sync/tasks.md)
|
||||||
|
- [ROLLBACK.md](specs/044-foss-desk-ticket-sync/ROLLBACK.md)
|
||||||
|
- **contracts/**
|
||||||
|
- [ticket-field-mapping.md](specs/044-foss-desk-ticket-sync/contracts/ticket-field-mapping.md) — **fonte única IDs**
|
||||||
|
- [ticket-sync-api.md](specs/044-foss-desk-ticket-sync/contracts/ticket-sync-api.md)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
**Status:** 📋 **Draft — decisões fechadas, pronta para plano**
|
**Status:** 📋 **Draft — decisões fechadas, pronta para plano**
|
||||||
**Prioridade:** **P0** (bloqueia operação humana no onboarding)
|
**Prioridade:** **P0** (bloqueia operação humana no onboarding)
|
||||||
**Depende de:** Spec 001 (webhooks VM112), Spec 003 (auth/RBAC)
|
**Depende de:** Spec 001 (webhooks VM112), Spec 003 (auth/RBAC)
|
||||||
**Relacionada:** Spec 007 (push escalada), Spec 008 (Kanban/SLA), Spec 011 (OTRS futuro)
|
**Relacionada:** Spec 007 (push escalada), Spec 008 (Kanban/SLA), Spec 011 (OTRS futuro), **[Spec 044](../044-foss-desk-ticket-sync/spec.md)** (sync FOSS)
|
||||||
**API alvo:** `0.9.0-desk-assist` (VM122) + contratos VM112 `assist-v1`
|
**API alvo:** `0.9.0-desk-assist` (VM122) + contratos VM112 `assist-v1`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ bash /opt/ligbox-ops-platform/deploy/vm123-finance-stack/setup-foss-antispam.sh
|
||||||
FOSSBilling Server Manager
|
FOSSBilling Server Manager
|
||||||
(criar/suspender contas hosting)
|
(criar/suspender contas hosting)
|
||||||
|
|
||||||
Desk VM122 ──webhook/link──► FOSSBilling / tickets
|
Desk VM122 ──webhook/link──► FOSSBilling / tickets · **[Spec 044](../044-foss-desk-ticket-sync/spec.md)** sync bidireccional
|
||||||
Wizard VM112 ──company.validated──► Desk
|
Wizard VM112 ──company.validated──► Desk
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
203
ligbox-ops-platform/specs/041-desk-operational-feed/spec.md
Normal file
203
ligbox-ops-platform/specs/041-desk-operational-feed/spec.md
Normal file
|
|
@ -0,0 +1,203 @@
|
||||||
|
# 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"`
|
||||||
|
|
@ -37,6 +37,7 @@ O Desk (VM122) é o **orquestrador**: recebe `company.validated`, persiste `bill
|
||||||
| [027](../027-desk-rbac-function-matrix/spec.md) | Quem pode activar conta |
|
| [027](../027-desk-rbac-function-matrix/spec.md) | Quem pode activar conta |
|
||||||
| [039](../039-ligbox-ops-authorization-catalog/spec.md) | `vm123_foss.*`, `vm123_openpanel.*`, Odoo |
|
| [039](../039-ligbox-ops-authorization-catalog/spec.md) | `vm123_foss.*`, `vm123_openpanel.*`, Odoo |
|
||||||
| [040](../040-desk-design-system-v013/spec.md) | UI staff Access Control Hub |
|
| [040](../040-desk-design-system-v013/spec.md) | UI staff Access Control Hub |
|
||||||
|
| [044](../044-foss-desk-ticket-sync/spec.md) | Sync tickets OB- ↔ Desk ↔ FOSS Support |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Spec 044 — Rollback
|
||||||
|
|
||||||
|
## Feature flag
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# VM122 .env
|
||||||
|
FOSS_TICKET_SYNC_ENABLED=false
|
||||||
|
systemctl restart ligbox-ops-api
|
||||||
|
```
|
||||||
|
|
||||||
|
Desactiva espelho Desk→FOSS e ignora webhook FOSS→Desk (HTTP 503 «sync disabled»).
|
||||||
|
|
||||||
|
## Git tags (após implementação)
|
||||||
|
|
||||||
|
| Tag | Descrição |
|
||||||
|
|-----|-----------|
|
||||||
|
| `desk-v0.15.0-pre-spec044-ticket-sync` | Antes Spec 044 |
|
||||||
|
| `desk-v0.15.1-spec044-ticket-sync` | Com sync FOSS tickets |
|
||||||
|
|
||||||
|
## Rollback manual
|
||||||
|
|
||||||
|
1. Remover `foss_sync` de tickets afectados (opcional — dados inofensivos)
|
||||||
|
2. Tickets FOSS criados manualmente podem permanecer no FOSS admin
|
||||||
|
3. Portal OB- e Desk continuam funcionando independentemente
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
# Contrato — Mapeamento IDs: Portal ↔ Desk ↔ FOSS
|
||||||
|
|
||||||
|
**Spec:** [044](../spec.md)
|
||||||
|
**Versão:** 1.0 · 2026-07-01 · Roger
|
||||||
|
**Status:** Fonte única para correlação de tickets
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Identificadores
|
||||||
|
|
||||||
|
| Campo | Formato | Sistema dono | Persistência Desk |
|
||||||
|
|-------|---------|--------------|-------------------|
|
||||||
|
| `wizard_ticket_id` | `OB-[A-F0-9]{8}` | VM112 portal | `tickets.payload.wizard_ticket_id` |
|
||||||
|
| `desk_ticket_id` | inteiro `#N` | VM122 Desk | `tickets.id` |
|
||||||
|
| `foss_ticket_id` | inteiro FOSS | VM123 FOSS | `tickets.payload.foss_ticket_id` |
|
||||||
|
| `external_customer_id` | inteiro FOSS client | VM123 FOSS | `billing_accounts.external_customer_id` |
|
||||||
|
| `session_id` | UUID wizard | VM112 | `tickets.session_id` |
|
||||||
|
| `domain` | FQDN | — | `tickets.payload.domain` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Chaves de idempotência
|
||||||
|
|
||||||
|
| Operação | Chave única | Comportamento se duplicado |
|
||||||
|
|----------|-------------|----------------------------|
|
||||||
|
| Portal → Desk | `event + session_id + domain` | Actualizar ticket existente (Spec 001 FR-012) |
|
||||||
|
| Desk → FOSS espelho | `desk_ticket_id` | Retornar `foss_ticket_id` existente |
|
||||||
|
| FOSS → Desk webhook | `foss_ticket_id + event_type` | Append nota, não criar ticket novo |
|
||||||
|
| Cliente FOSS novo | `foss_ticket_id` | Lookup Desk; criar só se ausente |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Mapa de estados
|
||||||
|
|
||||||
|
| Desk `status` | Portal OB- `status` | FOSS Support |
|
||||||
|
|---------------|---------------------|--------------|
|
||||||
|
| `open` | `open` | `open` |
|
||||||
|
| `escalated` | `in_review` | `open` |
|
||||||
|
| `assisting` | `in_progress` | `on hold` |
|
||||||
|
| `resolved` | `resolved` | `closed` (resolvido) |
|
||||||
|
| `closed` | `closed` | `closed` |
|
||||||
|
|
||||||
|
**Regra:** Desk é master para ops; FOSS é master para visibilidade cliente billing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Payload Desk (`tickets.payload` — extensão Spec 044)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"event": "onboarding.escalated",
|
||||||
|
"domain": "empresa.com.br",
|
||||||
|
"session_id": "331b4022-70a5-4a9d-ba3e-08aaa06cb4f4",
|
||||||
|
"data": {
|
||||||
|
"wizard_ticket_id": "OB-D424843A",
|
||||||
|
"client_note": "DNS não propaga",
|
||||||
|
"reason": "client_support_request"
|
||||||
|
},
|
||||||
|
"foss_sync": {
|
||||||
|
"foss_ticket_id": 42,
|
||||||
|
"external_customer_id": 17,
|
||||||
|
"synced_at": "2026-07-01T18:00:00Z",
|
||||||
|
"last_foss_event": "ticket.reply",
|
||||||
|
"foss_url": "https://financeiro.ligbox.com.br/admin/support/ticket/42"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Pré-requisitos para espelho FOSS
|
||||||
|
|
||||||
|
| Condição | Obrigatório |
|
||||||
|
|----------|-------------|
|
||||||
|
| `billing_accounts.external_customer_id` | Sim (Spec 043) |
|
||||||
|
| Ticket Desk com `domain` | Sim |
|
||||||
|
| Role staff a criar espelho | `sales_admin`, `sales_support`, `technician`, `ops_lead` |
|
||||||
|
| Onboarding puro (sem FOSS client) | Espelho **adiado** até Activar conta |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. URLs deep-link
|
||||||
|
|
||||||
|
| Destino | URL |
|
||||||
|
|---------|-----|
|
||||||
|
| Desk ticket | `https://desk.ligbox.com.br/#ticket/{desk_ticket_id}` |
|
||||||
|
| Portal OB- tracking | `https://onboard.ligbox.com.br/onboard?session={session_id}&ticket={wizard_ticket_id}` |
|
||||||
|
| FOSS admin ticket | `https://financeiro.ligbox.com.br/admin/support/ticket/{foss_ticket_id}` |
|
||||||
|
| FOSS client ticket | `https://financeiro.ligbox.com.br/support/ticket/{foss_ticket_id}` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Histórico
|
||||||
|
|
||||||
|
| Versão | Data | Autor | Notas |
|
||||||
|
|--------|------|-------|-------|
|
||||||
|
| 1.0 | 2026-07-01 | Roger / Cursor | Documento inicial Spec 044 |
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
# Contrato — API Sincronização Tickets Desk ↔ FOSS
|
||||||
|
|
||||||
|
**Spec:** [044](../spec.md)
|
||||||
|
**VM122:** Desk API · **VM123:** FOSSBilling Admin API
|
||||||
|
**Status:** 📋 Especificado — implementação pendente
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Desk → FOSS — criar espelho
|
||||||
|
|
||||||
|
**Quando:** ticket Desk criado ou escalado **e** `external_customer_id` disponível.
|
||||||
|
|
||||||
|
### `foss_client.create_support_ticket()` (novo módulo VM122)
|
||||||
|
|
||||||
|
```
|
||||||
|
POST https://financeiro.ligbox.com.br/api/admin/support/ticket_create
|
||||||
|
Auth: Basic admin@ligbox.com.br:{FOSS_ADMIN_API_KEY}
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
```
|
||||||
|
|
||||||
|
| Campo FOSS | Origem Desk |
|
||||||
|
|------------|-------------|
|
||||||
|
| `client_id` | `billing_accounts.external_customer_id` |
|
||||||
|
| `subject` | `tickets.subject` |
|
||||||
|
| `content` | Primeira nota + link Desk + OB- se existir |
|
||||||
|
| `helpdesk` | `Ligbox Ops` (departamento default) |
|
||||||
|
| `priority` | mapa Desk priority → FOSS |
|
||||||
|
|
||||||
|
**Resposta esperada:** `{ "result": { "id": 42 } }` → gravar `foss_ticket_id=42`.
|
||||||
|
|
||||||
|
**Idempotência:** antes de criar, `GET ticket by desk_ticket_id` em cache local ou custom field FOSS `desk_ticket_id`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. FOSS → Desk — webhook inbound
|
||||||
|
|
||||||
|
### `POST /api/v1/webhooks/foss/support`
|
||||||
|
|
||||||
|
**Auth:** header `X-Foss-Webhook-Secret: {FOSS_WEBHOOK_SECRET}`
|
||||||
|
**Content-Type:** `application/json`
|
||||||
|
|
||||||
|
### Payload
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"event": "ticket.reply",
|
||||||
|
"foss_ticket_id": 42,
|
||||||
|
"client_id": 17,
|
||||||
|
"domain": "empresa.com.br",
|
||||||
|
"subject": "Problema DNS",
|
||||||
|
"status": "open",
|
||||||
|
"message": "Cliente respondeu: ainda não resolveu",
|
||||||
|
"author": "client",
|
||||||
|
"created_at": "2026-07-01T18:05:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| `event` | Acção Desk |
|
||||||
|
|---------|------------|
|
||||||
|
| `ticket.opened` | Criar ticket Desk se não existir (cliente abriu no FOSS) |
|
||||||
|
| `ticket.reply` | Append nota interna + notificar assignee |
|
||||||
|
| `ticket.closed` | `UPDATE tickets SET status='closed'` |
|
||||||
|
| `ticket.reopened` | `status='open'` |
|
||||||
|
|
||||||
|
### Response 200
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"desk_ticket_id": 45,
|
||||||
|
"handled": true,
|
||||||
|
"duplicate": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Erros
|
||||||
|
|
||||||
|
| HTTP | Condição |
|
||||||
|
|------|----------|
|
||||||
|
| 401 | Secret inválido |
|
||||||
|
| 404 | `foss_ticket_id` sem correlação e `client_id` desconhecido |
|
||||||
|
| 409 | Evento duplicado (idempotência) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Desk — API staff (fase E)
|
||||||
|
|
||||||
|
### `POST /api/v1/support/tickets`
|
||||||
|
|
||||||
|
**Auth:** JWT Desk · roles: `technician+`, `sales_support+`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"domain": "empresa.com.br",
|
||||||
|
"subject": "Webmail inacessível",
|
||||||
|
"body": "Cliente reporta erro 502",
|
||||||
|
"mirror_foss": true,
|
||||||
|
"wizard_ticket_id": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fluxo:**
|
||||||
|
1. Resolve `billing_accounts` por `domain`
|
||||||
|
2. INSERT `tickets`
|
||||||
|
3. Se `mirror_foss=true` e `external_customer_id` → `foss_client.create_support_ticket()`
|
||||||
|
4. Return `{ desk_ticket_id, foss_ticket_id, tracking_url }`
|
||||||
|
|
||||||
|
### `GET /api/v1/support/tickets/{id}/sync-status`
|
||||||
|
|
||||||
|
Retorna estado sync FOSS + links.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Portal VM112 — sem alteração v1
|
||||||
|
|
||||||
|
Endpoints existentes mantidos:
|
||||||
|
|
||||||
|
| Método | Path | Notas |
|
||||||
|
|--------|------|-------|
|
||||||
|
| `POST` | `/api/onboarding/support/ticket` | Cria OB- + webhook Desk |
|
||||||
|
| `GET` | `/api/onboarding/support/ticket/{OB-}/public` | Portal cliente Spec 026 |
|
||||||
|
|
||||||
|
**Extensão fase E:** resposta inclui `desk_ticket_id` quando sync completo (opcional, não bloqueia cliente).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. FOSS — configuração webhook (VM123)
|
||||||
|
|
||||||
|
Opções (escolher uma na implementação):
|
||||||
|
|
||||||
|
| Opção | Prós | Contras |
|
||||||
|
|-------|------|---------|
|
||||||
|
| **A** Hook PHP FOSS custom | Tempo real | Requer patch container |
|
||||||
|
| **B** Cron Desk poll `support/ticket_get_list` | Sem patch FOSS | Latência 1–5 min |
|
||||||
|
| **C** Traefik + sidecar notifier | Desacoplado | Mais infra |
|
||||||
|
|
||||||
|
**Recomendação v1:** Opção **B** (poll) + Opção **A** quando estável.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Variáveis ambiente (VM122)
|
||||||
|
|
||||||
|
| Variável | Descrição |
|
||||||
|
|----------|-----------|
|
||||||
|
| `FOSSBILLING_URL` | `https://financeiro.ligbox.com.br` |
|
||||||
|
| `FOSS_ADMIN_EMAIL` | Conta M2M admin |
|
||||||
|
| `FOSS_ADMIN_API_KEY` | API key FOSS (Spec 027) |
|
||||||
|
| `FOSS_WEBHOOK_SECRET` | Validação inbound FOSS→Desk |
|
||||||
|
| `FOSS_TICKET_SYNC_ENABLED` | `true` / `false` feature flag |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Testes curl
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Webhook simulado FOSS → Desk
|
||||||
|
curl -s -X POST https://desk.ligbox.com.br/api/v1/webhooks/foss/support \
|
||||||
|
-H "X-Foss-Webhook-Secret: $FOSS_WEBHOOK_SECRET" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"event": "ticket.reply",
|
||||||
|
"foss_ticket_id": 42,
|
||||||
|
"client_id": 17,
|
||||||
|
"domain": "empresa.com.br",
|
||||||
|
"message": "Teste sync Spec 044"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Histórico
|
||||||
|
|
||||||
|
| Versão | Data | Notas |
|
||||||
|
|--------|------|-------|
|
||||||
|
| 1.0 | 2026-07-01 | Contrato inicial Spec 044 |
|
||||||
109
ligbox-ops-platform/specs/044-foss-desk-ticket-sync/spec.md
Normal file
109
ligbox-ops-platform/specs/044-foss-desk-ticket-sync/spec.md
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
# Spec 044 — Sincronização Tickets: Portal ↔ Desk ↔ FOSS
|
||||||
|
|
||||||
|
**Criado:** 2026-07-01
|
||||||
|
**Solicitado por:** Roger
|
||||||
|
**Status:** 📋 **Especificado — implementação pendente**
|
||||||
|
**Prioridade:** P1 (suporte unificado pós-activação)
|
||||||
|
**Sistemas:** VM112 Portal · VM122 Desk · VM123 FOSSBilling
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resumo
|
||||||
|
|
||||||
|
Hoje existem **três filas de tickets isoladas**:
|
||||||
|
|
||||||
|
| Sistema | ID | Estado |
|
||||||
|
|---------|-----|--------|
|
||||||
|
| Portal wizard (VM112) | `OB-XXXXXXXX` | ✅ Activo — JSON local + portal cliente |
|
||||||
|
| Desk Ops (VM122) | `#N` / `CH-*` | ✅ Activo — webhook VM112 |
|
||||||
|
| FOSS Support (VM123) | `foss_ticket_id` | ❌ **Sem sync** com portal/Desk |
|
||||||
|
|
||||||
|
Esta spec define a **ponte bidireccional** Desk ↔ FOSS, preservando o portal wizard como canal de entrada do cliente e o Desk como **fonte de verdade operacional**.
|
||||||
|
|
||||||
|
**Contratos:**
|
||||||
|
- [ticket-field-mapping.md](./contracts/ticket-field-mapping.md) — chaves de correlação
|
||||||
|
- [ticket-sync-api.md](./contracts/ticket-sync-api.md) — webhooks e endpoints API
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Specs relacionadas
|
||||||
|
|
||||||
|
| Spec | Relação |
|
||||||
|
|------|---------|
|
||||||
|
| [001](../001-webhook-vm112-integration/spec.md) | Webhooks VM112 → Desk (base) |
|
||||||
|
| [010](../010-desk-assist-takeover/spec.md) | Escalada, ASM, `onboarding.escalated` |
|
||||||
|
| [012](../012-abandoned-onboarding-lead/spec.md) | Ticket único por jornada onboarding |
|
||||||
|
| [024](../024-openpanel-fossbilling/spec.md) | FOSS VM123, módulo Support |
|
||||||
|
| [027](../027-desk-rbac-function-matrix/contracts/vm123-product-roles.md) | `support` FOSS, roles comercial |
|
||||||
|
| [039](../039-ligbox-ops-authorization-catalog/spec.md) | `vm123_foss.support.ticket` |
|
||||||
|
| [041](../041-desk-operational-feed/spec.md) | Central Operacional — canal Tickets |
|
||||||
|
| [043](../043-desk-client-activation-sync/spec.md) | `external_customer_id` FOSS pós-activação |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arquitectura alvo
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ VM112 — Portal (onboard.ligbox.com.br) │
|
||||||
|
│ OB-* tickets · POST /api/onboarding/support/ticket │
|
||||||
|
│ Cliente acompanha: GET .../support/ticket/{OB-}/public │
|
||||||
|
└───────────────────────────────┬─────────────────────────────────────────┘
|
||||||
|
│ webhook onboarding.escalated (+ started)
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ VM122 — Desk (fonte de verdade ops) │
|
||||||
|
│ tickets.payload: wizard_ticket_id, foss_ticket_id, external_customer_id│
|
||||||
|
│ Staff: Chamados · Serviços · Central Operacional (041) │
|
||||||
|
└───────────────┬───────────────────────────────┬─────────────────────────┘
|
||||||
|
│ POST espelho (M2M) │ webhook FOSS → Desk
|
||||||
|
▼ ▼
|
||||||
|
┌─────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ VM123 — FOSSBilling Support │
|
||||||
|
│ Cliente: financeiro.ligbox.com.br/support │
|
||||||
|
│ Staff: /admin/support · API /api/admin/support/* │
|
||||||
|
└─────────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Regras de negócio
|
||||||
|
|
||||||
|
1. **Um incidente = um ticket Desk** — nunca duplicar `#N` para a mesma `session_id` ou `foss_ticket_id`.
|
||||||
|
2. **Portal OB-** continua a existir para onboarding; Desk grava `wizard_ticket_id` no payload (já parcialmente implementado na UI).
|
||||||
|
3. **FOSS espelho** só após `external_customer_id` conhecido (Spec 043) — tickets de onboarding pré-FOSS ficam só Desk + OB-.
|
||||||
|
4. **Sync bidireccional de estado:** `open` ↔ `in_progress` ↔ `resolved` ↔ `closed` (mapa em contrato).
|
||||||
|
5. **Cliente pós-activação** pode abrir ticket no FOSS client area **ou** no portal/console Ligbox; ambos convergem no Desk.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fases de implementação
|
||||||
|
|
||||||
|
| Fase | Entrega | VM |
|
||||||
|
|------|---------|-----|
|
||||||
|
| **A** | Documentação + contratos (esta spec) | CT130 |
|
||||||
|
| **B** | `foss_client.create_support_ticket()` + espelho Desk→FOSS | VM122 |
|
||||||
|
| **C** | Webhook FOSS → Desk (`POST /api/v1/webhooks/foss/support`) | VM122 + VM123 |
|
||||||
|
| **D** | UI Desk: link FOSS ticket + badge sync | VM122 |
|
||||||
|
| **E** | Portal pós-activação: criar via Desk API (propaga FOSS) | VM112 / Console |
|
||||||
|
|
||||||
|
Ver [tasks.md](./tasks.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fora de escopo (v1)
|
||||||
|
|
||||||
|
- OTRS (→ Spec 011)
|
||||||
|
- Sync automático e-mail inbound (→ Spec 041 fase B)
|
||||||
|
- Tickets Odoo Helpdesk
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Validação Roger
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1) Cliente abre OB- no wizard → Desk #N com wizard_ticket_id
|
||||||
|
# 2) Activar conta (Spec 043) → external_customer_id preenchido
|
||||||
|
# 3) Staff responde no Desk → foss_ticket_id criado no FOSS
|
||||||
|
# 4) Cliente responde no FOSS → webhook actualiza nota no Desk #N
|
||||||
|
```
|
||||||
42
ligbox-ops-platform/specs/044-foss-desk-ticket-sync/tasks.md
Normal file
42
ligbox-ops-platform/specs/044-foss-desk-ticket-sync/tasks.md
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Spec 044 — Tasks
|
||||||
|
|
||||||
|
## Documentação
|
||||||
|
- [x] Spec índice `spec.md`
|
||||||
|
- [x] Contrato `contracts/ticket-field-mapping.md`
|
||||||
|
- [x] Contrato `contracts/ticket-sync-api.md`
|
||||||
|
- [x] Registo em `SPEC-REGISTRY.md`
|
||||||
|
- [x] Ligações cruzadas specs 010/012/024/041/043
|
||||||
|
- [x] Sync Obsidian VM130
|
||||||
|
|
||||||
|
## Fase A — Estado actual (baseline)
|
||||||
|
- [x] Portal OB- → Desk via `onboarding.escalated` (VM112)
|
||||||
|
- [x] UI Desk mostra `wizard_ticket_id` (OB-) no painel ticket
|
||||||
|
- [x] FOSS Support nativo em VM123 (sem bridge)
|
||||||
|
- [ ] Inventário endpoints FOSS Support API (Roger validar admin)
|
||||||
|
|
||||||
|
## Fase B — Desk → FOSS (espelho)
|
||||||
|
- [ ] Coluna/payload `foss_ticket_id` em `tickets`
|
||||||
|
- [ ] `foss_client.create_support_ticket()` — M2M admin API
|
||||||
|
- [ ] Hook pós-criação ticket Desk: se `billing_accounts.external_customer_id` → espelho FOSS
|
||||||
|
- [ ] Idempotência: não recriar se `foss_ticket_id` já existe
|
||||||
|
- [ ] Unit tests `test_foss_ticket_sync_044.py`
|
||||||
|
|
||||||
|
## Fase C — FOSS → Desk (webhook)
|
||||||
|
- [ ] Endpoint `POST /api/v1/webhooks/foss/support` (auth `FOSS_WEBHOOK_SECRET`)
|
||||||
|
- [ ] Plugin/hook FOSS ou cron poll — eventos `ticket.opened`, `ticket.reply`, `ticket.closed`
|
||||||
|
- [ ] Upsert nota / status no ticket Desk correlacionado
|
||||||
|
- [ ] Log em `webhook_events` source=`vm123-foss`
|
||||||
|
|
||||||
|
## Fase D — UI Desk
|
||||||
|
- [ ] Painel ticket: badge «FOSS #123» + deep-link `financeiro.ligbox.com.br/admin/support`
|
||||||
|
- [ ] Serviços IaaS / ficha cliente: «Abrir ticket FOSS» (roles sales_admin, sales_support)
|
||||||
|
- [ ] Central Operacional (041): evento `desk_tickets` com `foss_ticket_id`
|
||||||
|
|
||||||
|
## Fase E — Portal pós-activação
|
||||||
|
- [ ] Console `/me/suporte` ou FOSS client area — single entry (decisão Roger)
|
||||||
|
- [ ] API Desk `POST /api/v1/support/tickets` → cria Desk + FOSS espelho
|
||||||
|
- [ ] Resposta cliente inclui `tracking_url` (portal ou FOSS)
|
||||||
|
|
||||||
|
## Testes E2E
|
||||||
|
- [ ] Roger: OB- onboarding → activar conta → staff responde → cliente vê no FOSS
|
||||||
|
- [ ] Roger: cliente abre ticket FOSS → aparece no Desk Chamados
|
||||||
|
|
@ -8,5 +8,6 @@
|
||||||
| **041** | **`041-desk-operational-feed/`** | **Central Operacional (ex-Mensagens) + ops-inbox API** | **0.13.0** |
|
| **041** | **`041-desk-operational-feed/`** | **Central Operacional (ex-Mensagens) + ops-inbox API** | **0.13.0** |
|
||||||
| **042** | **`042-ligbox-nettools-portal/`** | **NetTools — 23 ferramentas OSS em nettools.ligbox.com.br** | — |
|
| **042** | **`042-ligbox-nettools-portal/`** | **NetTools — 23 ferramentas OSS em nettools.ligbox.com.br** | — |
|
||||||
| **043** | **`043-desk-client-activation-sync/`** | **Mapa campos Wizard→Desk→FOSS→OpenPanel→Odoo + API Activar conta** | — |
|
| **043** | **`043-desk-client-activation-sync/`** | **Mapa campos Wizard→Desk→FOSS→OpenPanel→Odoo + API Activar conta** | — |
|
||||||
|
| **044** | **`044-foss-desk-ticket-sync/`** | **Sync tickets Portal OB- ↔ Desk ↔ FOSS Support** | — |
|
||||||
|
|
||||||
Atualizado: 2026-07-01 · Roger · Spec 043 mapeamento activação cliente
|
Atualizado: 2026-07-01 · Roger · Spec 044 sync tickets FOSS/portal
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue