Skip to content

fix: enforce tenant data isolation and prevent silent cross-tenant leaks#12

Merged
mindsers merged 2 commits intomainfrom
fix/tenant-data-scoping
Apr 10, 2026
Merged

fix: enforce tenant data isolation and prevent silent cross-tenant leaks#12
mindsers merged 2 commits intomainfrom
fix/tenant-data-scoping

Conversation

@mindsers
Copy link
Copy Markdown
Contributor

Summary

  • Unauthenticated route validation: login, password-forgot, and password-reset pages now validate the subdomain via resolveCongregationFromRequest() and redirect to /congregation-not-found for unknown subdomains.
  • Data scoping fix: the Prisma 7 pg adapter breaks AsyncLocalStorage context after awaited queries. The scoped db extension silently fell through to unscoped queries, returning data from all congregations. Now it throws on missing context (fail-safe) and re-enters context after each query.
  • verifyRole context restoration: verifyRole() re-enters ALS context before returning, so subsequent db queries in loaders have the correct tenant scope.
  • Replaces real congregation name (Lyon Confluence) with generic placeholder in seed and register UI.

Builds on #11 which handled session/login tenant validation.

Test plan

  • Log into congregation A, navigate to congregation B → see B's login page (session destroyed)
  • On congregation B's login, use congregation A's credentials → "Email ou mot de passe invalide"
  • Visit unknown subdomain → "Assemblée non trouvée" error page
  • Log into congregation A → see only congregation A's data (users, territories, publishers)
  • Single-tenant mode (MULTI_TENANT unset) → no behavioral change
  • pnpm test:unit — 316 tests pass
  • pnpm test:typecheck — clean
  • pnpm test:lint — clean

…set)

resolveCongregationFromRequest() was only called inside authenticated
code paths. Unauthenticated pages (login, password forgot, password
reset) on unknown subdomains rendered normally instead of redirecting
to /congregation-not-found.
The Prisma 7 pg adapter breaks AsyncLocalStorage context propagation
after awaited queries. The scoped db extension silently fell through to
unscoped queries when context was missing, returning data from all
congregations instead of just the current tenant.

- Make db extension throw on missing congregation context (fail-safe)
- Re-enter ALS context after each scoped query in the db extension
- Re-enter ALS context in verifyRole() after its unscopedDb queries
@mindsers mindsers merged commit f038a3a into main Apr 10, 2026
4 checks passed
@mindsers mindsers deleted the fix/tenant-data-scoping branch April 10, 2026 07:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant