La ciudad ya puede sobrevivir
La última iteración del primer MVP de Racoonity no añadió nuevas funciones: se dedicó a demostrar que todo lo construido puede instalarse, operar, reiniciarse, respaldarse y recuperarse de forma verificable.
La ciudad ya puede sobrevivir
Durante varias iteraciones, Racoonity fue aprendiendo a hacer cosas.
Aprendió a arrancar, a autenticar usuarios, a manejar catálogo e inventario, a conocer clientes, a abrir cajas, a vender, a supervisar lo que ocurrió, a extenderse con metadata dinámica y, finalmente, a reaccionar a eventos sin acoplar todo con todo.
La I9 fue diferente.
Esta vez no queríamos enseñarle un truco nuevo al mapache.
Queríamos comprobar que todo lo anterior realmente se sostiene cuando lo tratamos como un sistema completo.
La iteración se llamó harden-mvp-release, y su objetivo fue bastante menos vistoso que agregar una nueva pantalla o una nueva capacidad:
instalar desde cero, recorrer el MVP completo, reiniciar, respaldar, restaurar y demostrar que el estado sigue ahí.
En otras palabras, dejar de preguntarnos únicamente si las piezas funcionan y empezar a preguntar si Racoonity puede sobrevivir a la vida real.
Empezar desde absolutamente nada
Una de las primeras pruebas de la I9 parte de una base PostgreSQL completamente vacía.
Sin tablas de Racoonity.
Sin datos precargados.
Sin scripts misteriosos ejecutados a mano.
Desde ahí se aplican las migraciones del proyecto, se construye el runtime y se verifica que la API quede lista para recibir la configuración inicial.
El punto importante no era solamente que “arrancara”.
Era demostrar que alguien pudiera llegar con una instalación limpia y obtener un sistema válido siguiendo únicamente el camino documentado.
Eso también significó comprobar la cara opuesta del contrato: la API no intenta arreglar una base sin migrar por su cuenta.
Si la base no está preparada, el arranque falla de manera explícita.
Sin magia.
Sin cambios silenciosos.
El viaje dorado
Después vino la prueba más grande que hemos construido hasta ahora: JRN-MVP-GOLDEN.
La idea fue recorrer en una sola historia prácticamente todo lo que el primer MVP aprendió entre I0 e I8.
La historia comienza con una instalación fresca.
Se crea la empresa y el administrador.
El administrador inicia sesión.
Se crea una ubicación de almacén, una categoría y un producto.
Entran diez unidades al inventario.
Cinco se transfieren al piso de venta.
Se crea un cliente.
Se abre una sesión de caja.
Se confirma una venta de dos unidades.
El inventario queda como esperamos.
El evento sale.confirmed entra al outbox.
Courier lo procesa.
Un Observer deja evidencia de que lo recibió.
Después la sesión se cierra y la venta se cancela.
El movimiento de inventario se revierte y las existencias vuelven a su estado anterior.
Hasta aquí ya estábamos recorriendo buena parte del corazón operativo de Racoonity.
Pero faltaba demostrar una de las apuestas más importantes del proyecto.
El monstruo también tenía que sobrevivir
En la I7 introdujimos la primera versión de Racoon Artifier y los modelos dinámicos.
Así que el golden path también crea un campo personalizado para productos:
golden_warranty = 24
Luego crea un modelo completamente nuevo:
repairs
y dentro de él un registro:
First Repair
Todo usando los mismos contratos públicos del sistema.
Nada de insertar filas manualmente para que la demo se vea bonita.
Después Atlas resuelve nuevamente las definiciones y confirma que la metadata recién creada forma parte de la experiencia disponible.
Es una prueba pequeña en apariencia, pero importante para la dirección de Racoonity: el sistema no solo conserva datos comerciales tradicionales, también conserva aquello que el usuario construye encima del sistema.
Apagar todo y volver a levantarlo
Hasta aquí todavía quedaba una trampa posible.
Muchos sistemas funcionan maravillosamente mientras el proceso que creó todo sigue vivo.
¿Pero qué ocurre cuando lo apagamos?
La I9 destruye el runtime original y construye uno nuevo contra la misma base de datos.
Pool nuevo.
Courier nuevo.
Caches nuevas.
Componentes en memoria nuevos.
Y entonces vuelve a preguntar.
¿La instalación sigue completada?
Sí.
¿El usuario puede volver a iniciar sesión?
Sí.
¿La venta sigue cancelada?
Sí.
¿El inventario conserva los balances correctos?
Sí.
¿El registro dinámico First Repair sigue ahí?
Sí.
¿Atlas puede reconstruir el campo golden_warranty leyendo PostgreSQL, sin depender de una cache vieja?
También.
Incluso el evento previamente publicado sigue publicado, y Courier no intenta reclamarlo nuevamente como si acabara de aparecer.
Ese reinicio fue una de las pruebas que más quería ver funcionando desde que empezamos a dividir Racoonity en engines.
Porque significa que el estado importante vive donde debe vivir.
No dentro de la memoria accidental de un proceso.
Y luego lo respaldamos de verdad
Hablar de backups es muy fácil.
También es fácil escribir una sección en un README diciendo algo como:
use
pg_dumppara respaldar su base de datos.
La I9 decidió ser un poco más molesta.
El gate de backup crea una base dedicada, construye en ella un estado representativo del MVP, apaga el runtime y ejecuta un pg_dump real usando las herramientas estándar de PostgreSQL.
Después crea una segunda base completamente vacía y ejecuta pg_restore.
Sobre esa base restaurada se construye otro runtime desde cero.
Y entonces volvemos a preguntar:
- ¿la instalación sigue completada?
- ¿el administrador todavía puede autenticarse?
- ¿la venta sigue cancelada con el mismo total?
- ¿el registro dinámico sigue existiendo?
- ¿los balances siguen siendo 5 y 5?
- ¿la evidencia del Observer sigue ahí?
- ¿el outbox conserva su estado publicado?
La respuesta fue sí.
Al terminar, las bases temporales y el archivo de respaldo se eliminan y el test verifica que no dejó basura detrás.
Por primera vez en el proyecto, el backup no es una promesa de documentación.
Es una operación que forma parte del cierre verificable.
Cero funciones nuevas
Quizá la parte más curiosa de I9 es esta:
no añadió una sola capacidad de negocio nueva.
El delta público terminó así:
- 0 Actions nuevas
- 0 Queries nuevas
- 0 Events nuevos
- 0 PublicErrors nuevos
- 0 capabilities nuevas
- 0 migraciones nuevas
- 0 cambios de código de producción
Todo el trabajo de la iteración terminó concentrado en pruebas, documentación operativa y evidencia reproducible.
Y creo que esa era exactamente la señal que buscábamos.
Llegó un punto en el que la mejor forma de avanzar no era construir más.
Era obligar a lo ya construido a demostrar que podía sostenerse.
El examen final
El cierre técnico terminó con varias capas de comprobación.
El suite completo quedó verde en 49 paquetes.
Los 55 tests de arquitectura pasaron.
Se ejecutaron pruebas de carrera sobre Courier, Observer y composición sin detectar data races.
La matriz de escenarios negativos también quedó verde: configuración inválida, PostgreSQL inaccesible, base sin migraciones, idempotencia, permisos, degradación de readiness y reconstrucción de Courier.
El backup y restore real pasó.
Y las especificaciones completas de OpenSpec volvieron a validarse en modo estricto.
Todo eso quedó registrado en un documento de evidencia que no intenta ser un enorme log de consola, sino un índice reproducible: qué se probó, con qué comando y qué propiedad demuestra.
Lo que significa terminar un primer MVP
Cuando empecé Racoonity, “primer MVP” sonaba como una lista de funciones.
Productos.
Inventario.
Clientes.
Ventas.
Caja.
Después empezaron a aparecer cosas como Artifier, Atlas, Courier, Foreman y todo el resto de mapaches que fueron convirtiendo esa lista en una arquitectura.
La I9 terminó cambiando mi definición de MVP una vez más.
Un MVP no está listo solamente porque puede hacer algo.
También necesita poder explicar cómo arrancar.
Necesita fallar de manera comprensible.
Necesita conservar su estado.
Necesita sobrevivir un reinicio.
Necesita poder respaldarse y recuperarse.
Y, sobre todo, necesita que podamos demostrar esas cosas sin depender de “confía en mí, ayer funcionaba”.
La ciudad todavía es pequeña.
Todavía faltan interfaces, experiencias mucho más ricas y varias ideas bastante más ambiciosas para el futuro.
Pero debajo de todo eso ya existe algo que hace unos meses solo era un montón de documentos y nombres raros para componentes internos.
Una base.
Una ciudad que puede funcionar, detenerse, levantarse otra vez y recordar lo que ocurrió.
Y para un primer MVP, eso me parece un buen lugar donde poner el punto final.
Simple por defecto, monstruoso por elección.
🦝