@7365admin1/core 3.68.2 → 3.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @iservice365/core
2
2
 
3
+ ## 3.69.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d2cf85f: Invite Client: Seven365 staff can choose a new client's modules (`modules` on `POST /api/auth/invite/user`, console `organizations` permission). Onboarding from that invitation stores the list on the organisation and records the save row that makes the module gate enforce it. A new-client invitation no longer carries a shared template role, so the owner holds the organisation's own seeded owner role.
8
+
9
+ ## 3.68.3
10
+
11
+ ### Patch Changes
12
+
13
+ - 1d5050b: Re-inviting the same person to the same app, organisation and site now re-sends the pending invitation instead of adding a duplicate; invite request logs no longer record the invitee's e-mail address.
14
+
3
15
  ## 3.68.2
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,10 +1,8 @@
1
1
  import * as mongodb from 'mongodb';
2
2
  import { ObjectId, ClientSession, Db, Collection, Document, AggregateOptions } from 'mongodb';
3
3
  import Joi from 'joi';
4
- import { Request, Response, NextFunction } from 'express';
4
+ import { Request, Response, NextFunction, RequestHandler } from 'express';
5
5
  import * as bson from 'bson';
6
- import * as qs from 'qs';
7
- import * as express_serve_static_core from 'express-serve-static-core';
8
6
  import { z } from 'zod';
9
7
  import { Server } from 'socket.io';
10
8
 
@@ -971,24 +969,25 @@ type TMemberModulesDeps = {
971
969
  requireSelfOrPlatformStaff: typeof requireSelfOrPlatformStaff;
972
970
  gateData?: TModuleGateData;
973
971
  };
972
+ type MemberController = {
973
+ createMember: RequestHandler;
974
+ getByUserId: RequestHandler;
975
+ getByUserIdType: RequestHandler;
976
+ getModulesByUserIdType: RequestHandler;
977
+ getAll: RequestHandler;
978
+ getAllByUser: RequestHandler;
979
+ getOrgsByMembership: RequestHandler;
980
+ updateMemberStatus: RequestHandler;
981
+ updateRoleById: RequestHandler;
982
+ createMemberDirect: RequestHandler;
983
+ updateSiteById: RequestHandler;
984
+ getByUserIdTypeOrg: RequestHandler;
985
+ completeOnboarding: RequestHandler;
986
+ };
974
987
  declare function memberModulesHandlers({ requireSelfOrPlatformStaff, gateData, }: TMemberModulesDeps): {
975
988
  getModulesByUserIdType: (req: Request, res: Response, next: NextFunction) => Promise<void>;
976
989
  };
977
- declare function useMemberController(): {
978
- createMember: (req: Request, res: Response, next: NextFunction) => Promise<void>;
979
- getByUserId: (req: Request, res: Response, next: NextFunction) => Promise<void>;
980
- getByUserIdType: (req: Request, res: Response, next: NextFunction) => Promise<void>;
981
- getModulesByUserIdType: (req: Request<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction) => Promise<void>;
982
- getAll: (req: Request, res: Response, next: NextFunction) => Promise<void>;
983
- getAllByUser: (req: Request, res: Response, next: NextFunction) => Promise<void>;
984
- getOrgsByMembership: (req: Request, res: Response, next: NextFunction) => Promise<void>;
985
- updateMemberStatus: (req: Request, res: Response, next: NextFunction) => Promise<void>;
986
- updateRoleById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
987
- createMemberDirect: (req: Request, res: Response, next: NextFunction) => Promise<void>;
988
- updateSiteById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
989
- getByUserIdTypeOrg: (req: Request, res: Response, next: NextFunction) => Promise<void>;
990
- completeOnboarding: (req: Request, res: Response, next: NextFunction) => Promise<void>;
991
- };
990
+ declare function useMemberController(): MemberController;
992
991
 
993
992
  declare function useMemberService(): {
994
993
  createMember: (id: string) => Promise<{
@@ -1057,6 +1056,10 @@ declare class MVerification implements TVerification {
1057
1056
  constructor(value: TVerification);
1058
1057
  }
1059
1058
 
1059
+ type TKeyValuePair<K extends string | number | symbol = string, V = any> = {
1060
+ [key in K]: V;
1061
+ };
1062
+
1060
1063
  declare function useVerificationRepo(): {
1061
1064
  createIndex: () => Promise<void>;
1062
1065
  createTextIndex: () => Promise<void>;
@@ -1076,6 +1079,10 @@ declare function useVerificationRepo(): {
1076
1079
  }) => Promise<{}>;
1077
1080
  getByIdByType: (type: string) => Promise<TVerification[]>;
1078
1081
  updateStatusById: (_id: string | ObjectId, status: string, session?: ClientSession) => Promise<mongodb.UpdateResult<bson.Document>>;
1082
+ reissuePendingById: (_id: string | ObjectId, { metadata, expireAt }: {
1083
+ metadata: TKeyValuePair;
1084
+ expireAt: string;
1085
+ }) => Promise<number>;
1079
1086
  getByStatus: (status: string) => Promise<TVerification[]>;
1080
1087
  findOne: (query: any) => Promise<mongodb.WithId<bson.Document> | null>;
1081
1088
  completePendingInvites: ({ email, orgId, siteId, app, session, }: {
@@ -1087,10 +1094,6 @@ declare function useVerificationRepo(): {
1087
1094
  }) => Promise<mongodb.UpdateResult<bson.Document>>;
1088
1095
  };
1089
1096
 
1090
- type TKeyValuePair<K extends string | number | symbol = string, V = any> = {
1091
- [key in K]: V;
1092
- };
1093
-
1094
1097
  declare function useVerificationService(): {
1095
1098
  createUserInvite: ({ email, metadata, }: {
1096
1099
  email: string;
@@ -1560,22 +1563,23 @@ type TOrgOwnerRepairDeps = {
1560
1563
  declare function orgOwnerRepairHandlers({ requireConsolePermission, getOrgUncached, countOrgMembers, claim, release, holdsClaim, findUserByEmail, confirmOwnership, findOwnerRoleId, healDefaultRoles, createMemberDirect, recordConsoleAction, gateOn, }: TOrgOwnerRepairDeps): {
1561
1564
  repairOwnerMembership: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1562
1565
  };
1563
- declare function useOrgController(): {
1564
- add: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1565
- addOnboardingOrg: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1566
- getAll: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1567
- getOrgsByUserId: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1568
- getByName: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1569
- getById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1570
- getByEmail: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1571
- update: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1572
- getOrgsByEmail: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1573
- getAdminOrgForResident: (_req: Request, res: Response, next: NextFunction) => Promise<void>;
1574
- updateStatus: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1575
- updateModules: (req: Request<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction) => Promise<void>;
1576
- previewOrgModules: (req: Request<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction) => Promise<void>;
1577
- repairOwnerMembership: (req: Request<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction) => Promise<void>;
1578
- };
1566
+ type OrgController = {
1567
+ add: RequestHandler;
1568
+ addOnboardingOrg: RequestHandler;
1569
+ getAll: RequestHandler;
1570
+ getOrgsByUserId: RequestHandler;
1571
+ getByName: RequestHandler;
1572
+ getById: RequestHandler;
1573
+ getByEmail: RequestHandler;
1574
+ update: RequestHandler;
1575
+ getOrgsByEmail: RequestHandler;
1576
+ getAdminOrgForResident: RequestHandler;
1577
+ updateStatus: RequestHandler;
1578
+ updateModules: RequestHandler;
1579
+ previewOrgModules: RequestHandler;
1580
+ repairOwnerMembership: RequestHandler;
1581
+ };
1582
+ declare function useOrgController(): OrgController;
1579
1583
 
1580
1584
  /**
1581
1585
  * V2 organization HTTP surface — new handlers; v1 `useOrgController` remains unchanged.
@@ -3163,19 +3167,20 @@ declare function siteModulesHandlers({ requireSiteWrite, _getSiteById, _getOrgBy
3163
3167
  updateSiteModules: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3164
3168
  previewSiteModules: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3165
3169
  };
3166
- declare function useSiteController(): {
3167
- createSite: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3168
- getSites: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3169
- getSiteById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3170
- updateSiteBlock: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3171
- deleteSite: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3172
- updateById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3173
- updateSiteModules: (req: Request<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction) => Promise<void>;
3174
- previewSiteModules: (req: Request<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction) => Promise<void>;
3175
- updateGuardPostsById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3176
- siteInformation: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3177
- getAllSitesForResidentCreation: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3178
- };
3170
+ type SiteController = {
3171
+ createSite: RequestHandler;
3172
+ getSites: RequestHandler;
3173
+ getSiteById: RequestHandler;
3174
+ updateSiteBlock: RequestHandler;
3175
+ deleteSite: RequestHandler;
3176
+ updateById: RequestHandler;
3177
+ updateSiteModules: RequestHandler;
3178
+ previewSiteModules: RequestHandler;
3179
+ updateGuardPostsById: RequestHandler;
3180
+ siteInformation: RequestHandler;
3181
+ getAllSitesForResidentCreation: RequestHandler;
3182
+ };
3183
+ declare function useSiteController(): SiteController;
3179
3184
 
3180
3185
  type TChat = {
3181
3186
  _id?: ObjectId;
@@ -11161,6 +11166,8 @@ type TVerificationMetadataV2 = {
11161
11166
  invitedByName?: string;
11162
11167
  /** True when the sender was a property management company — those need approval. */
11163
11168
  invitedByPropertyManagement?: boolean;
11169
+ /** A new client's modules, chosen by Seven365 on Invite Client. */
11170
+ modules?: string[];
11164
11171
  };
11165
11172
  /**
11166
11173
  * The one-time code an invitee types to prove they own the mailbox, held on the
package/dist/index.js CHANGED
@@ -11268,9 +11268,6 @@ var import_node_server_utils45 = require("@7365admin1/node-server-utils");
11268
11268
  // src/services/verification.service.ts
11269
11269
  var import_node_server_utils41 = require("@7365admin1/node-server-utils");
11270
11270
 
11271
- // src/repositories/verification.repo.ts
11272
- var import_node_server_utils19 = require("@7365admin1/node-server-utils");
11273
-
11274
11271
  // src/models/verification.model.ts
11275
11272
  var import_node_server_utils18 = require("@7365admin1/node-server-utils");
11276
11273
  var import_mongodb16 = require("mongodb");
@@ -11319,6 +11316,7 @@ var MVerification = class {
11319
11316
  };
11320
11317
 
11321
11318
  // src/repositories/verification.repo.ts
11319
+ var import_node_server_utils19 = require("@7365admin1/node-server-utils");
11322
11320
  var import_mongodb17 = require("mongodb");
11323
11321
  function useVerificationRepo() {
11324
11322
  const db2 = import_node_server_utils19.useAtlas.getDb();
@@ -11548,6 +11546,28 @@ function useVerificationRepo() {
11548
11546
  throw new import_node_server_utils19.InternalServerError("Error updating verification status.");
11549
11547
  }
11550
11548
  }
11549
+ async function reissuePendingById(_id, { metadata, expireAt }) {
11550
+ try {
11551
+ _id = new import_mongodb17.ObjectId(_id);
11552
+ } catch (error) {
11553
+ throw new import_node_server_utils19.BadRequestError("Invalid verification ID format.");
11554
+ }
11555
+ try {
11556
+ const result = await collection.updateOne(
11557
+ { _id, status: "pending" },
11558
+ { $set: { metadata, expireAt, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } }
11559
+ );
11560
+ delNamespace().catch(
11561
+ (err) => import_node_server_utils19.logger.error(`Failed to clear cache for namespace: ${namespace_collection3}`, err)
11562
+ );
11563
+ delCache((0, import_node_server_utils19.makeCacheKey)(namespace_collection3, { _id })).catch(
11564
+ (err) => import_node_server_utils19.logger.error(`Failed to delete cache for verification ${_id}`, err)
11565
+ );
11566
+ return result.modifiedCount;
11567
+ } catch (error) {
11568
+ throw new import_node_server_utils19.InternalServerError("Error re-sending the invitation.");
11569
+ }
11570
+ }
11551
11571
  async function getByStatus(status) {
11552
11572
  try {
11553
11573
  const data = await collection.find({ status }).toArray();
@@ -11617,6 +11637,7 @@ function useVerificationRepo() {
11617
11637
  getVerifications,
11618
11638
  getByIdByType,
11619
11639
  updateStatusById,
11640
+ reissuePendingById,
11620
11641
  getByStatus,
11621
11642
  findOne,
11622
11643
  completePendingInvites
@@ -17606,7 +17627,8 @@ function useVerificationService() {
17606
17627
  add,
17607
17628
  getById: _getById,
17608
17629
  updateStatusById: _updateStatusById,
17609
- getByStatus: _getByStatus
17630
+ getByStatus: _getByStatus,
17631
+ reissuePendingById
17610
17632
  } = useVerificationRepo();
17611
17633
  const { getUserByEmail } = useUserRepo();
17612
17634
  const { getById: getOrgById, getByEmail: getOrgByEmail } = useOrgRepo();
@@ -17681,13 +17703,6 @@ function useVerificationService() {
17681
17703
  }
17682
17704
  const verificationIds = [];
17683
17705
  for (const app of apps) {
17684
- await useVerificationRepo().findOne({
17685
- type,
17686
- email,
17687
- "metadata.app": app,
17688
- "metadata.org": metadata.org,
17689
- "metadata.siteId": metadata.siteId
17690
- });
17691
17706
  const value = {
17692
17707
  type,
17693
17708
  email,
@@ -17698,7 +17713,24 @@ function useVerificationService() {
17698
17713
  expireAt: new Date(Date.now() + 72 * 60 * 60 * 1e3).toISOString(),
17699
17714
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
17700
17715
  };
17701
- const createdId = await add(value);
17716
+ const stored = new MVerification({
17717
+ ...value,
17718
+ metadata: { ...value.metadata }
17719
+ }).metadata;
17720
+ const pending = await useVerificationRepo().findOne({
17721
+ type,
17722
+ // same address in any letter case, as `completePendingInvites` reads it
17723
+ email: new RegExp(`^${email.replace(/[.*+?^$()|[\]{}\\]/g, "\\$&")}$`, "i"),
17724
+ status: "pending",
17725
+ "metadata.app": app,
17726
+ "metadata.org": stored.org,
17727
+ "metadata.siteId": stored.siteId
17728
+ });
17729
+ const reissued = pending?._id && await reissuePendingById(pending._id, {
17730
+ metadata: stored,
17731
+ expireAt: value.expireAt
17732
+ });
17733
+ const createdId = reissued ? pending._id : await add(value);
17702
17734
  verificationIds.push(createdId.toString());
17703
17735
  const link = `${APP_MAIN}/verify/invitation/${createdId}`;
17704
17736
  const emailContent = (0, import_node_server_utils41.compileHandlebar)({
@@ -29782,6 +29814,7 @@ function useMemberController() {
29782
29814
  // src/controllers/verification.controller.ts
29783
29815
  var import_node_server_utils66 = require("@7365admin1/node-server-utils");
29784
29816
  var import_joi28 = __toESM(require("joi"));
29817
+ var withoutEmail = (payload) => JSON.stringify({ ...payload, email: payload?.email ? "[redacted]" : void 0 });
29785
29818
  function callerId2(req) {
29786
29819
  const user = req.user;
29787
29820
  return user?.user?.toString?.() || user?._id?.toString?.();
@@ -29848,7 +29881,7 @@ function useVerificationController() {
29848
29881
  const payload = { ...req.body };
29849
29882
  import_node_server_utils66.logger.log({
29850
29883
  level: "info",
29851
- message: `[invite/user] payload: ${JSON.stringify(payload)}`
29884
+ message: `[invite/user] payload: ${withoutEmail(payload)}`
29852
29885
  });
29853
29886
  const validation = import_joi28.default.object({
29854
29887
  email: import_joi28.default.string().email().required(),
@@ -29857,7 +29890,9 @@ function useVerificationController() {
29857
29890
  name: import_joi28.default.string().optional().allow("", null),
29858
29891
  org: import_joi28.default.string().hex().optional().allow("", null),
29859
29892
  siteId: import_joi28.default.string().hex().optional().allow("", null),
29860
- siteName: import_joi28.default.string().optional().allow("", null)
29893
+ siteName: import_joi28.default.string().optional().allow("", null),
29894
+ // The modules Seven365 gives a NEW client (the console's Invite Client).
29895
+ modules: modulesSchema.optional()
29861
29896
  });
29862
29897
  const { error, value } = validation.validate(payload);
29863
29898
  if (error) {
@@ -29872,12 +29907,24 @@ function useVerificationController() {
29872
29907
  const {
29873
29908
  email,
29874
29909
  app,
29875
- role,
29876
29910
  name,
29877
29911
  org,
29878
29912
  siteId,
29879
- siteName
29913
+ siteName,
29914
+ modules
29880
29915
  } = value;
29916
+ const newClient = !org && !app.includes(PLATFORM_STAFF_MEMBER_TYPE);
29917
+ const role = newClient ? "" : value.role;
29918
+ let clientModules;
29919
+ if (modules !== void 0) {
29920
+ const invitedBy = await requireConsolePermission(req, "organizations");
29921
+ if (!newClient || app.length !== 1) {
29922
+ throw new import_node_server_utils66.BadRequestError(
29923
+ "Modules can only be chosen when inviting a new client, one application at a time."
29924
+ );
29925
+ }
29926
+ clientModules = { modules: normaliseModules(modules), invitedBy };
29927
+ }
29881
29928
  await requireInviteReach(req, org, app, role);
29882
29929
  const verificationIds = await _createSimpleUserInvite({
29883
29930
  email,
@@ -29887,7 +29934,8 @@ function useVerificationController() {
29887
29934
  name,
29888
29935
  org,
29889
29936
  siteId,
29890
- siteName
29937
+ siteName,
29938
+ ...clientModules
29891
29939
  }
29892
29940
  });
29893
29941
  const responseBody = {
@@ -29904,7 +29952,7 @@ function useVerificationController() {
29904
29952
  } catch (error2) {
29905
29953
  import_node_server_utils66.logger.log({
29906
29954
  level: "error",
29907
- message: `[invite/user] error for payload ${JSON.stringify(payload)}: ${error2.message}`
29955
+ message: `[invite/user] error for payload ${withoutEmail(payload)}: ${error2.message}`
29908
29956
  });
29909
29957
  next(error2);
29910
29958
  return;
@@ -29914,7 +29962,7 @@ function useVerificationController() {
29914
29962
  const payload = { ...req.body };
29915
29963
  import_node_server_utils66.logger.log({
29916
29964
  level: "info",
29917
- message: `[invite/member] payload: ${JSON.stringify(payload)}`
29965
+ message: `[invite/member] payload: ${withoutEmail(payload)}`
29918
29966
  });
29919
29967
  const validation = import_joi28.default.object({
29920
29968
  email: import_joi28.default.string().email().required(),
@@ -29966,7 +30014,7 @@ function useVerificationController() {
29966
30014
  } catch (error2) {
29967
30015
  import_node_server_utils66.logger.log({
29968
30016
  level: "error",
29969
- message: `[invite/member] error for payload ${JSON.stringify(payload)}: ${error2.message}`
30017
+ message: `[invite/member] error for payload ${withoutEmail(payload)}: ${error2.message}`
29970
30018
  });
29971
30019
  next(error2);
29972
30020
  return;
@@ -29976,7 +30024,7 @@ function useVerificationController() {
29976
30024
  const payload = req.body;
29977
30025
  import_node_server_utils66.logger.log({
29978
30026
  level: "info",
29979
- message: `[service-providers/invite] payload: ${JSON.stringify(payload)}`
30027
+ message: `[service-providers/invite] payload: ${withoutEmail(payload)}`
29980
30028
  });
29981
30029
  const validation = import_joi28.default.object({
29982
30030
  email: import_joi28.default.string().email().required(),
@@ -30033,7 +30081,7 @@ function useVerificationController() {
30033
30081
  } catch (error2) {
30034
30082
  import_node_server_utils66.logger.log({
30035
30083
  level: "error",
30036
- message: `[service-providers/invite] error for payload ${JSON.stringify(payload)}: ${error2.message}`
30084
+ message: `[service-providers/invite] error for payload ${withoutEmail(payload)}: ${error2.message}`
30037
30085
  });
30038
30086
  next(error2);
30039
30087
  return;
@@ -31675,6 +31723,7 @@ function useOrgController() {
31675
31723
  let invitedFrom = null;
31676
31724
  let invitedRole = null;
31677
31725
  let inviteAlreadyComplete = false;
31726
+ let invitedModules = null;
31678
31727
  let self = null;
31679
31728
  if (inviteId) {
31680
31729
  const [invite, caller] = await Promise.all([
@@ -31687,6 +31736,11 @@ function useOrgController() {
31687
31736
  invitedFrom = String(invite._id);
31688
31737
  invitedRole = invite.metadata?.role ? String(invite.metadata.role) : null;
31689
31738
  inviteAlreadyComplete = invite.status === "complete" /* COMPLETE */;
31739
+ const chosen = normaliseModules(invite.metadata?.modules);
31740
+ const invitedBy = invite.metadata?.invitedBy;
31741
+ if (chosen.length && invitedBy && invite.metadata?.app === body.nature) {
31742
+ invitedModules = { modules: chosen, invitedBy: String(invitedBy) };
31743
+ }
31690
31744
  } else {
31691
31745
  import_node_server_utils71.logger.log({
31692
31746
  level: "warn",
@@ -31702,7 +31756,29 @@ function useOrgController() {
31702
31756
  );
31703
31757
  }
31704
31758
  }
31705
- const _id = await _add({ ...body, createdBy, invitedFrom, invitedRole });
31759
+ const _id = await _add({
31760
+ ...body,
31761
+ createdBy,
31762
+ invitedFrom,
31763
+ invitedRole,
31764
+ ...invitedModules && { modules: invitedModules.modules }
31765
+ });
31766
+ if (invitedModules) {
31767
+ await recordConsoleAction({
31768
+ action: "client.modules-changed" /* CLIENT_MODULES_CHANGED */,
31769
+ actor: invitedModules.invitedBy,
31770
+ org: String(_id),
31771
+ target: String(_id).toLowerCase(),
31772
+ targetType: "organization" /* ORGANIZATION */,
31773
+ after: pickAuditFields("client.modules-changed" /* CLIENT_MODULES_CHANGED */, {
31774
+ modules: invitedModules.modules.join(", "),
31775
+ moduleCount: invitedModules.modules.length,
31776
+ gateListHash: moduleListHash(invitedModules.modules),
31777
+ acknowledged: false,
31778
+ impactMemberCount: 0
31779
+ })
31780
+ });
31781
+ }
31706
31782
  if (invitedFrom && !inviteAlreadyComplete) {
31707
31783
  try {
31708
31784
  await useVerificationRepoV2().updateStatusById(