Saltar a contenido

27 de junio de 2026

Día corto pero ordenador: junté en un solo lugar todo lo que venía dejando "para más adelante", disperso entre el PRD, el RFC y la bitácora.

Un tablero único de pendientes

Revisando el trabajo de los últimos días me di cuenta de algo incómodo: las cosas que iba dejando para resolver después estaban registradas —eso sí, fiel a la costumbre de anotar todo—, pero repartidas en cuatro lugares distintos. La aprobación manual del despliegue que pide plan pago estaba en la entrada de integración continua; el ejecutor on-premise que todavía no existe, también ahí; el origen del remito de ingreso a confirmar con el cliente vivía en el PRD; y el cache de sesión que asume un solo backend estaba metido en la prosa del RFC. Cada cosa en su contexto, sí, pero ninguna vista que me dijera de un saque "esto es lo que falta".

Así que armé esa vista. Una página nueva, pendientes.md, que funciona como tablero: cada ítem con su casilla para tachar, agrupado por tema —despliegue e infraestructura, integración con QUICK POS, decisiones de negocio por confirmar, deuda técnica y escala—. No me conformé con listar títulos: a cada pendiente le puse tres cosas, qué es, por qué quedó para después y, sobre todo, qué lo destraba, que es el dato que de verdad importa cuando uno vuelve a mirar la lista semanas más tarde y no se acuerda por qué algo seguía abierto.

Me importa aclarar que esta página no reemplaza el registro original. Los pendientes siguen naciendo donde corresponde —el día que aparecen, en la bitácora; las limitaciones asumidas, en el RFC; lo que queda fuera de alcance, en el PRD—. El tablero solo los reúne. Pensado como documento vivo: cuando algo se resuelve lo marco con la fecha, y si deja de tener sentido lo saco y lo cuento acá.

La enganché al hub como una sección más, entre el plan y la bitácora, y le dejé su tarjeta en la portada. Verifiqué que el sitio siga construyendo en modo estricto —sin enlaces rotos ni páginas sueltas— antes de dar la tarea por cerrada, que para eso me impuse esa verificación.

Afinando el filtro de la integración continua

Al subir este mismo tablero me topé con una inconsistencia que el propio ejercicio dejó a la vista. Tiempo atrás había hecho que la rutina de integración del código ignore los cambios que tocan solo la carpeta de documentación, para no gastar corridas de calidad y build en cosas que no son código. Pero el archivo de configuración del hub y sus dependencias viven en la raíz del repositorio, no adentro de esa carpeta, así que un cambio que solo movía la navegación del sitio seguía disparando la rutina del código igual —una corrida entera para revisar un código que ni se había tocado—.

Lo corregí extendiendo el filtro: ahora la rutina del código también ignora la configuración del hub, sus dependencias, el archivo que fija la versión de Python y el propio flujo de documentación. Todo eso es herramienta de la documentación y ya tiene su propia rutina, la que arma el sitio en modo estricto, que lo vigila aparte. Cada flujo se ocupa de lo suyo y los minutos de ejecución quedan para cuando de verdad cambia el código. Es un retoque chico, pero va en la misma línea que el filtro original: que la automatización no trabaje al pedo.

El modelo de datos toma forma: Prisma, tiendas y usuarios (Task 2)

Hoy escribí la segunda tarea del milestone, la que pone los cimientos de datos sobre los que se va a apoyar todo lo demás: el esquema con Prisma y las dos primeras tablas, tiendas y usuarios. Son las que necesita el Milestone 1 —administración y acceso—; el resto del modelo del RFC entra después, cada milestone con su propia migración, para no traer de golpe tablas que todavía no uso.

Apenas arranqué me llevé una sorpresa que me obligó a frenar y decidir. Instalé Prisma y resultó que la versión nueva, la 7, cambió de raíz cómo se configura: la dirección de la base de datos ya no va en el esquema, y el cliente ahora se conecta a través de un "adaptador" de driver en vez de hacerlo por su cuenta. No es un detalle menor —cambia qué dependencias uso y agrega un archivo de configuración aparte—, así que en lugar de asumirlo lo puse sobre la mesa: o me quedaba en la versión 6, más simple y la que el plan daba por sentada, o adoptaba la 7 con su esquema nuevo. Elegí la 7, la última, y la dejé andando con el adaptador de Postgres. Vale tenerlo anotado porque es de esas decisiones de stack que después hay que poder explicar.

Una cosa en la que me puse firme: los CHECK del modelo. El RFC dice, y con razón, que los constraints son parte del contrato y no decoración —que el puerto del QUICK POS esté en rango, que el correo sea del dominio de la empresa, que el rol sea uno de los dos válidos—. Prisma no expresa esas reglas en su esquema, así que en vez de dejarlas libradas a la confianza del código las grabé a mano en el SQL de la migración. Quedan en la base: aunque alguien algún día inserte un registro por fuera de la aplicación, la base lo rechaza. Lo verifiqué consultando los constraints directamente sobre Postgres, no me quedé con que "debería estar".

El cliente de Prisma lo armé como una instancia única para toda la app, con una precaución para desarrollo: como Next recarga los módulos en caliente cada vez que guardo, sin cuidado se crearía una conexión nueva en cada recarga hasta agotar la base. Guardándolo en una variable global eso se evita. Y aunque es código de cableado más que de lógica, le escribí su prueba igual —primero el test—, cubriendo las dos ramas: cuándo crea el cliente y cuándo reutiliza el que ya hay, en desarrollo y en producción. Quedó con la cobertura completa.

Cerré pasando toda la batería antes de dar nada por bueno: la migración aplica limpia contra la base de desarrollo, el esquema valida, los tipos compilan, el linter no chista, las pruebas pasan con cobertura total y el build de producción sale entero. De paso, corriendo el linter en mi máquina apareció un ruido que no tenía que ver con esta tarea: revisaba archivos de adentro del entorno de Python del hub de documentación, un montón de código ajeno y minificado. Le indiqué que ignore esa carpeta y la del sitio construido, igual que ya ignora las demás. En la nube nunca había molestado —ahí el entorno ni existe—, pero en local ensuciaba el resultado, y prefiero que correr el linter sea igual de limpio en los dos lados.