MiSodería
04En desarrollo120h invertidas

MiSodería

SaaS multi-tenant para distribuidoras de agua y soda — producto propio nacido de Celestina, ya con marca, diseño premium y testing real.

ReactViteSupabasePostgreSQLTailwindVitest
OneSignal
Problema

Celestina resolvía la logística de un solo cliente. Escalar el negocio a una segunda o tercera distribuidora con ese mismo código significaba clonar el proyecto y levantar un deploy y una base de Supabase nuevos por cada una — sin aislamiento real entre clientes y con cada bug o feature multiplicado por N instancias a mantener. Y como producto sin marca ni diseño propio, tampoco había nada presentable para mostrarle a un cliente nuevo.

Solución

Fork de Celestina reescrito como SaaS multi-tenant real —una sola base de datos y un solo deploy sirven a todas las distribuidoras, aisladas entre sí por Row Level Security— y relanzado como producto con nombre propio: MiSodería. Tenancy y rol viajan firmados en el token de sesión vía un Custom Access Token Hook, con un motor de facturación server-side (pg_cron) y un panel de operador de plataforma sin acceso directo a datos de tenants. Sobre esa base, un rediseño visual premium completo y una suite de tests automatizados sobre la lógica de negocio más sensible: la plata.

Resultado

Producto multi-tenant funcional y ya rebrandeado como MiSodería, con logo y sistema de diseño propio. Rediseño premium completo —inspirado en Linear/Stripe, con tema claro/oscuro real— sobre las cuatro superficies del producto: panel admin, vista del repartidor, panel de plataforma y versión mobile (11 pantallas). Un mismo repartidor puede tener ruta, caja e historial separados dentro de la misma empresa multi-tenant. Los flujos de contraseña se endurecieron: cambio obligatorio en el primer login tras un alta o un reset, y el admin de cada distribuidora puede resetear la contraseña de sus propios repartidores sin pedirme ayuda. La facturación granula cada cobro en abono, adicional y extras, y el catálogo de productos ahora se puede vender en cualquier entrega, no solo en Venta Directa. Y lo más importante para un sistema que maneja plata de terceros: se sumó una suite de tests con Vitest que cubre el motor de facturación (facturar_cliente, sincronizar_mensualidades, absorción de crédito), aislamiento entre tenants por RLS e idempotencia del cron — cada caso de test cita la regla de negocio que protege, para saber qué se rompió si alguna vez falla.

MiSodería
MiSodería
Arquitectura

Fork de Celestina reescrito para multi-tenancy real: misma base de código de producto, pero con aislamiento de datos por empresa, roles inyectados server-side, un sistema de diseño propio (MiSodería) y una suite de tests automatizados sobre la lógica de negocio crítica.

TenancyCustom Access Token Hook inyecta empresa_id y rol en el JWT al login — RLS los lee directo del token, no de una tabla que el cliente pueda falsear.
RLSCada tabla de negocio filtra por empresa_id = empresa_actual() con USING y WITH CHECK — una empresa no puede leer ni escribir filas de otra.
Funciones SECURITY DEFINERLas funciones de negocio que reciben un id como parámetro (ej. facturación) verifican explícitamente que ese id sea de la empresa de quien llama, porque dentro de una SECURITY DEFINER RLS no se aplica solo.
Facturaciónpg_cron dispara facturacion_diaria() una vez por día, recorre todas las empresas activas y genera la deuda de los clientes con abono mensual.
Panel de plataformaEl operador no lee tablas de negocio directo — todo pasa por una Edge Function que valida sus permisos contra plataforma_admins.
DiseñoSistema visual propio (MiSodería): monocromo con un único acento, tema claro/oscuro funcional, rediseñado en admin, mobile, vista repartidor y panel de plataforma.
TestingVitest sobre el motor de facturación, absorción de crédito, aislamiento RLS entre tenants e idempotencia del cron diario — cada test cita la regla de negocio documentada que protege.
Decisiones técnicas

¿Clonar el código por cada cliente nuevo o construir multi-tenancy real?

elegido

Una sola base de datos y un solo deploy para todas las empresas, aisladas por RLS

descartado

Seguir el patrón de Celestina: un proyecto de Supabase y un deploy por cliente

↳ Clonar no escala: cada bug hay que arreglarlo N veces, cada feature hay que desplegarla N veces. Multi-tenant real significa un solo lugar donde mantener el producto.

¿Dónde inyectar el rol y la empresa del usuario?

elegido

Custom Access Token Hook — quedan firmados en el JWT

descartado

Leerlos de una tabla o de localStorage en cada request

↳ Si el rol se lee de un lugar que el cliente controla, se puede falsificar. Firmado en el token, el backend confía en el mismo valor que usa RLS del lado del servidor.

¿Qué testear primero en un producto que recién arranca a escribir tests?

elegido

La lógica de facturación y liquidación de dinero, antes que la UI

descartado

Empezar por tests de componentes o end-to-end

↳ Un bug visual se nota enseguida; un bug de facturación se nota un mes después, cuando la caja no cierra. El riesgo más caro de no testear es el que toca plata.

Errores reales · lo que salió mal
01

Dentro de una función SECURITY DEFINER, RLS no se aplica automáticamente aunque la tabla tenga políticas — hubo que agregar un chequeo explícito de que el id recibido por parámetro pertenece a la empresa de quien llama, en cada función de negocio que toca datos por id.

02

empresa_actual() explotaba cuando el JWT no traía claims (sesión vieja, token sin refrescar) en vez de simplemente no matchear ninguna fila. Fix: manejar el caso de claims vacíos explícitamente, cubierto ahora por un test de aislamiento RLS.

03

Las mensualidades ya abonadas podían revertirse a 'pendiente' si la deuda total del cliente se recalculaba después. Fix: la sincronización respeta los meses ya saldados en vez de recorrerlos todos de nuevo.

Qué mejoraría

Flujo de self-service para que una distribuidora nueva se dé de alta sola, sin intervención manual del operador. Panel de planes/facturación para que la comercialización sea autogestionada, no manual por mi parte. Sumar cobertura de tests end-to-end sobre los flujos de UI, no solo sobre la lógica de negocio pura.