From 9e508c2c4b2a7728c4f8d4778323f31729a82a15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:32:55 -0400 Subject: [PATCH] fix(vendors): skip assignee validation when assignee hasn't changed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(vendors): skip assignee validation when assignee hasn't changed The form sends the existing assigneeId on every PATCH even when the user only changed a different field (e.g. website). If the vendor's current assignee is a platform admin, every update fails with "Cannot assign a platform admin as assignee" — even though no one is trying to change the assignee. Only run validateAssigneeNotPlatformAdmin when assigneeId is actually being changed to a different value. Co-Authored-By: Claude Opus 4.6 (1M context) * fix(vendors): don't assign platform admins as vendor assignees during onboarding The vendor mitigation task assigned vendors to whoever triggered onboarding (authorId). When a platform admin onboards a customer, all vendors get assigned to the admin. Since platform admins are filtered from the UI assignee list, vendors appear "Unassigned" but the backend still has the admin's member ID — which then blocks all PATCH updates with "Cannot assign a platform admin". Two fixes: - Service: only validate assignee when it's actually changing - Onboarding: skip assignee if author is a platform admin Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: Mariano Fuentes Co-authored-by: Claude Opus 4.6 (1M context) --- apps/api/src/vendors/vendors.service.ts | 8 ++++++-- .../tasks/onboarding/generate-vendor-mitigation.ts | 11 +++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/api/src/vendors/vendors.service.ts b/apps/api/src/vendors/vendors.service.ts index ae1a2acb39..755e445414 100644 --- a/apps/api/src/vendors/vendors.service.ts +++ b/apps/api/src/vendors/vendors.service.ts @@ -600,9 +600,13 @@ export class VendorsService { ) { try { // First check if the vendor exists in the organization - await this.findById(id, organizationId); + const existing = await this.findById(id, organizationId); - if (updateVendorDto.assigneeId) { + // Only validate assignee when it's actually changing + if ( + updateVendorDto.assigneeId && + updateVendorDto.assigneeId !== existing.assigneeId + ) { await this.validateAssigneeNotPlatformAdmin(updateVendorDto.assigneeId, organizationId); } diff --git a/apps/app/src/trigger/tasks/onboarding/generate-vendor-mitigation.ts b/apps/app/src/trigger/tasks/onboarding/generate-vendor-mitigation.ts index e1aa5776bc..f33fd95e9b 100644 --- a/apps/app/src/trigger/tasks/onboarding/generate-vendor-mitigation.ts +++ b/apps/app/src/trigger/tasks/onboarding/generate-vendor-mitigation.ts @@ -44,12 +44,19 @@ export const generateVendorMitigation = task({ await createVendorRiskComment(vendor, policies, organizationId, authorId); - // Mark vendor as assessed and assign to owner/admin + // Mark vendor as assessed and assign to author (unless they're a platform admin, + // since platform admins are hidden from the assignee UI and would block future updates) + const author = await db.member.findFirst({ + where: { id: authorId, organizationId }, + include: { user: { select: { role: true } } }, + }); + const assigneeId = author?.user.role === 'admin' ? null : authorId; + await db.vendor.update({ where: { id: vendor.id, organizationId }, data: { status: VendorStatus.assessed, - assigneeId: authorId, + assigneeId, }, });