From cc9cee39539e5e2ed7d5905f34033c8c979a0a1f Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Thu, 4 Dec 2025 20:43:30 -0800 Subject: [PATCH 1/4] fix(additional-privileges): return correct project membership ID --- ...ity-project-additional-privilege-router.ts | 10 +- .../additional-privilege-service.ts | 112 +++++++++++++++++- 2 files changed, 111 insertions(+), 11 deletions(-) diff --git a/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts b/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts index 47b3f5258c..70ef9990ee 100644 --- a/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts +++ b/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts @@ -84,7 +84,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privilege: { ...privilege, identityId: req.body.identityId, - projectMembershipId: req.body.projectId, + projectMembershipId: privilege.projectMembershipId || req.body.projectId, projectId: req.body.projectId, slug: privilege.name } @@ -168,7 +168,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privilege: { ...privilege, identityId: privilegeDoc.actorIdentityId as string, - projectMembershipId: privilegeDoc.projectId as string, + projectMembershipId: privilege.projectMembershipId || (privilegeDoc.projectId as string), projectId: privilegeDoc.projectId as string, slug: privilege.name } @@ -222,7 +222,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privilege: { ...privilege, identityId: privilegeDoc.actorIdentityId as string, - projectMembershipId: privilegeDoc.projectId as string, + projectMembershipId: privilege.projectMembershipId || (privilegeDoc.projectId as string), projectId: privilegeDoc.projectId as string, slug: privilege.name } @@ -276,7 +276,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privilege: { ...privilege, identityId: privilegeDoc.actorIdentityId as string, - projectMembershipId: privilegeDoc.projectId as string, + projectMembershipId: privilege.projectMembershipId || (privilegeDoc.projectId as string), projectId: privilegeDoc.projectId as string, slug: privilege.name } @@ -391,7 +391,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privileges: privileges.map((privilege) => ({ ...privilege, identityId: req.query.identityId, - projectMembershipId: privilege.projectId as string, + projectMembershipId: privilege.projectMembershipId || (privilege.projectId as string), projectId: req.query.projectId, slug: privilege.name })) diff --git a/backend/src/services/additional-privilege/additional-privilege-service.ts b/backend/src/services/additional-privilege/additional-privilege-service.ts index 2af9e6419a..7fa99b47ab 100644 --- a/backend/src/services/additional-privilege/additional-privilege-service.ts +++ b/backend/src/services/additional-privilege/additional-privilege-service.ts @@ -58,6 +58,21 @@ export const additionalPrivilegeServiceFactory = ({ const scope = factory.getScopeField(dto.scopeData); const dbActorField = data.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; + let projectMembershipId: string | undefined; + if (scope.key === "projectId") { + const projectMembership = await membershipDAL.findOne({ + [dbActorField]: data.actorId, + scopeProjectId: scope.value, + scope: AccessScope.Project + }); + + if (!projectMembership) { + throw new NotFoundError({ message: `Project membership for ${data.actorType} ${data.actorId} not found` }); + } + + projectMembershipId = projectMembership.id; + } + const existingSlug = await additionalPrivilegeDAL.findOne({ name: data.name, [dbActorField]: data.actorId, @@ -79,7 +94,11 @@ export const additionalPrivilegeServiceFactory = ({ }); return { - additionalPrivilege: { ...additionalPrivilege, permissions: unpackPermissions(additionalPrivilege.permissions) } + additionalPrivilege: { + ...additionalPrivilege, + permissions: unpackPermissions(additionalPrivilege.permissions), + projectMembershipId + } }; } @@ -103,7 +122,11 @@ export const additionalPrivilegeServiceFactory = ({ }); return { - additionalPrivilege: { ...additionalPrivilege, permissions: unpackPermissions(additionalPrivilege.permissions) } + additionalPrivilege: { + ...additionalPrivilege, + permissions: unpackPermissions(additionalPrivilege.permissions), + projectMembershipId + } }; }; @@ -114,6 +137,21 @@ export const additionalPrivilegeServiceFactory = ({ const scope = factory.getScopeField(dto.scopeData); const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; + let projectMembershipId: string | undefined; + if (scope.key === "projectId") { + const projectMembership = await membershipDAL.findOne({ + [dbActorField]: dto.selector.actorId, + scopeProjectId: scope.value, + scope: AccessScope.Project + }); + if (!projectMembership) { + throw new NotFoundError({ + message: `Project membership for ${dto.selector.actorType} ${dto.selector.actorId} not found` + }); + } + projectMembershipId = projectMembership.id; + } + const existingPrivilege = await additionalPrivilegeDAL.findOne({ [dbActorField]: dto.selector.actorId, id: dto.selector.id, @@ -136,7 +174,11 @@ export const additionalPrivilegeServiceFactory = ({ }); return { - additionalPrivilege: { ...additionalPrivilege, permissions: unpackPermissions(additionalPrivilege.permissions) } + additionalPrivilege: { + ...additionalPrivilege, + permissions: unpackPermissions(additionalPrivilege.permissions), + projectMembershipId + } }; } @@ -158,7 +200,11 @@ export const additionalPrivilegeServiceFactory = ({ }); return { - additionalPrivilege: { ...additionalPrivilege, permissions: unpackPermissions(additionalPrivilege.permissions) } + additionalPrivilege: { + ...additionalPrivilege, + permissions: unpackPermissions(additionalPrivilege.permissions), + projectMembershipId + } }; }; @@ -169,6 +215,21 @@ export const additionalPrivilegeServiceFactory = ({ const scope = factory.getScopeField(dto.scopeData); const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; + let projectMembershipId: string | undefined; + if (scope.key === "projectId") { + const projectMembership = await membershipDAL.findOne({ + [dbActorField]: dto.selector.actorId, + scopeProjectId: scope.value, + scope: AccessScope.Project + }); + if (!projectMembership) { + throw new NotFoundError({ + message: `Project membership for ${dto.selector.actorType} ${dto.selector.actorId} not found` + }); + } + projectMembershipId = projectMembership.id; + } + const existingPrivilege = await additionalPrivilegeDAL.findOne({ id: selector.id, [dbActorField]: dto.selector.actorId, @@ -179,7 +240,11 @@ export const additionalPrivilegeServiceFactory = ({ const additionalPrivilege = await additionalPrivilegeDAL.deleteById(existingPrivilege.id); return { - additionalPrivilege: { ...additionalPrivilege, permissions: unpackPermissions(additionalPrivilege.permissions) } + additionalPrivilege: { + ...additionalPrivilege, + permissions: unpackPermissions(additionalPrivilege.permissions), + projectMembershipId + } }; }; @@ -190,6 +255,21 @@ export const additionalPrivilegeServiceFactory = ({ const scope = factory.getScopeField(dto.scopeData); const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; + let projectMembershipId: string | undefined; + if (scope.key === "projectId") { + const projectMembership = await membershipDAL.findOne({ + [dbActorField]: dto.selector.actorId, + scopeProjectId: scope.value, + scope: AccessScope.Project + }); + if (!projectMembership) { + throw new NotFoundError({ + message: `Project membership for ${dto.selector.actorType} ${dto.selector.actorId} not found` + }); + } + projectMembershipId = projectMembership.id; + } + const additionalPrivilege = await additionalPrivilegeDAL.findOne({ id: selector.id, [dbActorField]: dto.selector.actorId, @@ -199,7 +279,11 @@ export const additionalPrivilegeServiceFactory = ({ throw new NotFoundError({ message: `Additional privilege with id ${selector.id} doesn't exist` }); return { - additionalPrivilege: { ...additionalPrivilege, permissions: unpackPermissions(additionalPrivilege.permissions) } + additionalPrivilege: { + ...additionalPrivilege, + permissions: unpackPermissions(additionalPrivilege.permissions), + projectMembershipId + } }; }; @@ -230,6 +314,21 @@ export const additionalPrivilegeServiceFactory = ({ const scope = factory.getScopeField(dto.scopeData); const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; + let projectMembershipId: string | undefined; + if (scope.key === "projectId") { + const projectMembership = await membershipDAL.findOne({ + [dbActorField]: dto.selector.actorId, + scopeProjectId: scope.value, + scope: AccessScope.Project + }); + if (!projectMembership) { + throw new NotFoundError({ + message: `Project membership for ${dto.selector.actorType} ${dto.selector.actorId} not found` + }); + } + projectMembershipId = projectMembership.id; + } + const additionalPrivileges = await additionalPrivilegeDAL.find({ [dbActorField]: dto.selector.actorId, [scope.key]: scope.value @@ -238,6 +337,7 @@ export const additionalPrivilegeServiceFactory = ({ return { additionalPrivileges: additionalPrivileges.map((el) => ({ ...el, + projectMembershipId, permissions: unpackPermissions(el.permissions) })) }; From b3f2fb13995ac62103e89d6d75067f5cf4787296 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Thu, 4 Dec 2025 23:02:29 -0800 Subject: [PATCH 2/4] added missed endpoint --- ...ity-project-additional-privilege-router.ts | 2 +- .../additional-privilege-service.ts | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts b/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts index 70ef9990ee..b13194278f 100644 --- a/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts +++ b/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts @@ -339,7 +339,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privilege: { ...privilege, identityId: req.query.identityId, - projectMembershipId: privilege.projectId as string, + projectMembershipId: privilege.projectMembershipId || (privilege.projectId as string), projectId, slug: privilege.name } diff --git a/backend/src/services/additional-privilege/additional-privilege-service.ts b/backend/src/services/additional-privilege/additional-privilege-service.ts index 7fa99b47ab..3fdc586344 100644 --- a/backend/src/services/additional-privilege/additional-privilege-service.ts +++ b/backend/src/services/additional-privilege/additional-privilege-service.ts @@ -294,6 +294,21 @@ export const additionalPrivilegeServiceFactory = ({ const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; const scope = factory.getScopeField(dto.scopeData); + let projectMembershipId: string | undefined; + if (scope.key === "projectId") { + const projectMembership = await membershipDAL.findOne({ + [dbActorField]: dto.selector.actorId, + scopeProjectId: scope.value, + scope: AccessScope.Project + }); + + if (!projectMembership) { + throw new NotFoundError({ + message: `Project membership for ${dto.selector.actorType} ${dto.selector.actorId} not found` + }); + } + projectMembershipId = projectMembership.id; + } const additionalPrivilege = await additionalPrivilegeDAL.findOne({ name: selector.name, [dbActorField]: dto.selector.actorId, @@ -303,7 +318,11 @@ export const additionalPrivilegeServiceFactory = ({ throw new NotFoundError({ message: `Additional privilege with name ${selector.name} doesn't exist` }); return { - additionalPrivilege: { ...additionalPrivilege, permissions: unpackPermissions(additionalPrivilege.permissions) } + additionalPrivilege: { + ...additionalPrivilege, + permissions: unpackPermissions(additionalPrivilege.permissions), + projectMembershipId + } }; }; From 0f3108f6fb2f22c8cbe85b5b4e9e735b57e680ed Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Sat, 6 Dec 2025 09:37:25 -0500 Subject: [PATCH 3/4] fix: removed projectMembershipId entirely --- ...ity-project-additional-privilege-router.ts | 6 - .../identitiy-additional-privilege.ts | 4 +- .../additional-privilege-service.ts | 112 ++---------------- 3 files changed, 10 insertions(+), 112 deletions(-) diff --git a/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts b/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts index b13194278f..23ba27b8a5 100644 --- a/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts +++ b/backend/src/ee/routes/v2/identity-project-additional-privilege-router.ts @@ -84,7 +84,6 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privilege: { ...privilege, identityId: req.body.identityId, - projectMembershipId: privilege.projectMembershipId || req.body.projectId, projectId: req.body.projectId, slug: privilege.name } @@ -168,7 +167,6 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privilege: { ...privilege, identityId: privilegeDoc.actorIdentityId as string, - projectMembershipId: privilege.projectMembershipId || (privilegeDoc.projectId as string), projectId: privilegeDoc.projectId as string, slug: privilege.name } @@ -222,7 +220,6 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privilege: { ...privilege, identityId: privilegeDoc.actorIdentityId as string, - projectMembershipId: privilege.projectMembershipId || (privilegeDoc.projectId as string), projectId: privilegeDoc.projectId as string, slug: privilege.name } @@ -276,7 +273,6 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privilege: { ...privilege, identityId: privilegeDoc.actorIdentityId as string, - projectMembershipId: privilege.projectMembershipId || (privilegeDoc.projectId as string), projectId: privilegeDoc.projectId as string, slug: privilege.name } @@ -339,7 +335,6 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privilege: { ...privilege, identityId: req.query.identityId, - projectMembershipId: privilege.projectMembershipId || (privilege.projectId as string), projectId, slug: privilege.name } @@ -391,7 +386,6 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F privileges: privileges.map((privilege) => ({ ...privilege, identityId: req.query.identityId, - projectMembershipId: privilege.projectMembershipId || (privilege.projectId as string), projectId: req.query.projectId, slug: privilege.name })) diff --git a/backend/src/server/routes/sanitizedSchema/identitiy-additional-privilege.ts b/backend/src/server/routes/sanitizedSchema/identitiy-additional-privilege.ts index e44b9af4ec..0feb1ba55c 100644 --- a/backend/src/server/routes/sanitizedSchema/identitiy-additional-privilege.ts +++ b/backend/src/server/routes/sanitizedSchema/identitiy-additional-privilege.ts @@ -2,6 +2,8 @@ import { IdentityProjectAdditionalPrivilegeSchema } from "@app/db/schemas"; import { UnpackedPermissionSchema } from "./permission"; -export const SanitizedIdentityPrivilegeSchema = IdentityProjectAdditionalPrivilegeSchema.extend({ +export const SanitizedIdentityPrivilegeSchema = IdentityProjectAdditionalPrivilegeSchema.omit({ + projectMembershipId: true +}).extend({ permissions: UnpackedPermissionSchema.array() }); diff --git a/backend/src/services/additional-privilege/additional-privilege-service.ts b/backend/src/services/additional-privilege/additional-privilege-service.ts index 3fdc586344..69f103c853 100644 --- a/backend/src/services/additional-privilege/additional-privilege-service.ts +++ b/backend/src/services/additional-privilege/additional-privilege-service.ts @@ -58,21 +58,6 @@ export const additionalPrivilegeServiceFactory = ({ const scope = factory.getScopeField(dto.scopeData); const dbActorField = data.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; - let projectMembershipId: string | undefined; - if (scope.key === "projectId") { - const projectMembership = await membershipDAL.findOne({ - [dbActorField]: data.actorId, - scopeProjectId: scope.value, - scope: AccessScope.Project - }); - - if (!projectMembership) { - throw new NotFoundError({ message: `Project membership for ${data.actorType} ${data.actorId} not found` }); - } - - projectMembershipId = projectMembership.id; - } - const existingSlug = await additionalPrivilegeDAL.findOne({ name: data.name, [dbActorField]: data.actorId, @@ -96,8 +81,7 @@ export const additionalPrivilegeServiceFactory = ({ return { additionalPrivilege: { ...additionalPrivilege, - permissions: unpackPermissions(additionalPrivilege.permissions), - projectMembershipId + permissions: unpackPermissions(additionalPrivilege.permissions) } }; } @@ -124,8 +108,7 @@ export const additionalPrivilegeServiceFactory = ({ return { additionalPrivilege: { ...additionalPrivilege, - permissions: unpackPermissions(additionalPrivilege.permissions), - projectMembershipId + permissions: unpackPermissions(additionalPrivilege.permissions) } }; }; @@ -137,21 +120,6 @@ export const additionalPrivilegeServiceFactory = ({ const scope = factory.getScopeField(dto.scopeData); const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; - let projectMembershipId: string | undefined; - if (scope.key === "projectId") { - const projectMembership = await membershipDAL.findOne({ - [dbActorField]: dto.selector.actorId, - scopeProjectId: scope.value, - scope: AccessScope.Project - }); - if (!projectMembership) { - throw new NotFoundError({ - message: `Project membership for ${dto.selector.actorType} ${dto.selector.actorId} not found` - }); - } - projectMembershipId = projectMembership.id; - } - const existingPrivilege = await additionalPrivilegeDAL.findOne({ [dbActorField]: dto.selector.actorId, id: dto.selector.id, @@ -176,8 +144,7 @@ export const additionalPrivilegeServiceFactory = ({ return { additionalPrivilege: { ...additionalPrivilege, - permissions: unpackPermissions(additionalPrivilege.permissions), - projectMembershipId + permissions: unpackPermissions(additionalPrivilege.permissions) } }; } @@ -202,8 +169,7 @@ export const additionalPrivilegeServiceFactory = ({ return { additionalPrivilege: { ...additionalPrivilege, - permissions: unpackPermissions(additionalPrivilege.permissions), - projectMembershipId + permissions: unpackPermissions(additionalPrivilege.permissions) } }; }; @@ -215,21 +181,6 @@ export const additionalPrivilegeServiceFactory = ({ const scope = factory.getScopeField(dto.scopeData); const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; - let projectMembershipId: string | undefined; - if (scope.key === "projectId") { - const projectMembership = await membershipDAL.findOne({ - [dbActorField]: dto.selector.actorId, - scopeProjectId: scope.value, - scope: AccessScope.Project - }); - if (!projectMembership) { - throw new NotFoundError({ - message: `Project membership for ${dto.selector.actorType} ${dto.selector.actorId} not found` - }); - } - projectMembershipId = projectMembership.id; - } - const existingPrivilege = await additionalPrivilegeDAL.findOne({ id: selector.id, [dbActorField]: dto.selector.actorId, @@ -242,8 +193,7 @@ export const additionalPrivilegeServiceFactory = ({ return { additionalPrivilege: { ...additionalPrivilege, - permissions: unpackPermissions(additionalPrivilege.permissions), - projectMembershipId + permissions: unpackPermissions(additionalPrivilege.permissions) } }; }; @@ -255,21 +205,6 @@ export const additionalPrivilegeServiceFactory = ({ const scope = factory.getScopeField(dto.scopeData); const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; - let projectMembershipId: string | undefined; - if (scope.key === "projectId") { - const projectMembership = await membershipDAL.findOne({ - [dbActorField]: dto.selector.actorId, - scopeProjectId: scope.value, - scope: AccessScope.Project - }); - if (!projectMembership) { - throw new NotFoundError({ - message: `Project membership for ${dto.selector.actorType} ${dto.selector.actorId} not found` - }); - } - projectMembershipId = projectMembership.id; - } - const additionalPrivilege = await additionalPrivilegeDAL.findOne({ id: selector.id, [dbActorField]: dto.selector.actorId, @@ -281,8 +216,7 @@ export const additionalPrivilegeServiceFactory = ({ return { additionalPrivilege: { ...additionalPrivilege, - permissions: unpackPermissions(additionalPrivilege.permissions), - projectMembershipId + permissions: unpackPermissions(additionalPrivilege.permissions) } }; }; @@ -294,21 +228,6 @@ export const additionalPrivilegeServiceFactory = ({ const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; const scope = factory.getScopeField(dto.scopeData); - let projectMembershipId: string | undefined; - if (scope.key === "projectId") { - const projectMembership = await membershipDAL.findOne({ - [dbActorField]: dto.selector.actorId, - scopeProjectId: scope.value, - scope: AccessScope.Project - }); - - if (!projectMembership) { - throw new NotFoundError({ - message: `Project membership for ${dto.selector.actorType} ${dto.selector.actorId} not found` - }); - } - projectMembershipId = projectMembership.id; - } const additionalPrivilege = await additionalPrivilegeDAL.findOne({ name: selector.name, [dbActorField]: dto.selector.actorId, @@ -320,8 +239,7 @@ export const additionalPrivilegeServiceFactory = ({ return { additionalPrivilege: { ...additionalPrivilege, - permissions: unpackPermissions(additionalPrivilege.permissions), - projectMembershipId + permissions: unpackPermissions(additionalPrivilege.permissions) } }; }; @@ -333,21 +251,6 @@ export const additionalPrivilegeServiceFactory = ({ const scope = factory.getScopeField(dto.scopeData); const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"; - let projectMembershipId: string | undefined; - if (scope.key === "projectId") { - const projectMembership = await membershipDAL.findOne({ - [dbActorField]: dto.selector.actorId, - scopeProjectId: scope.value, - scope: AccessScope.Project - }); - if (!projectMembership) { - throw new NotFoundError({ - message: `Project membership for ${dto.selector.actorType} ${dto.selector.actorId} not found` - }); - } - projectMembershipId = projectMembership.id; - } - const additionalPrivileges = await additionalPrivilegeDAL.find({ [dbActorField]: dto.selector.actorId, [scope.key]: scope.value @@ -356,7 +259,6 @@ export const additionalPrivilegeServiceFactory = ({ return { additionalPrivileges: additionalPrivileges.map((el) => ({ ...el, - projectMembershipId, permissions: unpackPermissions(el.permissions) })) }; From 20570094be1c42008baa82819eb3790cdd169b7e Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Sat, 6 Dec 2025 09:39:46 -0500 Subject: [PATCH 4/4] Update types.tsx --- .../src/hooks/api/identityProjectAdditionalPrivilege/types.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/hooks/api/identityProjectAdditionalPrivilege/types.tsx b/frontend/src/hooks/api/identityProjectAdditionalPrivilege/types.tsx index 1e070e2bb7..dbdbe7c3b9 100644 --- a/frontend/src/hooks/api/identityProjectAdditionalPrivilege/types.tsx +++ b/frontend/src/hooks/api/identityProjectAdditionalPrivilege/types.tsx @@ -5,7 +5,6 @@ export enum IdentityProjectAdditionalPrivilegeTemporaryMode { } export type TIdentityProjectPrivilege = { - projectMembershipId: string; slug: string; id: string; createdAt: Date;