Ir al contenido

Roadmap de desarrollo

El sistema Aquazaku no se construye de una sola vez. Se construye módulo por módulo, cada uno en su expresión mínima viable, con la arquitectura entre proyectos y el dominio ya cerrados antes de tocar el primer endpoint.

Esta página define qué se construye, en qué orden, y por qué en ese orden. El detalle de cómo se construye cada módulo vive en su propio cambio SDD (sdd/<módulo>/) y se linkea desde el catálogo.


El orden y la cadencia del roadmap se sostienen sobre cinco reglas. Las dos primeras son reglas de oro declaradas explícitamente; las demás son convenciones que ya están vigentes en el proyecto.

1. De menos a más — la fundación antes que el resto

Sección titulada «1. De menos a más — la fundación antes que el resto»

Cada módulo se construye en su expresión mínima viable antes de agregar complejidad. Si un módulo necesita identidad para funcionar, identidad se construye primero. Si necesita stock para vender, stock se construye antes que ventas.

Por qué: el módulo fundacional es el que menos-a-más dicta. En Aquazaku eso es Auth + RBAC: nada funciona sin saber quién opera y qué puede hacer. Referencia: memoria architecture/aquazaku-golden-rules.

2. Mobile-first como metodología de UI, no como plataforma

Sección titulada «2. Mobile-first como metodología de UI, no como plataforma»

Resuelto al implementar M0 (ver Decisiones abiertas): “mobile first” se interpreta como metodología de diseño UI — responsive, touch targets accesibles, sticky bottom CTAs — aplicada a TODA superficie. NO se interpreta como prioridad de plataforma: la prioridad sigue siendo web Admin + POS primero (decisión estrategia/mvp-scope-web-first).

Dejó de ser un supuesto construyéndolo: los hitos del MVP salieron todos por web, y la app del seller sigue diferida a M8.

Por qué: las dos lecturas son coherentes mientras no haya app móvil. La metodología mobile-first ya se aplica a la web responsiva del POS (mostrador) y del Admin (que se opera desde el celular cuando el dueño viaja).

3. Build incremental — no más iteración de diseño

Sección titulada «3. Build incremental — no más iteración de diseño»

El ciclo de iteración sobre los mockups de claude-design/ está cerrado. Lo que falta se corrige al construir, no en una nueva ronda de diseño.

Por qué: los mockups ya tienen fidelidad suficiente para servir de referencia visual. Seguir puliendo diseño es costo que no aporta valor. Las derivas conocidas (vencimiento 6m vs 30d, entrega vs retornables, personas placeholder) se resuelven en la implementación. Referencia: memoria architecture/aquazaku-build-strategy.

4. Orden fundación → operacionales → soporte

Sección titulada «4. Orden fundación → operacionales → soporte»
Fase Qué incluye Razón de ser
Fundación M0 (Auth + RBAC) Sin identidad no hay permisos, sin permisos no hay módulo que funcione.
Operacionales M1–M7 (Productos, Stock, Insumos, Producción, Clientes, Ventas, Retornables) Son los módulos que operan el negocio día a día. Cada uno depende del anterior.
Soporte y control M10, M9, M11, M12, M13 (Precios, Proveedores, Contador, Alertas, Auditoría) Son módulos que consumen lo que los operacionales ya registran, o que auditan lo que ya pasó. No son blockers de la operación.
Post-MVP M8 (Rutas y seller mobile) Mobile-first del seller + rutas con offline-first se difiere a post-MVP (decisión estrategia/mvp-scope-web-first).

5. Cada módulo pasa por el pipeline SDD completo

Sección titulada «5. Cada módulo pasa por el pipeline SDD completo»

Cada módulo atraviesa spec → design → tasks → apply → verify → archive antes de pasar al siguiente. No se arranca un módulo mientras el anterior esté a medias. Ver Pipeline SDD abajo.


/Users/mao/code/aquazaku/ ← repo "paraguas" (no versiona código)
├── docs/ ← Astro Starlight — este sitio (✅ activo)
├── api/ ← Backend y API HTTP/JSON (✅ en producción)
├── web/ ← Admin + POS responsivo (✅ en producción)
├── mobile/ ← App del seller (🔲 POST-MVP)
├── claude-design/ ← Mockups visuales (referencia, no docs)
└── README.md / .gitignore

Cada subproyecto (api/, web/, mobile/) vive en su propio repo git independiente y está ignorado por la raíz. La raíz solo contiene README y .gitignore para anclar el workspace y darle a engram un nombre de proyecto único.

Por qué polyrepo y no monorepo: preserva el repo aquazaku-docs que ya existía y evita que engram fragmente la memoria por repo. Las decisiones transversales (ej. sincronización, contrato API) viven en un solo silo. Referencia: memoria aquazaku/arquitectura/estrategia-repos.

Proyecto Rol Contrato hacia afuera Estado
docs/ Documentación técnica Sirve páginas estáticas (Astro Starlight). ✅ activo
api/ Backend Expone HTTP/JSON. Autentica, valida reglas, registra auditoría. ✅ api.aquazaku.com · api-ci verde en cada merge a main
web/ Admin + POS Server-rendered responsiva. Consume api/ solo desde el servidor. ✅ app.aquazaku.com · web-ci verde en cada merge a main
mobile/ App seller React Native o equivalente. Consume api/. 🔲 POST-MVP

Reglas de dependencia:

  • api/ no conoce web/ ni mobile/. Solo expone endpoints.
  • web/ y mobile/ solo hablan con api/. Nunca directo a la base.
  • docs/ no referencia código de api/ ni de web/ — describe reglas y decisiones, no implementaciones.

Las capas internas de cada proyecto (modelo de datos, controllers, componentes UI) se definen cuando arranca ese proyecto, no antes. Esta página describe el contrato entre proyectos, no las decisiones internas.


El sistema tiene cuatro roles canónicos — no tres. El contador se agregó en la sesión del 18-ago-2026 para temas tributarios en Colombia (DIAN) y es el único rol que no muta datos.

Rol Quién es Dónde opera Permisos
admin Dueño / administración Web (remoto, escritorio en planta cuando viaja) todo, sin restricciones
seller Vendedor — contacta clientes a distancia (llamada/WhatsApp) y registra ventas Web (mobile-first UI) en MVP; app móvil post-MVP Acotados a su alcance (propio, ruta)
pos Operario de planta + mostrador Web / terminal en la planta Acotados a planta + mostrador
contador Contador externo o interno Web, solo lectura Lectura + descarga de PDFs y CSV

Multi-rol: un usuario puede tener N roles asignados a la vez (ej. ["pos", "seller"]). Todo se audita bajo el mismo user_id. La UI muestra los módulos según los roles que el usuario tiene. Referencia: memoria dominio/acceso/roles-y-multi-rol.

Por qué existe contador aparte de admin: el dueño no debe ser quien se genera a sí mismo los reportes que va a presentar. La separación agrega un testigo externo al sistema.

La matriz completa celda por celda está en Roles y permisos.


El sistema se divide en 16 módulos numerados M0–M15 (M8 diferido a post-MVP). M14 y M15 no estaban en el plan original: salieron de ver el sistema en manos de quien lo usa. El número indica el orden de construcción sugerido, no prioridad de negocio: M0 es fundación porque todo lo demás lo necesita, no porque sea el más visible.

# Módulo Propósito (una línea) Roles que lo usan Depende de Estado
M0 Auth + RBAC Identidad, login, permisos por rol y alcance Todos — ✅ terminado
M1 Productos y catálogo Qué se vende: pacas 600ml/300ml, botellones con sus unidades y conversiones admin, pos, seller, contador M0 ✅ terminado
M2 Stock de producto terminado Lotes, vencimiento 30d, FIFO, bloqueo de vencidos admin, pos, seller, contador M0, M1 ✅ terminado
— Fase de diseño Sistema de diseño aplicado: marca real, vidrio y agua, semáforo de estados, vacíos, errores sin jerga, voz de usted, accesibilidad medida — M2 ✅ terminada
M3 Insumos Tapas, sellos, bolsas por kg con stock mínimo configurable (default 200/200) admin, pos M0 ✅ terminado
M4 Producción y cierre del día Cierre diario que mueve agua, stock e insumos en una transacción; balance de los dos tanques con reconciliación contra el nivel observado admin, pos, contador M0, M1, M2, M3 ✅ terminado
M5 Clientes Identidad con documento y dígito calculado, estado de verificación con responsable, tipo con lista de precios, direcciones como entidad y crédito que la base no deja habilitar sin verificar admin, pos, seller, contador M0 ✅ terminado
M6 Ventas Venta inmutable con precio congelado, anulación que revierte al mismo lote, cobros como documento aparte, devoluciones, descuentos con piso sostenido por la base, factura electrónica como intención admin, pos, seller, contador M0, M1, M2, M5 ✅ terminado
M7 Retornables (botellones y bases) Entrega con flujo híbrido, devoluciones, daño con tarifa fija, traza por id_sticker admin, pos, contador M0, M5 ✅ terminado
M8 Rutas y seller mobile App nativa del seller, offline-first, cierre de ruta seller, admin, contador M0, M5, M6, M7 ⏸ POST-MVP
M9 Proveedores y compras Mixto contado/transferencia/crédito, sin módulo de CxP completo admin, pos, contador M0, M3 ✅ terminado
M10 Precios y promociones Listas residencial/comercial con piso, códigos de descuento con piso absoluto admin, pos, seller, contador M0, M1 ✅ entregado en M1+M6
M11 Contador Panel solo lectura: extracto de los cinco movimientos de plata, cartera por edad, resumen mensual, CSV con columnas a elección, PDF por impresión del navegador contador, admin M0, M5, M6, M7, M9, M10 ✅ terminado
M12 Alertas Umbrales configurables en parametros, con sus límites en la base y cada cambio auditado con el valor anterior admin (configura), pos (ve los avisos) M0, M2, M3, M4 ✅ terminado
M13 Auditoría Quién hizo qué cuándo; transversal — todo módulo registra admin (consulta) M0 + transversal ✅ entregado en M0
M14 Clientes ubicables Dirección en nomenclatura colombiana, municipio del DANE, pin que pone la persona, y al menos un teléfono admin, pos, seller, contador M0, M5 ✅ terminado
M15 Seguimientos La lista de direcciones a las que hay que llamar, con su propio módulo; el tablero solo avisa cuántas hay admin, seller, pos, contador M0, M5 ✅ terminado
  1. M0 es fundación. Nada arranca antes que M0.
  2. M1, M2, M3 pueden ir en cualquier orden entre sí una vez M0 esté verificado. Son las “tablas maestras” del catálogo.
  3. M4 necesita M1+M2+M3. Producción registra producto, descuenta stock y consume insumos — los tres juntos.
  4. M5, M6, M7 se necesitan mutuamente en parte: M5 (clientes) habilita M6 (ventas) y M7 (retornables a un cliente). M7 puede arrancar con cliente opcional, pero la versión completa depende de M5.
  5. M10 va antes que M6 si se quiere validar precios antes de vender; o puede ir después de M6 si se arranca con precios hardcodeados y se flexibiliza después. Decisión de cadencia.
  6. M9, M11, M12, M13 son soporte — entran cuando los operacionales ya tienen datos reales para consumir/auditar.
  7. M8 queda explícitamente fuera del MVP. Se referencia acá para que no se olvide, pero no se implementa en esta fase.

Cada módulo tiene su documentación de dominio en /docs/dominio/ con las reglas de negocio (RN-*) ya acordadas. El roadmap no las repite — linkea.

Módulo Doc de dominio Reglas principales (referencia)
M1 Productos y catálogo RN-CAT-01 a 11 (catálogo cerrado, desactivar sin borrar, precio en el producto, piso absoluto, paca indivisible)
M2 Stock RN-STK-01 a 08 (ubicación, motivos, FIFO, devoluciones, descarte, lote y vencimiento 30d)
M3 Insumos ✅ documentado el 22-ago-2026. Mínimo 200/200 confirmado como valor inicial configurable (RN-INS-03); falta la equivalencia kg→unidades de bolsas (pregunta 37)
M4 Producción RN-PRD-02 a 24 (tanques separados, cierre diario, lote, encendido/apagado, etc.)
M5 Clientes RN-CLI-08 (documento único), RN-CLI-12 (crédito), RN-CLI-15 (verificación)
M6 Ventas RN-VEN-01 a 13 (inmutabilidad, anulación, precios, descuentos, factura)
M7 Botellones y bases RN-ENV-01+ y RN-BAS-01+ (entrega híbrida, daño con tarifa, id_sticker)
M9 Proveedores RN-PRO-01 a 07 (la compra le pone nombre al inventario que ya entra, crédito modelado sin ejercerse, aviso de vencidas)
M11 Contador RN-CON-01 a 09 (lee y no escribe, reportes reproducibles, el extracto cuadra o lo dice, cartera por edad, resumen mensual por meses enteros, columnas a elección salvo el monto, y el hueco de los gastos declarado)
M0 Roles y permisos RN-ACC-01 a 05 (multi-rol, UI oculta, alcance, auditoría, desactivación)

Reglas que aplican a todos los módulos, no a uno solo. El roadmap las recuerda; el detalle vive en los docs de dominio y en engram.

Convención Referencia
Reglas con ID RN-XXX-## — área + correlativo, estado explícito (✅ / 🟡 / 🔴) aquazaku/dominio/convencion-reglas
Mobile-first como metodología UI — touch targets ≥ 44px, sticky bottom CTAs, responsive de entrada architecture/aquazaku-golden-rules
Datos en bandas, no falsa precisión — “entre 3 y 5 días”, nunca “4,3” RN-PRD-15
Acción irreversible con motivo obligatorio — anulaciones, ajustes, descartes: texto ≥ 10 caracteres aquazaku/dominio/convencion-reglas + claude-design reglas-como-tests
El saldo calculado manda, la lectura visual reconcilia — patrón inventario contable vs conteo físico RN-PRD-14
Personas de los mockups son placeholder — al construir, el admin crea un perfil por cada rol canónico design/placeholder-personas
Multi-rol por usuario, un user_id único — la UI oculta módulos según el rol ejercido, la API prohíbe RN-ACC-01 a 03

Cada módulo recorre las seis fases de Spec-Driven Development antes de pasar al siguiente. No se pisan fases entre módulos distintos.

spec → ¿QUÉ se hace? (requerimientos + escenarios Given/When/Then)
design → ¿CÓMO se hace? (arquitectura interna, archivos, contratos, datos)
tasks → ¿CÓMO se parte? (lista de tareas implementables, agrupables)
apply → CONSTRUIR (código + tests, commits por unidades de revisión)
verify → PROBAR (ejecutar tests, simular escenarios, UAT conversacional)
archive → SINCRONIZAR (delta specs → spec canónico, cleanup)

Un módulo queda archivado solo cuando su verify pasa. El siguiente módulo puede arrancar en design mientras el anterior está en apply, pero no antes.


Al 11-oct-2026:

Fase Módulo
✅ Terminado M0 — Auth + RBAC · M1 — Productos · M2 — Stock · Fase de diseño (marca, vidrio, agua, estados, vacíos, voz de usted, accesibilidad) · M3 — Insumos · M4 — Producción · M5 — Clientes · M6 — Ventas · M7 — Retornables · M9 — Proveedores · M11 — Contador · M12 — Alertas · M15 — Seguimientos
Design en curso —
Apply en curso —

| Pendiente | — | | Diferido (post-MVP) | M8 — Rutas y seller mobile |

Los trece hitos del MVP están cerrados, M14 —lo que pidió la primera demo con el cliente— y M15 también.

No estaba en el roadmap: salió de ver el sistema en manos de quien lo va a usar. Dos huecos que ninguna revisión de código había mostrado.

La dirección era un campo de texto. Ahora se descompone en la nomenclatura colombiana —CL 45 A # 12 B - 34— con municipio, departamento y un pin opcional en el mapa.

Ningún campo de ubicación es obligatorio, y es una decisión: Aquazaku reparte en pueblos donde una dirección puede ser «Vereda La Peña, casa de tabla azul». Exigir la estructura haría que el operador invente CL 1 # 1-1 para poder guardar — perdiendo el dato y ensuciando la base.

Lo que sí exige la base es que el conjunto ubique: direcciones_ubicable pide al menos una de estructura, línea libre, indicaciones o coordenadas.

No había ningún dato de contacto. Se había construido la cartera por edad para saber a quién llamar primero, y no había a qué número llamar.

Municipio y departamento salen del catálogo oficial del DANE: 33 departamentos, 1122 municipios, con coordenadas. Se guardan en minúscula y se muestran con la ortografía correcta.

Hace falta un catálogo y no una transformación: «Campo de la Cruz» no se reconstruye desde campo de la cruz —un título automático daría «Campo De La Cruz»— porque las preposiciones en minúscula dependen de cuál palabra es.

Y sigue aceptando lo que el DANE no lista: las veredas.

Ningún servicio geocodifica CL 5 # 3-24, Campo de la Cruz con precisión. El mapa se centra en el municipio y la persona pone el pin: las coordenadas salen de alguien que sabe dónde está la casa. Una ruta calculada sobre una posición inventada es peor que ninguna — y esas coordenadas son la base de M8.


La lista de clientes a los que hay que llamar (RN-CLI-18) arrancó como una sección del tablero. Funcionaba — pero el peso de la tarjeta (días, teléfonos, etiqueta, botón de WhatsApp, dos franjas de urgencia) le ganaba al resto y el tablero dejaba de leerse como «qué hacer / cómo venimos»: se leía como «llamar a Yeimy».

La lista completa se mudó al módulo Seguimientos (/modulos/seguimientos), visible para los cuatro roles — todos tienen clientes:ver, que es lo que pide el endpoint. El tablero conserva solo el recordatorio: si hay N clientes a los que llamar, lo dice como un pendiente más, con la cantidad exacta y un link «Ir a Seguimientos →».

Pieza Estado
Endpoint /clientes/a-llamar intacto
Componente ClientesParaLlamar intacto, mismos tests
Permisos intactos (clientes:ver)
Render del tablero saqué la sección, sumé el pendiente
Catálogo de módulos entrada nueva seguimientos

Es el primer caso del patrón «sección pesada del tablero migra a módulo propio». El tablero sigue cumpliendo su rol de vistazo general del negocio; la vista dedicada es la lista completa.


M12 fue el último. Los avisos ya funcionaban —el de bases (RN-BAS-13), el de compras vencidas (RN-PRO-07), el de vencimiento próximo (RN-STK-11)—, pero con el umbral escrito en el código. Lo que cerró M12 es que ese número se mueve desde la administración.

Y las constantes se borraron, no quedaron como default. Un default en el código más una fila en la base son dos lugares donde configurar lo mismo, y el día que discrepen nadie sabría cuál manda.

Los límites de cada umbral viven en la base con un CHECK (ADR-0006): un umbral en cero apaga la alerta sin decirlo, y uno enorme la deja siempre encendida — las dos formas de romperla se ven igual desde afuera, porque en las dos nadie reacciona.

Cada cambio queda en la bitácora con el valor anterior. Un aviso que dejó de sonar tiene dos explicaciones —el problema desapareció, o alguien movió el número— y meses después no hay forma de distinguirlas sin eso.

Lo que sigue no es un hito: son M8 y la facturación electrónica, diferidos a propósito —están en la tabla de arriba—, y las preguntas abiertas con el contador.

M10 (Precios) también está entregado, absorbido por M1 y M6: listas residencial/comercial con piso, códigos de descuento y el piso sostenido por la base.

El resto del documento de dominio está cerrado: las reglas RN-* que ya están publicadas en /dominio/ cubren lo que el módulo necesita definir, no cómo lo implementa. El SDD de cada módulo traduce esas reglas en código.


No queda ninguna que frene la spec de un módulo. Los hitos del MVP están cerrados y M8 es la única pieza diferida, a propósito.

Lo que sigue abierto son las preguntas a Aquazaku —las mediciones 🟠 que hay que ir a tomar en la planta, las 🟢 del módulo de perfil y las 🔵 del contador—. Ninguna frena código en curso: los módulos que dependían de un número se entregaron con el número vacío y diciéndolo, en vez de estimarlo.

Pregunta Cómo quedó
Nombre del módulo de retornables: ¿entrega o retornables? retornables, en los dos repos. Se decidió construyéndolo, no discutiéndolo; entrega quedó como el nombre de los mockups de claude-design/
Pregunta Cómo quedó
Stock mínimo default de insumos 200 tapas / 200 sellos como valor inicial, configurable desde la administración (RN-INS-03)
Las bolsas se cuentan por kilo o por unidad Se compran por kilo y se guardan por unidad (RN-INS-02). La conversión es una medición de planta, no una constante (pregunta 37)
El cloro y los filtros entran como stock No — son gasto, no inventario (RN-INS-04)
Pregunta Cómo quedó
Umbral del aviso de vencimiento próximo 7 días como valor inicial, configurable desde la administración (RN-STK-11) — pregunta 36 cerrada
Pregunta Cómo quedó
Interpretación de “mobile-first” Metodología de UI. La app móvil del seller es post-MVP; se arranca por web y las pantallas se diseñan desde el ancho chico hacia arriba
Stack del proyecto api/ ADR-0001, y ya implementado: Node 22, Fastify 5, Drizzle, Postgres 17, Better-Auth 1.7. La ADR dice 16 porque eso se eligió en agosto de 2026; local migró a 17 el 16-sep-2026 para alinearse con producción y CI
Derivas heredadas del paquete claude-design/ M0 se construyó desde el dominio y los ADR, no desde los mockups. Las derivas documentadas en el verify del 19-ago-2026 no se replicaron en el código; siguen valiendo como advertencia para los módulos que sí usen esos diseños