418 lines
14 KiB
Markdown
418 lines
14 KiB
Markdown
# Feature Specification: Desk Assist & Takeover — Intervenção Técnica (010)
|
|
|
|
**Criado:** 2026-06-10
|
|
**Solicitado por:** Roger
|
|
**Status:** 📋 **Draft — decisões fechadas, pronta para plano**
|
|
**Prioridade:** **P0** (bloqueia operação humana no onboarding)
|
|
**Depende de:** Spec 001 (webhooks VM112), Spec 003 (auth/RBAC)
|
|
**Relacionada:** Spec 007 (push escalada), Spec 008 (Kanban/SLA), Spec 011 (OTRS futuro)
|
|
**API alvo:** `0.9.0-desk-assist` (VM122) + contratos VM112 `assist-v1`
|
|
|
|
---
|
|
|
|
## Resumo
|
|
|
|
Hoje o **Ligbox Ops Desk** é **observacional**: técnicos veem funil, tickets e timeline, mas **não podem intervir** quando o onboarding trava ou o cliente pede ajuda.
|
|
|
|
**Objetivo Spec 010:** transformar o Desk no **control plane de assistência humana** — com escalada bidirecional (cliente ou técnico), **modo ASM** (técnico substitui o cliente no wizard), pausa de sessão, ticket atribuído e **ações operacionais só via Desk** (nunca embed Proxmox/Carbonio).
|
|
|
|
O **wizard continua no VM112**; o **Desk (VM122)** orquestra escalada, atribuição, audit e acções API.
|
|
|
|
---
|
|
|
|
## Decisões confirmadas (Roger — 2026-06-10)
|
|
|
|
| # | Pergunta | Decisão |
|
|
|---|----------|---------|
|
|
| 1 | Quem inicia escalada? | **Cliente** (botão no wizard) **e técnico** (puxar sessão activa no Desk) |
|
|
| 2 | Visibilidade do técnico | **Não cego total** — observa até etapa simples; **intervenção relevante a partir de `domain.validated`**; takeover pleno especialmente após `account.created` |
|
|
| 3 | Takeover vs co-browse | **ASM — técnico substitui o cliente** (não co-browse guia). Cliente pausado durante assistência |
|
|
| 4 | Consoles externos | **Links em nova aba** (Proxmox, Carbonio, Traefik, Cloudflare) — **acções operacionais só no Desk** via API |
|
|
| 5 | OTRS | Escalada **fica no Desk (VM122)** por agora. Integração OTRS → **Spec 011** (VM112 ↔ OTRS, futuro) |
|
|
|
|
---
|
|
|
|
## Dois modos de operação
|
|
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> Observador: onboarding normal
|
|
Observador --> Escalado: cliente pede ajuda OU técnico puxa OU failed OU stale
|
|
Escalado --> Assistindo: técnico assume ASM takeover
|
|
Assistindo --> Observador: handoff / resolvido
|
|
note right of Observador
|
|
Etapas started até antes de domain:
|
|
funil mínimo, sem takeover
|
|
end note
|
|
note right of Assistindo
|
|
Cliente pausado
|
|
Técnico actua no wizard VM112
|
|
Acções API via Desk
|
|
end note
|
|
```
|
|
|
|
### Modo Observador (default)
|
|
|
|
- Técnico vê **funil + sessões activas** (domínio, etapa, `session_id`, stale).
|
|
- Até **`onboarding.started`**: visibilidade mínima — processo deve correr sozinho.
|
|
- A partir de **`domain.validated`**: ticket pode ser criado/atualizado; técnico **pode** escalar ou ser alertado.
|
|
- **Sem acção** no wizard do cliente.
|
|
|
|
### Modo Assistência activa (ASM)
|
|
|
|
- Cliente **pausado** — wizard bloqueado com mensagem pt-BR.
|
|
- Técnico **substitui** o cliente no wizard (token takeover VM112).
|
|
- Ticket: `assisting` + `assigned_to`.
|
|
- Desk expõe **Console de assistência**: passo, timeline, acções permitidas, links externos (nova aba).
|
|
- **Handoff**: técnico encerra assistência → cliente retoma.
|
|
|
|
---
|
|
|
|
## Etapas do funil e regras de visibilidade/intervenção
|
|
|
|
Alinhado a `FUNNEL_EVENT_RANK` (Spec 001):
|
|
|
|
| Rank | Evento | Etapa | Observador | Escalar | Takeover ASM |
|
|
|------|--------|-------|------------|---------|--------------|
|
|
| 1 | `onboarding.started` | started | ✅ mínimo | ❌ | ❌ **+ ticket no «Criar conta»** (Spec 012 — Roger 2026-06-10) |
|
|
| 2 | `domain.validated` | domain_validated | ✅ | ✅ | ✅ (técnico puxa) |
|
|
| 3 | `dns.applied` | dns_applied | ✅ | ✅ | ✅ |
|
|
| 4 | `account.created` | account_created | ✅ + nota no ticket | ✅ | ✅ **principal** |
|
|
| 5+ | infra, completed, company, webmail | … | ✅ | ✅ | ✅ |
|
|
| 99 | `onboarding.failed` | failed | ✅ + ticket auto | ✅ auto | ✅ |
|
|
|
|
**Regra PII:** técnico **não fica totalmente cego** — vê domínio e etapa cedo; dados sensíveis (e-mail conta, perfil empresa) **reforçados após `account.created`** no console de assistência.
|
|
|
|
---
|
|
|
|
## Quem inicia escalada
|
|
|
|
| Origem | Actor | Acção |
|
|
|--------|-------|-------|
|
|
| Wizard VM112 | Cliente | Botão **«Preciso de ajuda técnica»** → webhook `onboarding.escalated` |
|
|
| Desk VM122 | Técnico / ops_lead | **«Assumir sessão»** em sessão ≥ `domain.validated` |
|
|
| Automático | Sistema | `onboarding.failed` · sessão stale 24h (já detectada) |
|
|
| Automático | Sistema | Push Spec 007 — «funil travado» (fase posterior) |
|
|
|
|
**Ambos** (cliente e técnico) podem iniciar. Primeiro a completar takeover **ganha** a sessão (lock optimista).
|
|
|
|
---
|
|
|
|
## Arquitetura
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
subgraph VM112["VM112 — Wizard"]
|
|
W[Wizard cliente]
|
|
WA[Wizard ASM takeover]
|
|
API112[Assist API]
|
|
end
|
|
subgraph VM122["VM122 — Desk"]
|
|
DESK[Desk UI Console]
|
|
API122[Assist orchestrator]
|
|
DB[(SQLite tickets + assist_log)]
|
|
end
|
|
W -->|webhooks| API122
|
|
DESK -->|JWT| API122
|
|
API122 -->|service token| API112
|
|
API112 --> WA
|
|
API112 -->|pause/resume| W
|
|
DESK -->|links nova aba| EXT[Proxmox · Carbonio · Traefik · CF]
|
|
API122 -->|acções API| API112
|
|
```
|
|
|
|
**Princípio:** VM122 **nunca** embeda Proxmox/Carbonio. Links são referência; **botões de acção** chamam API (VM112 ou integrações futuras 005/006).
|
|
|
|
---
|
|
|
|
## Estados de ticket (novo)
|
|
|
|
| Status | Significado |
|
|
|--------|-------------|
|
|
| `open` | Ticket criado, ninguém a assistir |
|
|
| `escalated` | Cliente ou sistema pediu ajuda |
|
|
| `assisting` | Técnico em ASM takeover activo |
|
|
| `resolved` | Problema resolvido, aguarda fecho |
|
|
| `closed` | Encerrado |
|
|
|
|
Transições:
|
|
|
|
```
|
|
open → escalated → assisting → resolved → closed
|
|
open → assisting (técnico puxa directo, se ≥ domain.validated)
|
|
assisting → open (handoff cancelado — raro)
|
|
qualquer → closed (ops_lead / super_admin)
|
|
```
|
|
|
|
---
|
|
|
|
## Data model (VM122)
|
|
|
|
### `tickets` (alteração)
|
|
|
|
| Campo | Tipo | Uso |
|
|
|-------|------|-----|
|
|
| `status` | TEXT | + `escalated`, `assisting`, `resolved` |
|
|
| `session_id` | TEXT | FK lógica onboarding VM112 |
|
|
| `assist_mode` | TEXT | `null` \| `asm` |
|
|
| `assisted_by` | TEXT | username técnico em takeover |
|
|
| `assisted_at` | TEXT | ISO timestamp |
|
|
| `client_paused` | INTEGER | 1 se wizard pausado |
|
|
|
|
### `assist_sessions` (nova)
|
|
|
|
```sql
|
|
CREATE TABLE assist_sessions (
|
|
id INTEGER PRIMARY KEY,
|
|
session_id TEXT NOT NULL,
|
|
ticket_id INTEGER,
|
|
initiated_by TEXT NOT NULL, -- 'client' | 'technician' | 'system'
|
|
initiated_by_user TEXT, -- desk username se técnico
|
|
status TEXT NOT NULL, -- 'active' | 'handoff' | 'ended'
|
|
funnel_stage TEXT,
|
|
domain TEXT,
|
|
takeover_token_hash TEXT, -- token VM112 (não plain text)
|
|
started_at TEXT NOT NULL,
|
|
ended_at TEXT,
|
|
audit_summary TEXT
|
|
);
|
|
```
|
|
|
|
### `assist_actions` (audit log)
|
|
|
|
```sql
|
|
CREATE TABLE assist_actions (
|
|
id INTEGER PRIMARY KEY,
|
|
assist_session_id INTEGER NOT NULL,
|
|
actor TEXT NOT NULL,
|
|
action TEXT NOT NULL, -- 'escalate' | 'takeover' | 'action.dns_retry' | 'handoff'
|
|
payload TEXT,
|
|
created_at TEXT NOT NULL
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## API VM122 (Desk — orchestrator)
|
|
|
|
| Método | Endpoint | Auth | Descrição |
|
|
|--------|----------|------|-----------|
|
|
| GET | `/api/v1/assist/sessions` | JWT | Sessões activas + estado assistência |
|
|
| GET | `/api/v1/assist/sessions/{session_id}` | JWT | Detalhe + timeline + ticket |
|
|
| POST | `/api/v1/assist/sessions/{session_id}/escalate` | JWT | Técnico escala manualmente |
|
|
| POST | `/api/v1/assist/sessions/{session_id}/takeover` | JWT | Inicia ASM — chama VM112 |
|
|
| POST | `/api/v1/assist/sessions/{session_id}/handoff` | JWT | Devolve controlo ao cliente |
|
|
| POST | `/api/v1/assist/sessions/{session_id}/actions/{action}` | JWT | Acção Desk (ver catálogo) |
|
|
| GET | `/api/v1/assist/sessions/{session_id}/links` | JWT | Deep links externos (nova aba) |
|
|
|
|
**Webhook ingress (VM112 → VM122):**
|
|
|
|
| Evento | Efeito |
|
|
|--------|--------|
|
|
| `onboarding.escalated` | Ticket `escalated` + notificação |
|
|
| `onboarding.assist.started` | Confirma takeover |
|
|
| `onboarding.assist.ended` | Handoff confirmado |
|
|
|
|
---
|
|
|
|
## API VM112 (wizard — contrato `assist-v1`)
|
|
|
|
*Implementação no repo VM112 (SUP-4). Desk consome.*
|
|
|
|
| Método | Endpoint | Auth | Descrição |
|
|
|--------|----------|------|-----------|
|
|
| POST | `/api/onboarding/sessions/{id}/pause` | service + desk JWT | Pausa wizard cliente |
|
|
| POST | `/api/onboarding/sessions/{id}/takeover` | desk JWT | Retorna URL wizard ASM + token |
|
|
| POST | `/api/onboarding/sessions/{id}/resume` | desk JWT | Retoma cliente |
|
|
| GET | `/api/onboarding/sessions/{id}/state` | service | Etapa, erros, campos permitidos |
|
|
| POST | `/api/onboarding/sessions/{id}/actions/{action}` | desk JWT | Executa acção no passo actual |
|
|
|
|
**Resposta takeover:**
|
|
|
|
```json
|
|
{
|
|
"takeover_url": "https://onboard.ligbox.com.br/assist/{session_id}?token=...",
|
|
"expires_in": 3600,
|
|
"client_paused": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Catálogo de acções (só Desk — MVP)
|
|
|
|
Acções invocam VM112 ou integrações; **nunca** abrem shell Proxmox.
|
|
|
|
| Acção | Etapa mínima | Efeito |
|
|
|-------|--------------|--------|
|
|
| `dns.revalidate` | dns_applied | Revalida DNS / Cloudflare via VM112 |
|
|
| `dns.reapply` | dns_applied | Re-aplica registos |
|
|
| `account.retry_sync` | account_created | Re-sync Carbonio |
|
|
| `infra.resync` | infra_synced | Re-sync Proxmox/Traefik via VM112 |
|
|
| `onboarding.mark_step_complete` | assisting | Avança passo (com confirmação) |
|
|
| `onboarding.abort` | assisting | Encerra sessão com motivo (ops_lead+) |
|
|
|
|
Links externos (GET `/links`) — **nova aba**, sem acção automática:
|
|
|
|
| Sistema | URL template |
|
|
|---------|--------------|
|
|
| Proxmox | `https://proxmox.../?node=...` (contexto tenant) |
|
|
| Carbonio | Admin domain |
|
|
| Traefik | Dashboard route |
|
|
| Cloudflare | Zone DNS |
|
|
|
|
---
|
|
|
|
## UI Desk — Console de assistência
|
|
|
|
### Dashboard / Funil
|
|
|
|
- Sessões **clicáveis** (hoje read-only).
|
|
- Badge: `observando` · `escalado` · `assistindo`.
|
|
- Botão **«Assumir sessão»** se etapa ≥ `domain.validated` e não locked.
|
|
|
|
### Vista ticket / sessão
|
|
|
|
| Bloco | Conteúdo |
|
|
|-------|----------|
|
|
| **Cabeçalho** | Domínio · etapa · `session_id` · assignee |
|
|
| **Estado** | Observador / Escalado / Assistindo (ASM) |
|
|
| **Timeline** | Webhooks existentes |
|
|
| **Acções Desk** | Botões catálogo (disabled se não assisting) |
|
|
| **Links** | Proxmox, Carbonio, Traefik, CF — `target=_blank` |
|
|
| **Takeover** | «Assumir sessão» → abre wizard ASM nova aba |
|
|
| **Handoff** | «Devolver ao cliente» |
|
|
|
|
### Permissões RBAC
|
|
|
|
| Role | Escalar | Takeover | Acções | Handoff | Ver links |
|
|
|------|---------|----------|--------|---------|-----------|
|
|
| super_admin | ✅ | ✅ | ✅ todas | ✅ | ✅ |
|
|
| ops_lead | ✅ | ✅ | ✅ todas | ✅ | ✅ |
|
|
| technician | ✅ | ✅ | ✅ N1/N2 | ✅ própria sessão | ✅ |
|
|
| noc | 👁️ | ❌ | ❌ | ❌ | 👁️ |
|
|
|
|
---
|
|
|
|
## Fluxo ASM (takeover)
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant C as Cliente VM112
|
|
participant D as Desk VM122
|
|
participant W as Wizard VM112
|
|
participant T as Técnico
|
|
|
|
alt Cliente pede ajuda
|
|
C->>W: Clica ajuda técnica
|
|
W->>D: webhook onboarding.escalated
|
|
else Técnico puxa
|
|
T->>D: POST takeover
|
|
end
|
|
D->>W: POST pause + takeover
|
|
W-->>C: Wizard pausado
|
|
W-->>D: takeover_url + token
|
|
D-->>T: Console + link ASM
|
|
T->>W: Actua no wizard ASM
|
|
T->>D: Acções API (dns.reapply, etc.)
|
|
T->>D: POST handoff
|
|
D->>W: POST resume
|
|
W-->>C: Retoma onboarding
|
|
```
|
|
|
|
---
|
|
|
|
## User stories
|
|
|
|
### US1 — Cliente pede ajuda (P0)
|
|
|
|
Como cliente no wizard, quero pedir ajuda técnica para destravar o onboarding.
|
|
|
|
**Aceite:** botão no VM112 · sessão pausada · ticket escalado no Desk · push/e-mail ops (007).
|
|
|
|
### US2 — Técnico assume sessão (P0)
|
|
|
|
Como técnico, quero assumir uma sessão após domínio validado e actuar no wizard em nome do cliente.
|
|
|
|
**Aceite:** ASM takeover · cliente pausado · audit log · handoff funcional.
|
|
|
|
### US3 — Acções só no Desk (P0)
|
|
|
|
Como técnico, quero revalidar DNS ou re-sync infra **pelo Desk**, sem aceder Proxmox directamente.
|
|
|
|
**Aceite:** botões acção chamam API · links externos só referência nova aba.
|
|
|
|
### US4 — Observação pré-domínio (P1)
|
|
|
|
Como ops, quero que etapas antes de domínio corram sem intervenção humana.
|
|
|
|
**Aceite:** takeover disabled antes de `domain.validated`.
|
|
|
|
### US5 — Conflito de takeover (P1)
|
|
|
|
Como ops_lead, quero que apenas um técnico assista por sessão.
|
|
|
|
**Aceite:** segundo takeover recebe 409 + nome do assignee.
|
|
|
|
---
|
|
|
|
## Critérios de aceite MVP
|
|
|
|
- [ ] Escalada cliente (VM112) + webhook `onboarding.escalated`
|
|
- [ ] Escalada técnico no Desk (≥ `domain.validated`)
|
|
- [ ] ASM takeover — técnico substitui cliente, cliente pausado
|
|
- [ ] Handoff — cliente retoma
|
|
- [ ] Estados ticket: escalated, assisting, resolved
|
|
- [ ] Console Desk: timeline + acções + links nova aba
|
|
- [ ] Catálogo acções MVP (dns.revalidate, account.retry_sync, infra.resync)
|
|
- [ ] Audit log `assist_actions`
|
|
- [ ] RBAC conforme tabela
|
|
- [ ] pt-BR em toda UI/mensagens
|
|
- [ ] **Sem** embed Proxmox/Carbonio
|
|
- [ ] OTRS **fora** — Spec 011
|
|
|
|
---
|
|
|
|
## Fora de escopo (010)
|
|
|
|
- Co-browse / pointer mode (Roger escolheu ASM puro)
|
|
- Embed de consoles externos
|
|
- OTRS (→ Spec 011)
|
|
- Kanban visual (→ Spec 008, após 010)
|
|
- Acções directas Proxmox API no Desk (→ integrações 005/006 encapsuladas depois)
|
|
|
|
---
|
|
|
|
## Dependências e ordem
|
|
|
|
| Spec | Relação |
|
|
|------|---------|
|
|
| **001** | Webhooks + funil + session_id |
|
|
| **003** | RBAC + assigned_to |
|
|
| **007** | Push «sessão escalada» (paralelo ok) |
|
|
| **008** | Kanban usa estados 010 |
|
|
| **011** | OTRS VM112 — futuro, não bloqueia 010 |
|
|
|
|
**Prioridade backlog:** 010 **antes** de 005/006 para onboarding operacional.
|
|
|
|
---
|
|
|
|
## Referências
|
|
|
|
- SAP Commerce **Assisted Service Mode (ASM)** — emulação sessão agente
|
|
- Chatbase **Takeover** — escalada humano assume controlo
|
|
- BACKLOG **DESK-3**, **SUP-4.1/4.2**
|
|
- `specs/010-desk-assist-takeover/tasks.md`
|
|
- `specs/010-desk-assist-takeover/quickstart.md`
|
|
- `specs/011-integration-otrs/spec.md` (stub)
|
|
|
|
---
|
|
|
|
## Fases de entrega
|
|
|
|
| Fase | Entrega | Onde |
|
|
|------|---------|------|
|
|
| **A** | Webhook escalada + estados ticket + UI «Assumir» (sem takeover ainda) | VM122 |
|
|
| **B** | VM112 pause/takeover/resume + wizard ASM | VM112 |
|
|
| **C** | Console acções Desk + audit | VM122 + VM112 |
|
|
| **D** | Push escalada (007) + links contextuais | VM122 |
|