# Feature Specification: Onboarding Abandonado → Lead CRM (012) **Criado:** 2026-06-10 **Solicitado por:** Roger **Status:** 📋 **Draft — decisões fechadas, pronta para plano** **Prioridade:** **P1** **Depende de:** Spec 001 (webhooks VM112), Spec 010 (ticket cedo + assist), Spec 007 (alertas — fase B) **API alvo:** `0.9.1-onboard-ticket` (VM122) + VM112 wizard + CRM TBD --- ## Resumo Cada sessão de onboarding no wizard VM112 gera **um ticket no Desk** no momento em que o cliente preenche e-mail/senha e clica **«Criar conta agora»** (`onboarding.started` com `step: create_account`). Esse ticket acompanha **todas as etapas** do funil. Se o cliente **abandonar** o processo ou ficar **parado muitas horas** sem concluir, o mesmo registro é **promovido a Lead** no CRM — base para outreach proativo via chat (canal a estudar: IP, tablet SEO, widget web, etc.). **Princípio:** não duplicar ticket nem lead — **um registro, uma jornada**. --- ## Decisões confirmadas (Roger — 2026-06-10) | # | Pergunta | Decisão | |---|----------|---------| | 1 | Quando criar ticket? | No clique **«Criar servidor/conta»** — webhook `onboarding.started` com `email` | | 2 | Precisa pedir suporte? | **Não** — ticket sempre, independente de escalada | | 3 | Etapas no ticket? | **Sim** — `funnel_notes` + backfill de `domain.validated` e `dns.applied` | | 4 | Abandono | Ticket `open` + sessão stale → **Lead CRM** (Spec 012) | | 5 | Outreach | Chat proativo com cliente — **dispositivo/canal TBD** | | 6 | OTRS | Fora de escopo — Spec 011 futura | --- ## Fluxo VM112 → Desk (implementado 2026-06-10) ```mermaid sequenceDiagram participant C as Cliente participant W as Wizard VM112 participant D as Desk VM122 C->>W: Valida domínio W->>D: domain.validated C->>W: Aplica DNS W->>D: dns.applied C->>W: E-mail + senha + Criar conta W->>D: onboarding.started (email, step=create_account) Note over D: Cria ticket + backfill etapas anteriores W->>W: zmprov create account W->>D: account.created W->>D: infra.synced / onboarding.completed Note over D: Notas no mesmo ticket ``` **Alteração VM112:** `onboarding.started` **removido** de `validate-domain`; **adicionado** em `POST /onboarding/account/create`. --- ## Estados `crm_track` (payload ticket) | Valor | Significado | Gatilho | |-------|-------------|---------| | `onboarding` | Cliente comprometeu-se (criar conta) | `onboarding.started` | | `onboarding_completed` | Funil concluído | `onboarding.completed` | | `lead` | Abandonado / stale — candidato CRM | Job Spec 012 (futuro) | | `lead_contacted` | Outreach iniciado | Chat Spec 012 | | `lead_converted` | Voltou e concluiu ou fechou venda | Manual / webhook | | `lead_lost` | Sem resposta após N tentativas | Manual / regra | --- ## Detecção de abandono ### Critérios (MVP) | Critério | Valor default | Configurável | |----------|---------------|--------------| | Tempo sem evento | **24h** | `ONBOARD_STALE_HOURS` | | Etapa máxima | < `completed` | — | | Ticket status | `open` ou `escalated` (não `assisting`) | — | | `crm_track` | `onboarding` (não já `lead`) | — | ### O que **não** é abandono - Sessão `completed` ou `failed` - Ticket em `assisting` (técnico activo) - Ticket `closed` / `resolved` manualmente ### Job proposto (VM122 worker) ``` A cada 15 min: 1. Listar sessões stale no funil (já calculado em _funnel_summary) 2. Para cada sessão com ticket_id e crm_track=onboarding: - PATCH ticket payload: crm_track=lead, lead_detected_at=now - Opcional: push ops_lead (Spec 007) - Enfileirar outreach (Spec 012 Fase B) ``` --- ## Outreach / Chat (Fase B — canal TBD) Roger vai estudar ferramenta para identificar e contactar o visitante: | Opção | Prós | Contras | |-------|------|---------| | Widget chat web (Crisp, Tawk, Chatwoot) | E-mail + sessão browser | Precisa embed no wizard | | Tablet SEO / dispositivo loja | Presencial | Escopo físico | | IP + WHOIS / enrichment | Automático | Baixa precisão, LGPD | | E-mail do ticket | Já temos `account_email` | Só após «criar conta» | **MVP Fase A:** ops contacta manualmente via e-mail/telefone do ticket. **MVP Fase B:** integrar canal escolhido + log em `lead_outreach_log`. --- ## Integração CRM ### Campos mínimos do Lead | Campo | Origem | |-------|--------| | `session_id` | VM112 cookie | | `domain` | Webhook | | `email` | `onboarding.started` / `account.created` | | `funnel_stage` | Última etapa conhecida | | `last_event_at` | Funil Desk | | `ticket_id` | Desk SQLite | | `desk_ticket_url` | `https://desk.ligbox.com.br/#ticket/{id}` | ### Destino CRM (TBD) - **Odoo CRM** (API key Roger já disponível no ambiente) - Ou export CSV / webhook genérico **Regra:** `ticket_id` é a chave de idempotência — não criar lead duplicado. --- ## API / Data model (VM122) ### Alterações em `tickets.payload` ```json { "crm_track": "onboarding", "funnel_notes": [ {"event": "domain.validated", "at": "...", "backfilled": true}, {"event": "dns.applied", "at": "...", "backfilled": true}, {"event": "account.created", "at": "...", "data": {"email": "..."}} ], "account_email": "admin@dominio.com", "onboarding_outcome": null, "lead_detected_at": null, "lead_outreach": [] } ``` ### Endpoints novos (propostos) | Método | Endpoint | Auth | Descrição | |--------|----------|------|-----------| | GET | `/api/v1/crm/leads` | JWT ops_lead+ | Lista tickets `crm_track=lead` | | POST | `/api/v1/crm/leads/{ticket_id}/contact` | JWT | Regista tentativa outreach | | POST | `/api/v1/crm/leads/{ticket_id}/promote` | JWT | Força lead manualmente | | POST | `/api/v1/crm/leads/sync` | internal token | Job stale → lead | --- ## User stories ### US-1 — Ticket no compromisso Como ops lead, quero um ticket quando o cliente clica «Criar conta», para ver a jornada mesmo sem pedido de suporte. **Critério:** `onboarding.started` com `step=create_account` → `ticket_created=true`, assunto `[onboarding] domínio — email`. ### US-2 — Etapas completas no ticket Como técnico, quero ver no ticket as etapas anteriores (domínio, DNS) e posteriores (conta, infra, concluído). **Critério:** `funnel_notes` contém ≥3 eventos após funil completo; backfill marca `backfilled: true`. ### US-3 — Abandono vira Lead Como ops lead, quero que sessões paradas 24h sem concluir apareçam como Leads para recuperação. **Critério:** job marca `crm_track=lead`; lista `/api/v1/crm/leads` retorna o ticket. ### US-4 — Outreach rastreável Como técnico, quero registar cada contacto ao lead (chat, e-mail, telefone) no ticket. **Critério:** `POST .../contact` append em `lead_outreach[]`. --- ## RBAC | Acção | super_admin | ops_lead | technician | noc | |-------|-------------|----------|------------|-----| | Ver leads | ✅ | ✅ | ✅ | ❌ | | Contactar lead | ✅ | ✅ | ✅ | ❌ | | Promover manual | ✅ | ✅ | ❌ | ❌ | | Sync CRM externo | ✅ | ✅ | ❌ | ❌ | --- ## Fases de entrega | Fase | Entrega | Estado | |------|---------|--------| | **A** | Ticket no `onboarding.started` (criar conta) + backfill + VM112 alinhado | ✅ 2026-06-10 | | **B** | Job stale → `crm_track=lead` + UI lista Leads no Desk | ✅ 2026-06-10 | | **C** | Outreach log + push ops_lead (007) | 📋 | | **D** | Sync Odoo CRM / canal chat escolhido | 📋 | --- ## Fora de escopo - Criar ticket só na validação de domínio (removido) - Múltiplos tickets por sessão - Chatbot com IA - Spec 011 OTRS --- ## Referências - `specs/010-desk-assist-takeover/spec.md` — assistência humana - `specs/007-mobile-push-notifications/spec.md` — alerta funil travado - VM112: `/opt/ibytera-mail-portal/backend/app/routers/onboarding.py` - VM122: `api/app/main.py` — `TICKET_EVENTS_BY_SOURCE`, `_backfill_funnel_notes`