# Feature Specification: Migração E-mail Legado — Execução VM122 (019) **Criado:** 2026-06-16 **Solicitado por:** Roger **Status:** 📋 Aprovado para planeamento / implementação **Prioridade:** **P0** **Depende de:** Spec 013 (modelo completo), Spec 010 (tickets), Spec 018 (Serviços MOSP) **Wizard cliente:** permanece na **VM112** — **não** executa migração legada --- ## Resumo executivo | Onde | O quê | |------|--------| | **VM112** | Wizard onboarding — criar domínio/conta Carbonio, DNS **só após gate** | | **VM122** | **Orquestração OPS** — migrar e-mail do servidor **anterior/legado** → Carbonio VM112 | **Regra de ouro (Roger):** **Migrar → validar → aprovar gate → só depois virar DNS (MX).** O cliente **não** vê imapsync nem PST no wizard. O técnico sénior opera no **Desk VM122** (vista Email Migration + ticket). --- ## Porquê VM122 e não VM112? | Critério | VM112 (wizard) | VM122 (Desk) | |----------|----------------|--------------| | Público | Cliente final | Técnico OPS | | Duração | minutos | horas / dias | | Credenciais servidor antigo | ❌ nunca | ✅ vault encriptado | | Ferramentas pesadas (imapsync, PST) | ❌ | ✅ worker/host | | Auditoria / ticket | parcial | completa | | Gate antes DNS | consulta API | controla e aprova | --- ## Ferramentas GitHub (rápidas e seguras) | Ferramenta | Repositório | Uso | Maturidade | |------------|-------------|-----|------------| | **imapsync** | [imapsync/imapsync](https://github.com/imapsync/imapsync) | IMAP → IMAP (cPanel, Zimbra, O365, Gmail…) | ⭐ ~4k — **padrão indústria** | | **imap-upload** | [rgladwell/imap-upload](https://github.com/rgladwell/imap-upload) | mbox → IMAP (pós readpst) | Complemento PST | | **readpst** | `pst-utils` (Debian) | Extrair PST Outlook | Sistema | | **zmmailbox TGZ** | Carbonio nativo | Zimbra/Carbonio → Carbonio | Oficial Zextras | | **oauth2_imap** | imapsync.lamiral.info | O365 / Gmail moderno | Obrigatório se Basic Auth off | **Não recomendado MVP:** ferramentas comerciais fechadas, scripts aleatórios sem logs, migração manual sem gate. ### Boas práticas imapsync (oficial) 1. `--justlogin` + `--dry` + `--justfolders` **antes** do sync real 2. Credenciais em **ficheiro 600**, nunca na linha de comando 3. **Presync** (bulk) com MX ainda no servidor antigo 4. **Delta sync** agendado (6/6h) 5. **Sync final** na janela de cutover 6. `--maxbytespersecond` se origem limitar rate 7. O365: **OAuth2**, não password básica Fontes: [FAQ Migration Plan](https://imapsync.lamiral.info/FAQ.d/FAQ.Migration_Plan.txt), [FAQ Massive](https://github.com/imapsync/imapsync/blob/master/FAQ.d/FAQ.Massive.txt) --- ## Arquitectura VM122 ``` ┌─────────────────────────────────────────────────────────────┐ │ Desk VM122 (ligbox-ops-platform) │ │ UI: Email Migration │ API /api/v1/migration/* │ │ Worker + ferramentas │ Gate DNS → bloqueia wizard VM112 │ └────────────┬───────────────────────────────┬────────────────┘ │ imapsync / PST pipeline │ GET /migration/gate ▼ ▼ Servidor LEGADO (host1) VM112 Carbonio (host2) cPanel / Zimbra / O365 mail.{dominio} ``` ### Onde correm as ferramentas | Fase piloto | Host | |-------------|------| | **Agora** | VM122 host ou container worker (fora da API) | | **Produção volume** | VM123 dedicada `ligbox-migration` (Spec 013 infrastructure.md) | **Nunca** dentro do container API FastAPI (bloqueia event loop, sem ferramentas). --- ## Fluxo operacional (técnico sénior) ```mermaid sequenceDiagram participant T as Técnico Desk participant V122 as VM122 API/Worker participant LEG as Servidor legado participant V112 as Carbonio VM112 participant W as Wizard VM112 T->>V122: Criar job migração (domínio, mailboxes) T->>V122: Preflight (--justlogin) V122->>LEG: Teste IMAP origem V122->>V112: Teste IMAP destino T->>V122: Sync initial (MX ainda no legado) V122->>LEG: imapsync bulk V122->>V112: grava mensagens loop Delta T->>V122: Sync delta end T->>V122: Verify ≥99% T->>V122: Approve gate (ops_lead) W->>V122: GET /migration/gate?domain= V122-->>W: ready_for_dns T->>W: Cutover DNS (ou assist) T->>V122: Sync final T->>V122: Close job + relatório ticket ``` --- ## Integração com wizard VM112 | Momento | VM112 | VM122 | |---------|-------|-------| | Cliente cria conta | ✅ wizard | job `discovered` manual ou webhook | | Contas destino Carbonio | ✅ zmprov via wizard | preflight confirma | | Aplicar MX Cloudflare | ⚠️ **bloqueado** se gate ≠ `ready_for_dns` | gate API | | Override emergência | — | `super_admin` + motivo auditado | **Implementação gate (Fase B):** `GET /api/v1/migration/gate?domain=` — VM112 chama antes de `dns.applied` final. --- ## Fases e critérios (resumo Spec 013) | Fase | DNS virado? | Acção | |------|-------------|-------| | discovered | Não | Inventário mailboxes | | preflight | Não | Testes login + mapeamento pastas | | initial_sync | Não | imapsync bulk | | delta_sync | Não | incrementais | | cutover_ready | Não | verify ≥99%, aprovação ops_lead | | dns_cutover | **Sim** | MX → VM112 | | final_sync | Sim | última delta | | verified / closed | Sim | relatório ticket | --- ## Matriz de risco (Roger) | Risco | Nível | Impacto | Mitigação | |-------|-------|---------|-----------| | Virar MX antes da migração | 🔴 **Crítico** | Perda de e-mail novo + antigo separados | **Gate API** + procedimento OPS | | PST corrompido | 🟠 Alto | Gaps silenciosos | readpst + quarentena + verify | | O365 Basic Auth bloqueado | 🟠 Alto | Sync falha | OAuth2 (`oauth2_imap`) | | Duplicatas em re-sync | 🟡 Médio | Inbox duplicado | imapsync Message-Id; não misturar PST+imap mesma pasta | | Rate limit servidor origem | 🟡 Médio | IP banido | `--maxbytespersecond`, horários off-peak | | Mailbox gigante (50GB+) | 🟡 Médio | Timeout | sync por pasta; worker 24h retomável | | Credenciais em log | 🔴 Crítico | Compromisso contas | vault Fernet; passfile 600 | | Carga VM122 | 🟡 Médio | Desk lento | worker separado / VM123 futuro | | Cliente envia mail durante cutover | 🟡 Médio | Algumas msgs no legado | sync final + TTL MX baixo pré-cutover | **Nível global da etapa:** 🟠 **ALTO** — dados de produção irreversíveis se mal executado. **Com Spec 013 + gate + presync:** 🟡 **MÉDIO controlável** para técnico sénior com runbook. --- ## Plano de implementação (como vamos proceder) ### Fase A — Fundação (VM122, ~1 sprint) 1. Schema SQLite (`migration_jobs`, `mailboxes`, `runs`, `credentials`) — Spec 013 data-model 2. `install-migration-tools.sh` na VM122 (imapsync, pst-utils, imap-upload) 3. API CRUD jobs + preflight `--justlogin` 4. Worker `migration_runner.py` — 1 mailbox imapsync 5. UI Desk mínima: lista jobs + log ### Fase B — Gate DNS (~½ sprint) 6. `gate.py` — ratio 99%, estados blocked/warning/ready 7. `GET /migration/gate?domain=` para VM112 8. Integração ticket + notas por `migration_run` ### Fase C — PST + verify (~1 sprint) 9. Upload PST multipart 10. Pipeline readpst → imap-upload 11. Relatório verify + approve-gate ### Fase D — VM112 hook (~½ sprint) 12. VM112: antes DNS final, consultar gate 13. Override auditado super_admin ### Piloto obrigatório - **1 domínio teste** (não produção crítica) - Origem: cPanel ou Zimbra conhecido - Destino: Carbonio VM112 tenant teste - Só depois: cliente real com legado --- ## API (referência — Spec 013) | Método | Path | |--------|------| | POST | `/api/v1/migration/jobs` | | POST | `/api/v1/migration/jobs/{id}/preflight` | | POST | `/api/v1/migration/jobs/{id}/sync` | | GET | `/api/v1/migration/jobs/{id}/verify` | | GET | `/api/v1/migration/gate?domain=` | | POST | `/api/v1/migration/jobs/{id}/approve-gate` | --- ## Fora de escopo desta spec - Migração no wizard Hero VM112 - Calendário/contactos CardDAV (só e-mail) - VM123 provisionamento (até volume exigir) --- ## Documentos relacionados - `specs/013-email-server-migration/spec.md` — spec completa - `specs/013-email-server-migration/research.md` — ferramentas GitHub - `specs/013-email-server-migration/plan.md` — ficheiros código - `specs/013-email-server-migration/quickstart.md` — runbook técnico - `specs/013-email-server-migration/tasks.md` — checklist T001–T040 --- ## Critérios de aceite execução VM122 - [ ] imapsync instalado e `--justlogin` OK VM122 → legado + Carbonio - [ ] Job piloto cPanel/Zimbra → Carbonio sem perda Inbox/Sent - [ ] Gate bloqueia DNS com sync < 99% - [ ] Gate libera com aprovação ops_lead + relatório - [ ] Wizard VM112 respeita gate (ou override auditado) - [ ] Zero credenciais origem em logs Desk