# 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  
