Datos · infrastructure/db
Adapter listo para producciónPrisma,
con guardrails.
El bug clásico de multi-tenancy es una query que se olvida su organizationId y sirve en silencio las filas de otro cliente. UseDeploy envuelve el cliente de Prisma en un tenant guard que convierte ese error en una excepción en tiempo de ejecución — no en una brecha de datos en producción.
Dos clientes: guardado por defecto
Los repositorios reciben el cliente guardado. Cualquier lectura o mutación sobre un modelo scopeado por tenant cuyo where no restrinja organizationId lanza TenantScopeViolationError. Existe un cliente de sistema separado y nombrado de forma explícita para los paths legítimos entre tenants (workers, lookups de tokens, export GDPR), así cada bypass es grepeable.
1 export const getPrismaClient = (): PrismaClient => {
2 if (!guardedClient) {
3 guardedClient = applyTenantGuard(getBaseClient());
4 }
5 return guardedClient;
6 };
7
8 // Unguarded, explicit, greppable — for workers / token lookups only:
9 export const getSystemPrismaClient = () => getBaseClient();
Por qué importa
Falla a los gritos, no en silencio
Olvidarte del scope de org en código nuevo lanza en la primera ejecución en vez de filtrar filas entre tenants — el modo de falla que querés.
Lista explícita de modelos
TENANT_SCOPED_MODELS enumera cada modelo propiedad de una org. Agregar uno nuevo al schema implica agregarlo acá — un paso deliberado y revisable.
Un solo connection pool
El cliente guardado y el de sistema comparten el pool del cliente base, así el guard no cuesta conexiones extra.
Friendly con poolers
DIRECT_URL está soportada para pgbouncer de Supabase y poolers similares, donde las migraciones necesitan una conexión directa.
Referencia de configuración
Variables de entorno
DATABASE_URLrequeridaPostgres connection string
DIRECT_URLopcionaldirect connection when DATABASE_URL is a pooler
Dónde vive
apps/server/src/infrastructure/db/prisma-client.tsapps/server/src/infrastructure/db/tenant-guard.ts
Datos multi-tenant que fallan seguro.
Construí sobre un cliente de Prisma que convierte un scope de org olvidado en una excepción, no en una fuga.