ligbox-ops-platform/specs/004-onboard-funnel-events/spec.md
Ligbox Spec Hub 3a2c64834b Initial import: ligbox-ops-platform + specs + LAPTOP + obsidian merge (CT130)
Source: VM122 /opt + obsidian-infra + LAPTOP
Hub: CT130 spec-hub 10.10.10.130
2026-06-19 17:26:41 +00:00

7.1 KiB

Feature Specification: Funil de Onboarding Completo (004)

Feature Branch: 004-onboard-funnel-events

Created: 2026-06-08

Status: Draft

Input: Completar a integração VM112 → VM122 com todos os marcos do wizard de onboarding, timeline por sessão e widget de funil no Dashboard Ops — continuando a feature 001 (Phase D).

Depends on: 001-webhook-vm112-integration (MVP account.created entregue)

User Scenarios & Testing (mandatory)

User Story 1 — Visibilidade do funil activo (Priority: P1)

A equipa ops vê no Dashboard quantos onboardings estão em cada fase (domínio validado, DNS aplicado, conta criada, concluído) sem abrir o portal VM112.

Why this priority: Responde directamente à expectativa de um painel com informação útil — mostra onde clientes travam.

Independent Test: Emitir eventos simulados para 3 sessões em fases diferentes e confirmar contadores correctos no widget funil.

Acceptance Scenarios:

  1. Given 2 sessões com domain.validated e 1 com onboarding.completed, When o dashboard carrega, Then o widget mostra contagens por fase actual.
  2. Given sessão sem eventos há > 24h, When listada no funil, Then aparece marcada como stale (inactiva).

User Story 2 — Timeline por sessão no ticket (Priority: P1)

Ao abrir um ticket de onboarding, a equipa vê a sequência cronológica de eventos da mesma session_id (validação, DNS, conta, infra, conclusão).

Why this priority: Diagnóstico rápido quando onboarding falha a meio — sem cruzar logs manualmente.

Independent Test: Enviar 5 eventos com mesmo session_id e confirmar timeline ordenada no detalhe do ticket.

Acceptance Scenarios:

  1. Given ticket criado por account.created, When chegam domain.validated e dns.applied com mesma sessão, Then aparecem na timeline do ticket (notas/eventos).
  2. Given onboarding.completed para sessão existente, When processado, Then actualiza ticket (nota ou tag ready) sem criar ticket duplicado.

User Story 3 — Portal emite marcos do wizard (Priority: P1)

O portal VM112 emite webhooks para cada marco importante do funil, de forma não-bloqueante (mesmo padrão ops_webhook.py).

Why this priority: Sem emissor completo, o Ops não tem dados para funil nem timeline.

Independent Test: Percorrer wizard em staging e confirmar eventos no registo Ops por ordem.

Acceptance Scenarios:

  1. Given POST /validate-domain com sucesso, When resposta 200, Then emite domain.validated.
  2. Given POST /dns/cloudflare/apply com registos aplicados, When sucesso, Then emite dns.applied.
  3. Given provision infra concluído após criar conta, When sucesso, Then emite infra.synced.
  4. Given fluxo completo sem erro, When resposta final ao cliente, Then emite onboarding.completed.
  5. Given falha crítica (ex. CarbonioError em create account), When HTTP 400, Then emite onboarding.failed com motivo em data.error.

User Story 4 — Sessão iniciada (Priority: P2)

Quando o cliente escolhe/valida domínio pela primeira vez na sessão, o Ops regista onboarding.started para contagem de funil desde o início.

Why this priority: Permite taxa de conversão início → conclusão; não bloqueia MVP do funil.

Independent Test: Primeira validação de domínio numa sessão nova gera evento onboarding.started uma única vez.

Acceptance Scenarios:

  1. Given nova session_id, When primeiro validate-domain OK, Then emite onboarding.started (idempotente — não repete na mesma sessão).

Edge Cases

  • Eventos fora de ordem (ex. onboarding.completed antes de dns.applied): Ops aceita e ordena por timestamp na timeline.
  • Mesmo evento repetido (retry portal): idempotência event + session_id + domain — sem duplicar timeline.
  • Sessão sem session_id: evento aceite, funil agrupa em unknown.
  • Domínio com múltiplas sessões: funil mostra sessões separadas; tickets ligados por session_id.
  • Ops offline: portal continua; activity log regista falha webhook.

Requirements (mandatory)

Functional Requirements

  • FR-001: Portal DEVE emitir: onboarding.started, domain.validated, dns.applied, infra.synced, onboarding.completed, onboarding.failed via ops_webhook.emit_event.
  • FR-002: Emissão DEVE ser non-blocking (BackgroundTasks ou equivalente) — nunca alterar resposta HTTP ao cliente.
  • FR-003: Ops DEVE persistir todos os eventos em webhook_events (já existente).
  • FR-004: Ops DEVE expor GET /api/v1/onboard/funnel com contagens por fase e lista de sessões activas (últimas 48h).
  • FR-005: Ops DEVE expor GET /api/v1/onboard/sessions/{session_id}/timeline com eventos ordenados.
  • FR-006: Ticket existente (mesma session_id) DEVE enriquecer-se com novos eventos — notas internas ou campo timeline no detalhe.
  • FR-007: Apenas account.created e onboarding.failed criam ticket novo; restantes eventos actualizam contexto.
  • FR-008: Idempotência OBRIGATÓRIA: (event_type, session_id, domain) — já implementada em 001, manter.
  • FR-009: UI Dashboard DEVE incluir widget Funil Onboarding (contadores + link sessões).
  • FR-010: UI Ticket DEVE mostrar timeline de eventos da sessão.
  • FR-011: Comunicação LAN-only (10.10.10.11210.10.10.122).

Key Entities

  • Funnel Session: session_id, domain, current_stage, last_event_at, events[].
  • Funnel Stage: ordered enum — starteddomain_validateddns_appliedaccount_createdinfra_syncedcompleted | failed.
  • Timeline Entry: event_type, timestamp, data snapshot, source vm112-onboard.

Success Criteria (mandatory)

  • SC-001: 100% dos marcos do wizard (6 tipos) geram evento Ops quando portal e Ops disponíveis.
  • SC-002: Equipa identifica fase actual de um onboarding em < 10s via Dashboard (sem SSH no portal).
  • SC-003: Timeline completa visível no ticket para qualquer sessão com ≥ 2 eventos.
  • SC-004: Zero tickets duplicados por sessão além de account.created + opcional onboarding.failed.
  • SC-005: Falha Ops não afecta taxa de sucesso do wizard (0 regressões em testes E2E portal).

Assumptions

  • Receptor /api/v1/webhooks/onboard e ops_webhook.py já funcionais (001).
  • session_id disponível via bind_onboarding_session em todos os routers de onboarding.
  • Fases do funil mapeiam 1:1 aos passos actuais do wizard ibytera-mail-portal.
  • onboarding.completed dispara no fim de create_account após infra (mesmo request).
  • UI Desk v2 existente — extensão de dashboard e ticket detail, não rebuild.

Dependencies

  • Constitution v1.0.0 (separação VM112/122, LAN-only).
  • Feature 001 deployada em VM112 + VM122.
  • Feature 002 não conflita (origens diferentes).

Out of Scope

  • Notificações push (ntfy) em mudança de fase.
  • Auth/RBAC no Desk (feature 003 futura).
  • Sincronização Ops → Portal.
  • Expor webhook onboard na internet pública.
  • Kanban / SLA (feature desk futura).