Tenant isolation is one of those things that's easy to claim and hard to verify. Here's how we do it, with the actual mechanism, so you can audit the claim.
The plugin
Every Mongoose schema in the API installs a tenantScopePlugin. The plugin registers pre-hooks on every query verb — find, findOne, findOneAndUpdate, updateMany, deleteOne, deleteMany, countDocuments, aggregate, save.
On each query, the plugin:
1. Reads the current tenant from AsyncLocalStorage (set by authMiddleware on every request). 2. If the query doesn't include companyId, it injects the current tenant's value. 3. If the query DOES include a companyId, the plugin verifies it matches the current tenant. If not — it throws CROSS_TENANT_QUERY.
Throwing > returning empty
A naïve isolation approach returns empty results when tenants mismatch. That's worse than failing loudly: bugs that should throw at dev time silently return [] in production, and the dev assumes "no data."
We throw. Loudly. Stack trace. So that a controller that accidentally constructs a cross-tenant query gets noticed in the first 5 seconds of testing.
Escape hatch — but audited
Some legitimate flows (platform-staff admin tooling, internal migrations) need cross-tenant access. They use bypassTenantScope(query), which sets a special option on the query. Every use of that helper is grep-able and reviewed.
The result
There is no path through the application where data from tenant A reaches a session bound to tenant B. Not from a missing filter, not from a populated reference, not from an aggregation. The tenant boundary is a property of the data layer, not a property of any individual route.