basalt / teams/src / tenantMembershipPlugin
Function: tenantMembershipPlugin()
> tenantMembershipPlugin(options?): BasaltPlugin<unknown>
Defined in: teams/src/plugin.ts:151
Secure-by-default tenant isolation guard. On EVERY authenticated, tenant-scoped request it asserts that ctx().user holds a membership in the resolved ctx().tenant (rank is only enforced with an explicit role) — closing the gap where a tenant is resolved from client-supplied input (x-tenant-id header / Host) without checking that the caller actually belongs to it.
The guard runs only when BOTH a tenant and a user are present (i.e. an authenticated request that resolved a tenant). It is skipped for:
- routes with no resolved tenant (central/platform routes),
- account routes,
meta: { account: true }— routes about the caller's own identity rather than the tenant's data.authRoutes(),mfaRoutes(),oauthRoutes()(@basaltkit/auth) and the invite-accept route ofteamRoutes()declare it, so a non-member can sign in and accept an invitation on the company's tenant.accountis a neutral key: any package can mark its own account-scoped routes with it, and - routes that explicitly opt out with
meta: { central: true }— used by the routes that legitimately act across/outside a single tenant (tenant creation, platform admin).
Register it alongside authPlugin, tenancyPlugin and teamsPlugin. Treat tenant resolution as identification, never authorization.
Parameters
options?
TenantMembershipPluginOptions = {}
Returns
BasaltPlugin<unknown>