12 KiB
Plan de Docker y migraciones de base de datos
Estado: implementación local disponible; adopción de producción pendiente de inventario y ensayo. Fecha: 17 de octubre de 2026.
Operación vigente: Base de datos local y migraciones. Este documento conserva la planificación y sus criterios de aceptación.
Objetivo y alcance
Levantar MariaDB local para desarrollo y tests, y evolucionar el esquema mediante
migraciones versionadas. La referencia facilitada para producción es
11.8.3-MariaDB-ubu2404.
El backend y el frontend seguirán ejecutándose en WSL con Node.js 24 y PNPM 11.25.0. Esta adaptación no requiere contenerizar toda la aplicación ni cambiar la base de producción. Su incorporación al historial se preparará y ensayará antes de ejecutarse en ese entorno.
Situación de partida
- Los E2E ya provisionan una MariaDB efímera con Compose, puerto dinámico, credenciales generadas y limpieza al finalizar.
- Los E2E preparan el esquema mediante
sequelize.sync(). - Los tests HTTP crean bases con nombres únicos sobre un servidor configurado
y fuerzan
DB_SYNC_MODE=alter; su cierre no elimina esas bases. - El runtime permite
none,alteryforce, sin restricción por entorno. - Los scripts SQL están repartidos entre
docsymodules/identity/sql; mezclan DDL, cambios de datos, seeds, diagnósticos y procedimientos históricos. - No existe un historial versionado de migraciones.
- El build del servidor tiene un único punto de entrada. Las migraciones deben formar parte del artefacto desplegable.
- El Dockerfile raíz declara PNPM 10.20.0, mientras
packageManagerexige 11.25.0. Habrá que alinear el build afectado sin modificarpackageManager.
Decisiones propuestas
- Usar la imagen oficial
mariadb:11.8.3, verificar el servidor resultante y registrar su digest para fijar el artefacto utilizado. - Centralizar la referencia de imagen utilizada en desarrollo, HTTP, E2E y CI.
- Usar Compose para el ciclo de vida de MariaDB. Reutilizar la infraestructura E2E existente donde encaje, sin crear un framework nuevo.
- Usar Umzug con Sequelize v6 para ejecutar migraciones TypeScript mediante un catálogo explícito y ordenado. No depender de descubrir archivos TS en producción.
- Ubicar el ejecutor y el catálogo en
modules/core/src/api/infrastructure/databasepara compartir contrato entre servidor y worker. La CLI reside enapps/server/src/infrastructure/database. No entran en Domain/Application. - Mantener migraciones aplicadas inmutables. Los cambios posteriores se harán mediante nuevas migraciones, sin importar modelos ORM que puedan evolucionar.
- Separar migraciones, datos de demostración y fixtures de tests. Los datos funcionales indispensables se clasificarán expresamente antes de incorporarlos.
- Ejecutar migraciones con una orden explícita, separada del arranque del backend. El backend comprobará compatibilidad sin modificar el esquema.
Fase 0. Inventario y contrato inicial
- Confirmar Docker/Compose disponibles desde WSL. Resolver la discrepancia entre
la ruta real del checkout y la indicada en
AGENTS.mdantes de modificar código. - Inventariar modelos registrados realmente por la composición del servidor, asociaciones, índices, restricciones y tablas de auditoría.
- Clasificar todos los SQL: vigente, histórico, seed, diagnóstico o limpieza. Registrar dependencias y precondiciones, sin ejecutarlos en lote.
- Comparar el esquema esperado con un inventario autorizado de desarrollo y, cuando se disponga de él, de producción. No asumir que coinciden con los modelos.
- Determinar
charset,collation,sql_mode, zona horaria y configuración relevante de producción. Mantener explícitamente cualquier diferencia necesaria. - Resolver diferencias detectadas entre SQL y modelos, por ejemplo
archived_aty la longitud deproforma_number, sin escoger un contrato arbitrariamente.
Salida: inventario y contrato de esquema revisables; lista de diferencias por entorno y clasificación de tablas legacy. No se eliminan datos ni tablas.
Fase 1. MariaDB de desarrollo
- Añadir un Compose local dedicado a la base de datos, independiente de los stacks de despliegue por empresa.
- Usar un volumen nombrado persistente y publicar el puerto solo en
127.0.0.1. - Incorporar
healthcheck.sh --connect --innodb_initializedy comprobación SQL antes de preparar el esquema. - Definir configuración de ejemplo sin secretos reales. Usar credenciales distintas para administrar/migrar y para ejecutar la aplicación.
- Añadir órdenes PNPM para levantar, detener y consultar logs. El reset de datos será una orden separada, explícita y limitada al proyecto local correspondiente.
- Documentar conexión desde WSL, persistencia y recuperación de un backup local.
Aceptación: detener y levantar conserva los datos; el reset solo afecta al volumen local previsto; la imagen y la versión SQL son las esperadas.
Fase 2. Ejecutor de migraciones
- Incorporar Umzug como dependencia del servidor y un punto de entrada CLI independiente, con configuración mínima de conexión y sin inicializar HTTP, módulos, warmups, certificados ni servicios externos.
- Definir identificadores ordenables, por ejemplo
202610170001-initial-schema, y un catálogo sin duplicados. - Persistir el historial de migraciones aplicadas y sus checksums. El historial permitirá distinguir pendientes, aplicadas y cambios indebidos de archivos. Usar el almacenamiento de Umzug como base y ampliar solo los datos necesarios.
- Detectar historiales incompatibles: migraciones desconocidas, huecos y checksums diferentes. Registrar inicio, resultado y fallos sin credenciales.
- Impedir ejecuciones concurrentes mediante bloqueo de MariaDB mantenido en una conexión dedicada durante toda la operación. Probar liberación y timeout.
- Registrar una migración como aplicada únicamente después de completarla. Los cambios con varios pasos tendrán precondiciones y recuperación documentada ante ejecución parcial; no se reintentará a ciegas tras un fallo.
- Incorporar órdenes propuestas
db:migrate,db:statusydb:verify.db:verifycomprobará historial y contrato de esquema;db:statusserá de lectura. - Compilar y empaquetar el ejecutor y todas las migraciones con el servidor;
comprobar su funcionamiento desde el artefacto final sin
tsxni fuentes TS.
MariaDB realiza commits implícitos en operaciones DDL. No se ofrecerá un rollback transaccional general ni una orden destructiva de reversión de producción. Se usarán transacciones para cambios de datos cuando proceda; para DDL, pasos recuperables, migraciones correctivas y restauración verificada cuando sea necesaria.
Aceptación: una base vacía se prepara; una segunda ejecución no cambia nada; un fallo no aparece como éxito; se detectan modificaciones del historial y se impiden dos ejecutores simultáneos.
Fase 3. Migración inicial y adopción de bases existentes
Bases nuevas
Crear una migración inicial explícita con el esquema activo completo, validado contra el inventario: identity, companies, catalogs, customers, suppliers, customer-invoices, recurring-proformas, onboarding, factuges y auditoría, según su registro real. No copiar automáticamente todos los modelos ni encadenar SQL legacy.
La migración inicial no incluirá empresas concretas, usuarios reales ni datos de demostración. Los seeds de desarrollo serán opcionales e idempotentes.
Bases existentes
- Obtener backup verificable y ensayar el procedimiento en una copia aislada.
- Ejecutar un diagnóstico de tablas, columnas, tipos, índices, restricciones y datos relevantes para los cambios pendientes.
- Preparar reconciliaciones explícitas para las diferencias demostradas. Conservar tablas legacy y datos ajenos al esquema activo.
- Permitir registrar la migración inicial como ya existente solo después de verificar el contrato. Rechazar bases incompatibles; no marcar todas las migraciones como aplicadas ni ejecutar el DDL inicial sobre ellas.
- Registrar la evidencia de adopción y ejecutar después las migraciones pendientes.
Aceptación: una instalación nueva y una base existente reconciliada alcanzan el mismo contrato activo. Los datos existentes y las tablas legacy se conservan.
Fase 4. Tests sobre migraciones reales
- Mantener el ciclo de vida Compose de los E2E y fijar la imagen de MariaDB.
- Sustituir
sequelize.sync()en la preparación E2E por el mismo ejecutor de migraciones. Mantener separados bootstrap y datos de escenario. - Añadir un launcher de integración HTTP que provisione MariaDB temporal con credenciales generadas. Mantener una base única por runtime cuando lo requiera el aislamiento actual y eliminar todas al terminar el contenedor.
- Sustituir
DB_SYNC_MODE=alterdel runtime HTTP por migraciones ynone. - Limitar creación/eliminación de bases a la instancia temporal aprovisionada.
No aceptar automáticamente servidores externos desde
.env.test. - Mantener los tests unitarios independientes de Docker cuando no necesiten BD.
- Añadir pruebas de instalación vacía, reejecución, fallo parcial recuperable, concurrencia, checksums y adopción de esquema compatible/incompatible.
- Probar actualizaciones desde versiones anteriores con datos representativos, incluyendo aislamiento por empresa, referencias, contadores e integridad fiscal.
Aceptación: HTTP y E2E pasan con el esquema creado por migraciones; dos ejecuciones concurrentes no comparten datos; éxito, fallo y cancelación limpian sus recursos.
Fase 5. Retirada de sincronización y despliegue
- Tras convertir los consumidores, retirar
alteryforcedel arranque normal y actualizar configuración, tests y ejemplos. Rechazar explícitamente esas opciones. - Hacer que el arranque falle con un diagnóstico claro si el historial no es compatible o quedan migraciones pendientes. No aplicar DDL automáticamente.
- Añadir a CI instalación vacía, actualización desde versión anterior, verificación del esquema y pruebas desde el artefacto compilado.
- Preparar el procedimiento de despliegue: backup, control de escrituras cuando proceda, ejecución única de migraciones, verificación y arranque de procesos.
- Separar privilegios del usuario migrador y de la aplicación. Revisar los permisos que requieran los warmups existentes antes de reducirlos.
- Documentar compatibilidad entre versiones de aplicación/esquema y recuperación. Ejecutar cambios destructivos solo tras auditoría y una migración posterior.
- Marcar los SQL antiguos como referencia histórica o procedimiento específico, enlazando la migración que los sustituye. Conservar los necesarios para auditoría.
Entregas y validación
Entregas incrementales propuestas:
- Inventario, contrato y Compose de desarrollo.
- Ejecutor, historial, migración inicial y artefacto compilado.
- Diagnóstico y adopción de bases existentes, ensayados en copias.
- Integración HTTP y E2E mediante Docker y migraciones.
- Retirada de sincronización, CI y procedimiento operativo.
No retirar la preparación anterior hasta que su sustitución funcione en la misma
entrega. Cada entrega tendrá sus comprobaciones dirigidas; al modificar contratos
compartidos se ejecutarán pnpm typecheck y pnpm lint globales, las suites
unitarias pertinentes, pnpm --filter @erp/factuges-server test, pnpm test:e2e
y pnpm --filter @erp/factuges-server build, según alcance. El ejecutor compilado
se verificará contra una MariaDB temporal. Se informarán fallos y comprobaciones
no ejecutadas; este documento no implica que hayan pasado.
Datos pendientes para cerrar la implementación
- Configuración efectiva de producción y esquema activo real.
- Disponibilidad de una copia anonimizada o fixtures equivalentes para ensayar adopción.
- Cómo se ejecutan actualmente los despliegues y qué CI se utiliza.
- Recursos Docker disponibles para ajustar el paralelismo de tests.
Estas comprobaciones no impiden preparar la infraestructura local y el ejecutor, pero sí condicionan el contrato final y la adopción de producción.