obsidian-vault/ligbox-ops-platform/specs/010-desk-assist-takeover/spec.md
2026-06-19 17:26:42 +00:00

14 KiB

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

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

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)

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)

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:

{
  "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)

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