fix-tenant-guard-populaterun.mdlane/output/notes.md/finances (and any page populating a user-discriminator ref) throws
[tenant] expert.find called without tenantId and renders an error ·
expected: the page loads; the populate is a tenant-safe _id join_id, $or and
$and in the filter. Populating a discriminator ref makes Mongoose add the discriminator key
(role on the user model) to that filter, so the check fails and the guard throws.packages/services/src/db/plugins/tenant.ts: allow the queried model's discriminator key
alongside _id / $or / $and in the populate shape check.Not reproducible in the agent sandbox (no database, no preview credentials). Reproduced instead from production telemetry plus a deterministic code trace:
web: group
Error: [tenant] expert.find called without tenantId …, routes /finances.rsc, /finances.quoteService.findAll (packages/services/src/db/services/quote/index.ts) populates
{ path: "expert", … }, plus customer, vendor and manager.getExpertModel (packages/services/src/db/models/user.ts) is a discriminator on the user model,
declared with { discriminatorKey: "role" }. Mongoose therefore issues the populate as
expert.find({ _id: { $in: [...] }, role: "expert", $or: [ …soft-delete… ] }).role is not in the allowlist → the idOnly test fails → the guard throws.The error names expert.find — the discriminator model, not the base user model — which is the
confirming detail.
The guard's existing rationale is that ObjectIds are globally unique, so an _id-only join cannot
widen results across tenants. The discriminator key only narrows the same join, so allowing it
cannot widen anything. Every other named field in a filter still throws, and non-find hooks are
untouched.
Any populate of a user-discriminator ref without a tenant filter — quotes and invoices lists, and
plausibly other pages that populate expert / customer / vendor / csm. Present on main
since #739; only surfaced now because these pages had not been exercised on a preview since.