From ea3cb56988d348b0f907a568613b30903dbae728 Mon Sep 17 00:00:00 2001 From: Dustin Healy <54083382+dustinhealy@users.noreply.github.com> Date: Thu, 21 May 2026 07:59:34 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix:=20replace=20multi-join=20$l?= =?UTF-8?q?ookup=20in=20getPromptGroup=20for=20DocumentDB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the subpipeline $lookup in getPromptGroup with the simple localField/foreignField form and enforce tenant isolation on the joined production prompt in JS after $unwind. AWS DocumentDB does not support the $lookup with let + pipeline form and rejects the aggregation with: MongoServerError: Aggregation stage not supported: '$lookup on multiple join conditions' Because the catch block returns null, the route treats the prompt group as missing and responds 404 Not Found. Any page that loads a single prompt group (open-for-edit, detail view, etc.) breaks under TENANT_ISOLATION_STRICT=true on a DocumentDB-backed deployment. The simple localField/foreignField form works on both real MongoDB and DocumentDB. Tenant filtering of the joined production prompt is now done after $unwind by clearing the field when its tenantId does not match the active context. --- packages/data-schemas/src/methods/prompt.ts | 41 ++++++++------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/packages/data-schemas/src/methods/prompt.ts b/packages/data-schemas/src/methods/prompt.ts index 86d830fecd..3a0bd35262 100644 --- a/packages/data-schemas/src/methods/prompt.ts +++ b/packages/data-schemas/src/methods/prompt.ts @@ -512,37 +512,26 @@ export function createPromptMethods(mongoose: typeof import('mongoose'), deps: P const tenantId = getTenantId(); const useTenantFilter = tenantId && tenantId !== SYSTEM_TENANT_ID; - const lookupStage = useTenantFilter - ? { - $lookup: { - from: 'prompts', - let: { prodId: '$productionId' }, - pipeline: [ - { - $match: { - $expr: { $eq: ['$_id', '$$prodId'] }, - tenantId, - }, - }, - ], - as: 'productionPrompt', - }, - } - : { - $lookup: { - from: 'prompts', - localField: 'productionId', - foreignField: '_id', - as: 'productionPrompt', - }, - }; - const result = await PromptGroup.aggregate([ { $match: matchFilter }, - lookupStage, + { + $lookup: { + from: 'prompts', + localField: 'productionId', + foreignField: '_id', + as: 'productionPrompt', + }, + }, { $unwind: { path: '$productionPrompt', preserveNullAndEmptyArrays: true } }, ]); const group = result[0] || null; + if ( + group?.productionPrompt && + useTenantFilter && + group.productionPrompt.tenantId !== tenantId + ) { + group.productionPrompt = null; + } if (group?.author) { group.author = group.author.toString(); }