# 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 2–3 - [ ] 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