SaaS multi-tenant para distribuidoras de agua y bidones — producto propio construido a partir de Celestina.
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.
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. La empresa y el rol de cada usuario viajan firmados en el token de sesión —inyectados por un Custom Access Token Hook— en vez de leerse de una tabla o del localStorage que el cliente podría manipular. Motor de facturación automática corriendo server-side con pg_cron, y un panel de operador de plataforma que administra altas de empresas sin acceso directo a los datos de ningún tenant.
Producto funcional con el modelo multi-tenant completo: alta de una distribuidora nueva sin tocar código (marca, alias bancario, textos de WhatsApp se configuran por empresa), aprobación manual de paneles de repartidor nuevos, RLS con USING y WITH CHECK en cada tabla de negocio, y funciones SECURITY DEFINER con guard explícito de tenant propio para que ni una función de facturación pueda tocar datos de otra empresa por error. El operador de la plataforma administra altas sin ver un solo dato de negocio de ningún cliente — todo pasa por una Edge Function que valida sus permisos aparte. Documentado en profundidad (diseño multi-tenant, lógica de negocio, onboarding) para poder incorporar clientes nuevos sin re-explicar el sistema cada vez.
Fork de Celestina reescrito para multi-tenancy real: misma base de código de producto, pero con aislamiento de datos por empresa y roles inyectados server-side en vez de leídos del cliente.
¿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.
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.
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.