# Feature Specification: Relógio por fase — Onboarding VM112 (014) **Criado:** 2026-06-16 **Solicitado por:** Roger **Status:** Implementação **Prioridade:** P1 **Depende de:** Spec 001 (webhooks VM112), módulo `funnel-timing` (Spec 015) **Módulo Desk:** `funnel-timing` (pode ser desactivado sem quebrar o sistema) --- ## Resumo Exibir **duração entre cada fase** do funil VM112→VM122 e o **tempo total** da sessão (primeiro evento → conclusão ou último evento), em Audit Overview, Tickets e API timeline. **Princípio:** timestamps já existem em `webhook_events`; esta spec **calcula e apresenta** deltas — não altera o wizard VM112. --- ## Fases medidas | Ordem | Evento | Label UI | |-------|--------|----------| | 0 | `session.started` | Sessão iniciada | | 1 | `domain.validated` | Domínio validado | | 2 | `dns.applied` | DNS aplicado | | 3 | `onboarding.started` | Criar conta | | 4 | `account.created` | Conta criada | | 5 | `infra.synced` | Infra sync | | 6 | `onboarding.completed` | Concluído | --- ## Campos API (quando módulo activo) Por evento na timeline: - `duration_from_prev_sec` / `duration_from_prev_label` - `duration_from_start_sec` / `duration_from_start_label` Resumo da sessão: - `total_duration_sec` / `total_duration_label` - `started_at`, `completed_at` - `current_phase_elapsed_sec` (se sessão não concluída — tempo desde último evento) --- ## Onde aparece na UI | Ecrã | Comportamento | |------|----------------| | Overview → detalhe domínio | Timeline com relógio entre fases + total | | Tickets → timeline onboard | Idem | | Infra 2 → sessões | Badge tempo total (se concluído) ou “parado há X” | | Módulo desactivado | Timeline clássica só com data/hora (sem regressão) | --- ## Regras - Duração negativa ou eventos fora de ordem: usar ordem por `id`/`created_at` ASC. - Backfill (`data.backfill=true`): incluir no cálculo (marca visual opcional). - SLA futuro (Spec 014-B): alerta se fase > N min — fora do MVP. --- ## Testes - Sessão `iofficebooks.com`: delta domain→dns ~116s - Timeline API com módulo ON retorna `total_duration_label` - Timeline API com módulo OFF não inclui campos `duration_*`