10 KiB
Feature Specification: Migração de E-mail entre Servidores (013)
Criado: 2026-06-10
Solicitado por: Roger
Status: 📋 Draft — Spec 019 execução VM122 (2026-06-16)
Execução OPS: Ver specs/019-email-migration-vm122-execution/spec.md — migração legado só VM122, wizard VM112 só após gate DNS.
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
Plano técnico: 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:
- Inventarie mailboxes e formatos de origem.
- Execute sync incremental enquanto o servidor antigo ainda recebe mail.
- Valide integridade (contagens, amostras, erros PST).
- Bloqueie cutover DNS até
migration_gate = ready_for_dns. - 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 (piloto) ou VM123 dedicada (produção — ver infrastructure.md) |
| 10 | VM / recursos | Decisão futura — documentado em infrastructure.md; não provisionar hoje |
Fases do ciclo de migração (antes e depois do DNS)
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 --justloginoureadpst -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.appliedfinal se gate =ready_for_dnsOU flagMIGRATION_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.
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_migrationou tag em ticket onboarding existente. - Cada
migration_rungera 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 / hoje)
- 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)
- Provisionar VM123 ou volume extra na VM122 — ver infrastructure.md (futuro)
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é
verifiedem 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
- plan.md — módulos, ficheiros, worker
- data-model.md — tabelas SQLite
- tasks.md — fases de implementação
- quickstart.md — runbook técnico
- infrastructure.md — VM/recursos (futuro — não hoje)