-
Notifications
You must be signed in to change notification settings - Fork 0
Tenant and Site Isolation
Four layers ensure Customer A can never see Customer B — and that users only see the sites they're granted.
-
Data columns — every pipeline/support/extraction table carries
tenant_id+site_id. -
JWT identity — the token carries
userId,tenantId,role;site_idcomes from the request (?site_id=or theX-Site-Idheader). -
EF Core global query filter — auto-injects
WHERE tenant_id = X AND site_id = Yon every query againstITenantScopedentities (Transaction,FileRecord,ActivityLog,InvoiceLineItem).Even if a developer forgets a
WHEREclause, the global filter protects the data. -
Site-access enforcement (FR-5.3) —
TenantSiteMiddlewarechecks the requestedsite_idagainst the user'sUserSiteAccessgrants and returns 403SITE_FORBIDDENif the user isn't authorized for that site. This closes the within-tenant gap that the tenant filter alone doesn't cover — a user can no longer read another site in their own tenant just by sending itsX-Site-Id.
Identity catalogs (users, sites, user_site_access) and global catalogs (document_types, item_categories, error_catalog) are intentionally not tenant-filtered.
- Global tenant scoping is always enforced.
-
Site is optional — supplied via
?site_id=orX-Site-Id. - When no site is supplied, services scope by tenant only.
- When a site is supplied, the middleware validates it against the user's
UserSiteAccessgrants → 403SITE_FORBIDDENif unauthorized.
Seed users have uneven site access on purpose. Example: user.b@acme.com (Chennai only) requesting Mumbai via X-Site-Id is rejected with 403. Full roster + walkthrough in API Reference.