# 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 | &lt; `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`
