ligbox-ops-platform/specs/025-wizard-onboarding-continuity/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

154 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Spec 025 — Onboarding contínuo (sem gaps)
**Criado:** 2026-06-17 · **Roger**
**Sistema:** Wizard VM112 + Desk VM122 + Traefik CT114 + Carbonio VM112
**Prioridade:** P0
**Relacionado:** Spec 012 (ticket/lead), Spec 017 (purge), Spec 022 (ACCOUNT_EXISTS ops)
---
## Problema
O wizard trata cada passo como linear e «virgem». Na prática o cliente (ou um técnico) pode:
- Abandonar no meio e voltar dias depois
- Ter conta já criada no Carbonio mas portal/Traefik/DNS incompletos
- Receber `ACCOUNT_EXISTS` no passo 3 e ficar **bloqueado** sem caminho
O Desk Spec 022 resolve o caso **para técnicos**; o cliente no wizard continua preso.
---
## Princípio — «Estado real, não passo cego»
Cada etapa consulta o **estado efectivo** no servidor antes de mostrar UI ou falhar:
| Camada | Fonte de verdade | Acção se já feito |
|--------|-------------------|-------------------|
| Domínio Carbonio | `domain_exists` | Avançar |
| DNS mail | `dns_verify` | Mostrar OK + continuar |
| Conta admin | `account_exists` + `domain_registry` | **Reconciliar** (não falhar) |
| Portal admin | `is_portal_admin` | Registar se em falta |
| Webmail gate | Traefik dynamic | `sync_webmail_gate` |
| Infra completa | `infrastructure.get_status` | Painel «pendente» com checklist |
**Regra de ouro:** `POST /account/create` é **idempotente** — conta existente → reconciliação + passos pós-criação, HTTP 200 com `reconciled: true`.
---
## Fluxo alvo (cliente)
```mermaid
flowchart LR
A[Domínio] --> B[DNS]
B --> C{Dados conta}
C -->|não existe| D[Confirmar + criar]
C -->|já existe| E[Continuar activação]
D --> F[Reconciliar pós-criação]
E --> F
F --> G{Infra OK?}
G -->|sim| H[Concluído — webmail]
G -->|não| I[Checklist infra + polling]
I --> H
```
### Passo 2 (UI)
- Consultar `GET /onboarding/account/status?domain=&local_part=`
- Se `exists: true` → banner **«Conta já existe — vamos concluir a activação»** (não «NÃO existe»)
- Botão: **«Continuar activação →»** em vez de só «Rever e criar»
### Passo 3 (UI)
- Se conta existe → **«Continuar activação»** (mesmo endpoint, reconcilia)
- Opcional: actualizar senha via `zmprov sp` se utilizador confirmou nova senha
### Erros que **não** bloqueiam
| Situação | Comportamento |
|----------|---------------|
| ACCOUNT_EXISTS | Reconciliar → 200 |
| DNS incompleto | Passo 4 com `finishPendingInfra` (já existe) |
| Traefik/LE pendente | Polling infra + guia no card Resumo |
| API lenta (>30s) | Timeout frontend 120s + mensagem clara (feito VM122) |
### Erros que **bloqueiam** (com saída clara)
| Situação | Comportamento |
|----------|---------------|
| Domínio inválido / blacklist | Mensagem + voltar passo 1 |
| Carbonio indisponível (OOM) | «Servidor ocupado — tente em 2 min» + webhook ops |
| Senha < 8 chars | Validação local |
---
## API VM112 (novo / alterado)
### `GET /onboarding/account/status`
```json
{
"email": "admin@exemplo.com",
"exists": true,
"portal_admin": true,
"domain_registered": true
}
```
### `POST /onboarding/account/create` (idempotente)
Resposta quando conta já existia:
```json
{
"email": "admin@exemplo.com",
"reconciled": true,
"account_verified": true,
"needs_review": false,
"infrastructure": { "ready": false, "steps": [...] }
}
```
Webhook: `account.reconciled` (novo) ou `account.created` com `reconciled: true`.
---
## Desk / Ops (sem duplicar Spec 022)
| Evento | Desk |
|--------|------|
| `account.reconciled` | Nota no ticket — «Cliente retomou conta existente» |
| `onboarding.failed` + ACCOUNT_EXISTS | Spec 022 — só se reconciliação **impossível** (conta órfã de outro email) |
| `onboarding.completed` + infra não ready | Ticket mantém `crm_track: infra_pending` |
---
## Fases de entrega
### Fase 1 — P0 (esta spec, 2026-06-17)
- [x] Spec documentada
- [ ] Backend: idempotência `create_account` + `GET account/status`
- [ ] Frontend: banners dinâmicos passos 23
- [ ] Deploy VM112 + smoke `exuberanti.com.br`
### Fase 2 — Resiliência
- [ ] Sessão wizard: ao reabrir URL, `resume` consulta estado e salta passos feitos
- [ ] VM112 RAM → 16 GB (Proxmox)
- [ ] Validação Traefik YAML (router sem `rule` = build fail)
### Fase 3 — Processo comercial completo
- [ ] Spec 012 abandonos → lead
- [ ] Spec 023 billing no Desk
- [ ] Wizard dedicado VM124 (Spec 018 fase 3)
---
## Critério de aceite (exuberanti.com.br)
1. Cliente com `teste001@exuberanti.com.br` já no Carbonio abre wizard no passo 2 → vê «conta já existe»
2. Clica «Continuar activação» → passo 4 sem erro 400
3. Portal admin registado; gate Traefik sincronizado
4. Ticket Desk recebe evento; Bloqueios Carbonio **não** aparece para este caso