243 lines
9.1 KiB
Markdown
243 lines
9.1 KiB
Markdown
# 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
|