feat: implement tenant isolation with PostgreSQL RLS

- users + tenant_memberships tables (tenant-scoped)
- RLS policy on tenant_memberships using set_config('app.current_tenant_id', ...)
- withTenantContext() helper for transaction-scoped tenant context
- separate non-superuser app role (b2bcall_app): the default Docker postgres
  user is SUPERUSER and always bypasses RLS even with FORCE, so the app must
  never connect through the migration/owner role. Documented in
  docs/TENANT_ISOLATION.md.
- automated isolation test proving tenant A never sees tenant B's data
This commit is contained in:
2026-08-28 05:47:23 -03:00
parent c0f29328bd
commit d66170c795
11 changed files with 676 additions and 6 deletions

View File

@@ -8,7 +8,8 @@
"prisma:generate": "prisma generate",
"prisma:migrate": "prisma migrate dev",
"prisma:deploy": "prisma migrate deploy",
"typecheck": "tsc --noEmit"
"typecheck": "tsc --noEmit",
"test:isolation": "tsx src/__tests__/tenant-isolation.test.ts"
},
"dependencies": {
"@prisma/adapter-pg": "^7.10.0",
@@ -17,6 +18,7 @@
},
"devDependencies": {
"@types/pg": "^8.23.1",
"prisma": "7.10.0"
"prisma": "7.10.0",
"tsx": "^4.23.12"
}
}