# Feature Specification: Migração de E-mail entre Servidores (013) **Criado:** 2026-06-10 **Solicitado por:** Roger **Status:** 📋 **Draft — pronta para plano e implementação** **Prioridade:** **P0** (bloqueia cutover DNS seguro em migrações) **Depende de:** Spec 001 (webhooks), Spec 010 (assist/takeover), Spec 012 (ticket/lead) **Pesquisa:** [research.md](./research.md) **Plano técnico:** [plan.md](./plan.md) --- ## Resumo Módulo **Email Migration** no Ligbox Ops Platform para **iniciar, acompanhar e finalizar** migrações de e-mail entre servidores diferentes (origem heterogénea → **Carbonio Ligbox**), com suporte a: - **IMAP** (cPanel, Zimbra, O365, Gmail, outro Carbonio…) - **PST / OST** (Outlook) - **mbox / EML** - **TGZ** (export nativo Zimbra/Carbonio) **Regra de ouro (Roger):** a decisão de migração e a **validação técnica** devem estar **concluídas antes de virar o DNS** (MX/SPF/DKIM/DMARC). O cutover DNS é um **gate** controlado pelo Ops Desk — não um passo do wizard sem pré-requisito. --- ## Problema Hoje o funil VM112 aplica DNS e cria contas sem um módulo formal que: 1. Inventarie mailboxes e formatos de origem. 2. Execute sync incremental **enquanto o servidor antigo ainda recebe mail**. 3. Valide integridade (contagens, amostras, erros PST). 4. **Bloqueie** cutover DNS até `migration_gate = ready_for_dns`. 5. Registe tudo no ticket Desk para auditoria. Risco sem este módulo: perda de e-mail, duplicatas, PST corrompido importado silenciosamente, MX apontado cedo demais. --- ## Decisões de arquitectura (propostas — Roger valida) | # | Tema | Decisão proposta | |---|------|------------------| | 1 | Ordem operacional | **Migrar → validar → depois DNS** | | 2 | Motor IMAP | **imapsync** (primário) | | 3 | Motor PST | **readpst** + **imap-upload** (pipeline oficial) | | 4 | Motor Zimbra/Carbonio | **zmmailbox TGZ** (nativo) + imapsync fallback | | 5 | Orquestração | VM122 API + Worker (não no wizard cliente) | | 6 | UI | Vista **Email Migration** no Desk + painel no ticket | | 7 | Gate DNS | API `migration_gate` integrada ao fluxo `dns.applied` / assist | | 8 | Credenciais origem | Vault encriptado SQLite; nunca em logs | | 9 | Execução ferramentas | Worker em VM122 ou **jump host** com rede para origem+destino | --- ## Fases do ciclo de migração (antes e depois do DNS) ```mermaid stateDiagram-v2 [*] --> discovered: Inventário origem discovered --> preflight: Contas destino criadas preflight --> initial_sync: 1ª sync bulk initial_sync --> delta_sync: Syncs incrementais delta_sync --> cutover_ready: Gate técnico OK cutover_ready --> dns_cutover: MX/DNS alterado dns_cutover --> final_sync: Última delta final_sync --> verified: Contagens OK verified --> closed: Ticket fechado initial_sync --> failed: Erro crítico delta_sync --> failed failed --> delta_sync: Retry após fix ``` ### Fase 0 — `discovered` (antes de qualquer sync) - Domínio e lista de mailboxes (manual ou CSV). - Por mailbox: `source_type` (imap | pst | mbox | eml | tgz | zimbra). - Tamanho estimado, pastas, requisitos OAuth. - **Saída:** job de migração criado no Desk. ### Fase 1 — `preflight` - Conta destino existe no Carbonio (`zmprov` / wizard já criou). - Teste credencial origem (`imapsync --justlogin` ou `readpst -V`). - Teste IMAP destino. - Plano de mapeamento pastas (ex.: `Sent Items` → `Sent`). ### Fase 2 — `initial_sync` (AINDA SEM DNS) - Sync bulk enquanto MX ainda aponta para **origem**. - Mail novo continua a chegar ao servidor antigo. - Pode durar horas/dias conforme volume. ### Fase 3 — `delta_sync` (AINDA SEM DNS) - Syncs incrementais agendados (ex.: 6/6h ou manual). - Dashboard mostra: msgs origem vs destino, % completo, último erro. ### Fase 4 — `cutover_ready` — **GATE antes do DNS** Critérios mínimos (configuráveis): | Check | Threshold default | |-------|-------------------| | Contagem mensagens destino ≥ origem | ≥ 99% | | Pastas críticas (Inbox, Sent) | 100% | | Erros PST em quarentena | 0 críticos sem revisão | | Delta última sync | < 50 msgs pendentes | | Aprovação ops_lead | Manual (botão) | **Estado `migration_gate`:** `blocked` | `warning` | `ready_for_dns` ### Fase 5 — `dns_cutover` (só com gate OK) - Alterar MX/SPF/DKIM/DMARC (Cloudflare / pfSense). - Wizard VM112 só avança `dns.applied` final se gate = `ready_for_dns` **OU** flag `MIGRATION_GATE_OVERRIDE` (super_admin + motivo). ### Fase 6 — `final_sync` - Janela de manutenção: sync final imapsync / doveadm sync -1. - TTL MX baixo aplicado na fase 4. ### Fase 7 — `verified` → `closed` - Relatório PDF/JSON no ticket. - Cliente notificado. - Credenciais origem revogadas do vault. --- ## Tipos de origem e pipeline | source_type | Pipeline | Ferramenta | |-------------|----------|------------| | `imap` | Direct sync | imapsync | | `imap_oauth` | OAuth token + sync | imapsync + oauth2_imap | | `pst` | Extract → upload | readpst → imap-upload | | `mbox` | Upload | imap-upload | | `eml` | Bulk import | zmmailbox addMessage (lotes) | | `tgz` | Native | zmmailbox getRestURL / postRestURL | | `zimbra` | TGZ ou IMAP | zmmailbox + imapsync fallback | | `dovecot` | dsync | doveadm backup (se aplicável) | Detalhe ferramentas: [research.md](./research.md). --- ## Integração Ligbox Ops Desk ### Novo menu / vista - **Email Migration** (`view-email-migration`) - Lista jobs: domínio, tenant, fase, % sync, gate DNS - Acções: Iniciar sync, Ver log, Aprovar gate, Bloquear DNS ### Ligação ao ticket (Spec 010) - Ticket tipo `email_migration` ou tag em ticket onboarding existente. - Cada `migration_run` gera nota no ticket. - Assist/takeover: técnico vê credenciais mascaradas e logs. ### Webhooks (opcional Fase B) - `migration.started` / `migration.phase_changed` / `migration.gate_ready` - VM112 wizard consulta `GET /api/v1/migration/gate?domain=` antes de DNS final. --- ## API (contrato resumido) | Método | Rota | Descrição | |--------|------|-----------| | POST | `/api/v1/migration/jobs` | Criar job | | GET | `/api/v1/migration/jobs` | Listar | | GET | `/api/v1/migration/jobs/{id}` | Detalhe + mailboxes | | POST | `/api/v1/migration/jobs/{id}/preflight` | Correr preflight | | POST | `/api/v1/migration/jobs/{id}/sync` | Disparar sync (initial/delta/final) | | GET | `/api/v1/migration/jobs/{id}/runs` | Histórico execuções | | GET | `/api/v1/migration/jobs/{id}/verify` | Relatório verificação | | GET | `/api/v1/migration/gate?domain=` | Estado gate DNS | | POST | `/api/v1/migration/jobs/{id}/approve-gate` | ops_lead aprova cutover | | POST | `/api/v1/migration/jobs/{id}/upload-pst` | Upload PST (multipart) | Permissões: `can_manage_migration` — `super_admin`, `ops_lead`, `technician`. --- ## Requisitos não-funcionais | ID | Requisito | |----|-----------| | NFR-1 | Logs de imapsync/readpst guardados 90 dias | | NFR-2 | Credenciais origem AES-256 em SQLite | | NFR-3 | PST upload max 50 GB (configurável) | | NFR-4 | Worker timeout 24h por mailbox (retomável) | | NFR-5 | Rate limit IMAP para não bloquear origem | | NFR-6 | Relatório verificação obrigatório antes gate | --- ## User Stories ### US1 — Criar job de migração (P0) **Como** ops_lead **Quero** registar migração domínio X com lista de mailboxes e tipo de origem **Para** planear sync antes do DNS **Aceite:** job criado; ticket associado; fase `discovered`. ### US2 — Sync incremental IMAP (P0) **Como** técnico **Quero** correr imapsync agendado origem → Carbonio **Para** copiar mail sem duplicar e retomar após falha **Aceite:** log parseado; contagens actualizadas; sem duplicatas em re-run. ### US3 — Import PST (P0) **Como** técnico **Quero** enviar ficheiro .pst e ver progresso por pasta **Para** migrar Outlook sem erros silenciosos **Aceite:** pipeline readpst→imap-upload; erros em quarentena; relatório final. ### US4 — Gate DNS (P0) **Como** ops_lead **Quero** que o sistema bloqueie cutover DNS até validação OK **Para** nunca virar MX com migração incompleta **Aceite:** `migration_gate=blocked` impede DNS; `ready_for_dns` libera com auditoria. ### US5 — Verificação pós-sync (P1) **Como** noc **Quero** comparar contagens origem/destino por pasta **Para** detectar perda antes do go-live **Aceite:** relatório ≥99% ou lista de excepções justificadas. --- ## Fora de escopo (MVP) - Migração calendário/contactos CardDAV (só e-mail IMAP/PST) - Ferramentas comerciais (BitRecover, etc.) - Migração automática sem ticket humano - Execução imapsync **dentro** do container API (vai para worker host) --- ## Riscos | Risco | Mitigação | |-------|-----------| | PST corrupto | readpst validate; quarentena ERR_MBOX | | O365 bloqueia password | OAuth2 obrigatório | | imap-upload encoding | `--debug`; retry; charset normalização | | MX virado cedo | Gate API + override auditado | | Mailbox gigante | Chunk por pasta; `--maxsize` imapsync | --- ## Critérios de aceite global - [ ] Job percorre fases até `verified` em ambiente de teste (2 domínios) - [ ] PST de teste importado sem perda em Inbox/Sent - [ ] imapsync cPanel→Carbonio com re-run sem duplicatas - [ ] Gate bloqueia DNS quando contagem < 99% - [ ] Gate libera com aprovação + relatório - [ ] Logs e contagens visíveis no Desk - [ ] Documentação quickstart reproduzível por técnico --- ## Próximos documentos 1. [plan.md](./plan.md) — módulos, ficheiros, worker 2. [data-model.md](./data-model.md) — tabelas SQLite 3. [tasks.md](./tasks.md) — fases de implementação 4. [quickstart.md](./quickstart.md) — runbook técnico