@7365admin1/core 3.72.1-staging.319 → 3.72.1-staging.321

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.
@@ -0,0 +1,5 @@
1
+ ---
2
+ "@7365admin1/core": minor
3
+ ---
4
+
5
+ Invite Client for a Property Management or real estate developer client can carry the Service365 resident app modules; onboarding writes them on the organisation
@@ -0,0 +1,5 @@
1
+ ---
2
+ "@7365admin1/core": patch
3
+ ---
4
+
5
+ Enforce the reach check on `POST /api/people` by default: a signed-in caller can only create a person at a site (or organisation) they belong to or serve. `PEOPLE_CREATE_REACH_MODE=log` switches back to counting without refusing.
package/dist/index.d.ts CHANGED
@@ -11378,6 +11378,8 @@ type TVerificationMetadataV2 = {
11378
11378
  modules?: string[];
11379
11379
  /** The new client owner's permissions in that application, chosen with the modules. */
11380
11380
  permissions?: string[];
11381
+ /** A Property Management client's Service365 resident app switches, chosen with the modules. */
11382
+ residentAppModules?: Record<string, boolean>;
11381
11383
  };
11382
11384
  /**
11383
11385
  * The one-time code an invitee types to prove they own the mailbox, held on the
package/dist/index.js CHANGED
@@ -24452,6 +24452,44 @@ function useMemberController() {
24452
24452
  // src/controllers/verification.controller.ts
24453
24453
  var import_node_server_utils67 = require("@7365admin1/node-server-utils");
24454
24454
  var import_joi28 = __toESM(require("joi"));
24455
+
24456
+ // src/utils/resident-app-modules.util.ts
24457
+ var RESIDENT_APP_NATURES = Object.freeze([
24458
+ "property_management_agency",
24459
+ "real_estate_developer"
24460
+ ]);
24461
+ function effectiveResidentAppModules(orgModules, siteModules) {
24462
+ const org = asModules(orgModules);
24463
+ const site = asModules(siteModules);
24464
+ const effective = {};
24465
+ for (const key of residentAppModuleKeys) {
24466
+ effective[key] = org[key] !== false && site[key] !== false;
24467
+ }
24468
+ return effective;
24469
+ }
24470
+ function residentAppModulesAboveCeiling(orgModules, requested, stored) {
24471
+ const org = asModules(orgModules);
24472
+ const wanted = asModules(requested);
24473
+ const had = asModules(stored);
24474
+ return residentAppModuleKeys.filter(
24475
+ (key) => org[key] === false && wanted[key] === true && had[key] === false
24476
+ );
24477
+ }
24478
+ function residentAppModulesAboveCeilingMessage(rejected) {
24479
+ return `This client has not been given ${rejected.join(", ")} in the resident app, so a site cannot switch it on. Ask Seven365 to add it to the organisation first.`;
24480
+ }
24481
+ function withoutDerivedSiteMetadata(metadata) {
24482
+ if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
24483
+ return metadata;
24484
+ }
24485
+ const { residentAppModulesEffective: _derived, ...stored } = metadata;
24486
+ return stored;
24487
+ }
24488
+ function asModules(value) {
24489
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
24490
+ }
24491
+
24492
+ // src/controllers/verification.controller.ts
24455
24493
  var withoutEmail = (payload) => JSON.stringify({ ...payload, email: payload?.email ? "[redacted]" : void 0 });
24456
24494
  function callerId2(req) {
24457
24495
  const user = req.user;
@@ -24533,7 +24571,11 @@ function useVerificationController() {
24533
24571
  modules: modulesSchema.optional(),
24534
24572
  // The new client owner's permissions in that application, chosen with
24535
24573
  // the modules (owner, 2026-09-15). Only accepted together with modules.
24536
- permissions: permissionsSchema.optional()
24574
+ permissions: permissionsSchema.optional(),
24575
+ // The Service365 resident app switches for a Property Management (or
24576
+ // real estate developer) client, same shape the Client details card saves
24577
+ // to `organizations.residentAppModules`. Only accepted with modules.
24578
+ residentAppModules: residentAppModulesSchema.optional()
24537
24579
  });
24538
24580
  const { error, value } = validation.validate(payload);
24539
24581
  if (error) {
@@ -24553,7 +24595,8 @@ function useVerificationController() {
24553
24595
  siteId,
24554
24596
  siteName,
24555
24597
  modules,
24556
- permissions
24598
+ permissions,
24599
+ residentAppModules
24557
24600
  } = value;
24558
24601
  const newClient = !org && !app.includes(PLATFORM_STAFF_MEMBER_TYPE);
24559
24602
  const role = newClient ? "" : value.role;
@@ -24583,6 +24626,14 @@ function useVerificationController() {
24583
24626
  }
24584
24627
  clientModules.permissions = chosen;
24585
24628
  }
24629
+ if (residentAppModules !== void 0) {
24630
+ if (!clientModules || !RESIDENT_APP_NATURES.includes(app[0])) {
24631
+ throw new import_node_server_utils67.BadRequestError(
24632
+ "Service365 resident app modules can only be chosen with the modules of a new Property Management client."
24633
+ );
24634
+ }
24635
+ clientModules.residentAppModules = residentAppModules;
24636
+ }
24586
24637
  await requireInviteReach(req, org, app, role);
24587
24638
  const verificationIds = await _createSimpleUserInvite({
24588
24639
  email,
@@ -26399,10 +26450,12 @@ function useOrgController() {
26399
26450
  const invitedBy = invite.metadata?.invitedBy;
26400
26451
  if (chosen.length && invitedBy && invite.metadata?.app === body.nature) {
26401
26452
  const permissions = clientInviteOwnerPermissionsOn() ? normalisePermissions(invite.metadata?.permissions) : [];
26453
+ const residentApp = RESIDENT_APP_NATURES.includes(body.nature) ? residentAppModulesSchema.validate(invite.metadata?.residentAppModules) : null;
26402
26454
  invitedModules = {
26403
26455
  modules: chosen,
26404
26456
  invitedBy: String(invitedBy),
26405
- permissions: permissionsOutsideModules(permissions, chosen).length ? [] : permissions
26457
+ permissions: permissionsOutsideModules(permissions, chosen).length ? [] : permissions,
26458
+ ...residentApp?.value && !residentApp.error ? { residentAppModules: residentApp.value } : {}
26406
26459
  };
26407
26460
  }
26408
26461
  } else {
@@ -26425,7 +26478,10 @@ function useOrgController() {
26425
26478
  createdBy,
26426
26479
  invitedFrom,
26427
26480
  invitedRole,
26428
- ...invitedModules && { modules: invitedModules.modules }
26481
+ ...invitedModules && { modules: invitedModules.modules },
26482
+ ...invitedModules?.residentAppModules && {
26483
+ residentAppModules: invitedModules.residentAppModules
26484
+ }
26429
26485
  });
26430
26486
  if (invitedModules) {
26431
26487
  await recordConsoleAction({
@@ -26439,7 +26495,10 @@ function useOrgController() {
26439
26495
  moduleCount: invitedModules.modules.length,
26440
26496
  gateListHash: moduleListHash(invitedModules.modules),
26441
26497
  acknowledged: false,
26442
- impactMemberCount: 0
26498
+ impactMemberCount: 0,
26499
+ ...invitedModules.residentAppModules && {
26500
+ residentAppModulesOff: Object.keys(invitedModules.residentAppModules).filter((key) => invitedModules.residentAppModules[key] === false).join(", ")
26501
+ }
26443
26502
  })
26444
26503
  });
26445
26504
  }
@@ -35042,40 +35101,6 @@ function useSiteService() {
35042
35101
 
35043
35102
  // src/controllers/site.controller.ts
35044
35103
  var import_node_server_utils109 = require("@7365admin1/node-server-utils");
35045
-
35046
- // src/utils/resident-app-modules.util.ts
35047
- function effectiveResidentAppModules(orgModules, siteModules) {
35048
- const org = asModules(orgModules);
35049
- const site = asModules(siteModules);
35050
- const effective = {};
35051
- for (const key of residentAppModuleKeys) {
35052
- effective[key] = org[key] !== false && site[key] !== false;
35053
- }
35054
- return effective;
35055
- }
35056
- function residentAppModulesAboveCeiling(orgModules, requested, stored) {
35057
- const org = asModules(orgModules);
35058
- const wanted = asModules(requested);
35059
- const had = asModules(stored);
35060
- return residentAppModuleKeys.filter(
35061
- (key) => org[key] === false && wanted[key] === true && had[key] === false
35062
- );
35063
- }
35064
- function residentAppModulesAboveCeilingMessage(rejected) {
35065
- return `This client has not been given ${rejected.join(", ")} in the resident app, so a site cannot switch it on. Ask Seven365 to add it to the organisation first.`;
35066
- }
35067
- function withoutDerivedSiteMetadata(metadata) {
35068
- if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
35069
- return metadata;
35070
- }
35071
- const { residentAppModulesEffective: _derived, ...stored } = metadata;
35072
- return stored;
35073
- }
35074
- function asModules(value) {
35075
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
35076
- }
35077
-
35078
- // src/controllers/site.controller.ts
35079
35104
  var import_joi51 = __toESM(require("joi"));
35080
35105
  var import_mongodb74 = require("mongodb");
35081
35106
  async function requireSiteWrite(req, siteId) {
@@ -57210,7 +57235,7 @@ var import_node_server_utils149 = require("@7365admin1/node-server-utils");
57210
57235
  var import_node_server_utils150 = require("@7365admin1/node-server-utils");
57211
57236
 
57212
57237
  // src/utils/people-create-gate.util.ts
57213
- var PEOPLE_CREATE_REACH_MODE_DEFAULT = "log";
57238
+ var PEOPLE_CREATE_REACH_MODE_DEFAULT = "enforce";
57214
57239
  function peopleCreateReachMode(env2 = process.env) {
57215
57240
  return gateMode(
57216
57241
  env2.PEOPLE_CREATE_REACH_MODE,