ADR-0009 · Migración legacy → ambiente nuevo: cutover total con freeze + parity fixtures¶
- Status: Accepted (revisado 2026-05-13)
- Date: 2026-04-30 · Revisado: 2026-05-13
- Deciders: Cristian Fernández (Zerviz Group)
- Related: ADR-0006 (CI/CD parity gate),
docs/discovery/00-phase1-prerequisites.md5.1, 5.2, 5.3,docs/discovery/08-legacy-delta.md.
Revisión 2026-05-13 — Cuenta única + delta de inventario¶
- Cuenta AWS Fase 2: se reutiliza la cuenta existente
450972188274(no se creaze-devaún). Recursos nuevos llevan prefijozen-{env}-*y tagProject=zengine-v2. Promoción a cuenta dedicada se hace tras la primera versión revisada. - Legacy intacto: los recursos
ze-*y el códigoZengineDEVno se tocan. El "freeze" pasa a significar "no se modifica desde el monorepo nuevo"; el owner sí puede seguir evolucionando el legacy en paralelo. - Delta de inventario obligatorio: antes de iniciar build, se ejecuta el re-inventario del legacy (código + AWS) y se publica
docs/discovery/08-legacy-delta.md. Cualquier funcionalidad nueva detectada se evalúa como entrada al backlog de Fase 2 (no se copia código). - Cutover: se mantiene la estrategia de cutover total con parity gate. La diferencia: el switch DNS no es a otra cuenta, sino a los endpoints nuevos
zen-*dentro de la misma cuenta.
Context¶
Asentado: cutover total con freeze del legacy una vez completado el ambiente nuevo (no strangler fig). Parity tests basados en fixtures sintéticas + flujos IPLACEX (no grabación de tráfico real, ya que no hay tráfico real en dev y no hay prod del que grabar — checklist U-03). Todo puede evolucionar; el ambiente nuevo NO debe replicar 1:1 el legacy.
Decision¶
Estrategia¶
- Freeze del legacy declarado en el día 1 de Fase 2 (post-aprobación de Fase 1). PR-rule en GitHub bloquea cambios a
aws/step-1-read-api/ysrc/enZengineDEV. Excepción: hotfixes críticos de seguridad, autorizados por owner. - Construcción del ambiente nuevo en la cuenta existente
450972188274con prefijozen-{env}-*(ver Revisión 2026-05-13; promoción a cuenta dedicada en fase posterior), siguiendo ADRs 0001..0008. Greenfield total — no se reutiliza código del legacy salvo los 2 patrones identificados (ZE-D360-Sender,ZE-conexion). - Parity gate (workflow
parity-gate.yml): - Fixture set IPLACEX-demo: 50 escenarios end-to-end (inbound WhatsApp → flow → Five9 → outbound respuesta → encuesta).
- Cada fixture tiene
input(payload de webhook) yexpected_outputs(eventos publicados, mensajes outbound, estado final en flow-state). - Se ejecuta en
qacontra el ambiente nuevo. Falla = bloquea cutover. - Cutover manual en ventana de mantenimiento:
- Switch DNS / API GW custom domain del cliente: el legacy sigue en
*.zengine.online(sin tocar). El nuevo exponezen.zervizdev.com(frontal cliente) yzen-admin.zervizdev.com(admin interno), con subdominios por env (dev.*,qa.*). El cutover redirige cuando el owner lo decida; mientras tanto ambos coexisten en distintos dominios. - Webhooks Meta/360/Five9 reapuntados al ambiente nuevo.
- Confirmación con smoke test sintético (1 conversación end-to-end por canal).
- Rollback plan: DNS revierte al endpoint legacy. Ambiente legacy permanece intacto y monitoreado durante 90 días post-cutover; si pasa el período sin incidentes, se decommissiona vía PR de Terraform import + delete.
Lo que NO migramos¶
- Código legacy: descartado por completo. Sólo se rescatan 2 patrones (D360-Sender + adjuntos S3) como referencia para
packages/connector-sdk. chat-flow.jsonlegacy (4 versiones divergentes — R-15): se reconstruye desde cero con esquema multi-tenant + Zod enpackages/flow-schema.- DynamoDB
chat-widget-auth-sessions(605 items, sin TTL): no se migra. El tier lógico arranca conze-{env}-five9-sessionsvacío. - RDS
ze-db: no se migra data. Esquema nuevo desde cero; data productiva no existe (es dev). En Fase 2 se documenta el esquema nuevo endocs/data/postgres-schema.md. - S3
ze-enginelegacy: queda intacto bajo freeze. Bucket nuevoze-{env}-data/flows/arranca vacío. - CloudFront legacy: distribuciones huérfanas se documentan pero NO se tocan (regla base).
Lo que SÍ migramos¶
- Funcionalidad (no código): inbound WhatsApp/360, webchat, Five9 handoff, outbound campañas, encuestas NPS, builder admin de flows.
- Patrones de integración: documentados en
docs/discovery/03-code-aws-crosswalk.md §4.1.bis. - Catálogo de proveedores: Meta Cloud API, 360dialog, Five9, OpenAI (variables y modos de uso).
- Catálogo de plantillas WhatsApp: se reconstruye en
tenant-mgmtdesde el dashboard del builder.
Parity fixtures (estructura)¶
tests/parity/fixtures/iplacex-demo/
├── 01-whatsapp-inbound-greeting.json
├── 02-whatsapp-flow-decision-tree.json
├── 03-handoff-to-five9.json
├── 04-outbound-template-broadcast.json
├── 05-encuesta-nps-completion.json
├── ...
Cada fixture tiene:
- input: payload normalizado + tenant_id IPLACEX-demo + timestamp determinístico.
- expected_outputs.events: eventos esperados a EventBridge (orden, tenant_id, schema).
- expected_outputs.outbound: requests esperadas a externos (mockeados en CI).
- expected_outputs.state: estado esperado en DDB después.
Consequences¶
Positive¶
- Sin overhead de strangler fig (no shadow traffic, no parity-online).
- Greenfield permite refactor profundo (multi-tenant, RLS, KMS por tenant, etc.) sin restricciones del legacy.
- Rollback simple = DNS switch.
Negative¶
- Cutover en ventana = downtime breve (esperado < 15 min). Aceptable porque dev no tiene tráfico real.
- Si fixtures IPLACEX no cubren un caso real futuro, lo descubrimos post-cutover. Mitigación: fixture set crece durante Fase 2-5.
Alternatives considered¶
- Strangler fig: rechazado por el owner (5.1). Razón: legacy frozen, no vale la pena coexistencia.
- Cutover por canal: rechazado, implica mantener ambos ambientes activos en simultáneo.
- Parity con tráfico real grabado: rechazado (no hay tráfico real).
Tenant-isolation impact¶
- Fixtures incluyen
iplacex-demoyzerviz-internal. Tests aseguran cero leak entre fixtures.
Blast radius¶
- Cutover fallido = rollback DNS. RPO 0 / RTO < 30 min.
Cost note¶
- Sin costo extra (fixtures viven en CI).
- Mantener legacy 90 días post-cutover: ~ USD 50/mes (sin tráfico).
ISO 27001 controls touched¶
- A.12.5.1 (instalación de software en sistemas operativos): cutover documentado.
- A.14.2.9 (testing de aceptación): parity gate.
- A.17.1.2 (implementación de continuidad): rollback plan.
Sources¶
docs/discovery/00-phase1-prerequisites.md5.1, 5.2, 5.3.docs/discovery/03-code-aws-crosswalk.md §4.1.bis(patrones rescatables).- ADR-0006 (CI/CD parity gate).