@7365admin1/core 3.64.5 → 3.65.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/dist/index.d.ts CHANGED
@@ -3,6 +3,8 @@ import { ObjectId, ClientSession, Db, Collection, Document, AggregateOptions } f
3
3
  import Joi from 'joi';
4
4
  import { Request, Response, NextFunction } 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';
6
8
  import { z } from 'zod';
7
9
  import * as urllib from 'urllib';
8
10
  import { Server } from 'socket.io';
@@ -490,10 +492,474 @@ declare function useMemberRepo(): {
490
492
  }) => Promise<string[]>;
491
493
  };
492
494
 
495
+ /**
496
+ * THE SEVEN365 STAFF CONSOLE CATALOGUE, ON THE SERVER.
497
+ *
498
+ * `console-authz.util.ts` `requirePlatformStaff` answers ONE question — is this
499
+ * session a Seven365 staff membership — and twelve controllers ask it before
500
+ * every console write. It has never read which modules the staff role holds, so
501
+ * a staff account onboarded onto a role ticked for Promo Codes alone could still
502
+ * suspend a client, publish platform Terms, mint a subscription and read every
503
+ * user on the platform. The console's own guard
504
+ * (`web-app-org middleware/console-tier.global.ts` + `composables/useConsoleGate.ts`,
505
+ * shipped in org #186) hides those screens from that role, but hiding a screen
506
+ * is drawing, not securing: the endpoint behind it answered anybody with a staff
507
+ * session. This file is the server half.
508
+ *
509
+ * ## The catalogue is a MIRROR, and it is pinned as one
510
+ *
511
+ * The strings below are `web-app-org composables/useAdminPermission.ts` — the
512
+ * tick-boxes a `type: "admin"` role is actually built from — plus the two
513
+ * families that composable pulls out of layer-common's `useCommonPermissions`
514
+ * (`members`, `roles-and-permissions`). It is copied rather than imported
515
+ * because `core` is a backend package and cannot depend on a Nuxt layer; a
516
+ * server that invented its own vocabulary would be the
517
+ * `visitor:create`/`visitor-mgmt:add-visitor` split all over again — a string
518
+ * the server enforces that no role editor can grant.
519
+ *
520
+ * ## THE EMPTY-LIST RULE — why switching this on locks nobody out
521
+ *
522
+ * `user.service.ts createDefaultUser()` seeds the platform-staff role with
523
+ * `permissions: []`, NOT `["*"]`. A plain membership test over this catalogue
524
+ * would therefore refuse the Seven365 owner's own account on the day it shipped.
525
+ *
526
+ * So an EMPTY list means "everything", exactly as it does today, and `"*"` keeps
527
+ * the short-circuit it has everywhere else in the estate. Both spellings the
528
+ * staging owner role and the seeder can produce (`["*"]` and `[]`) allow all, so
529
+ * **no role, member or user document has to be written for this to ship** —
530
+ * which matters, because nothing in a repo may write one.
531
+ *
532
+ * The moment somebody ticks a module on a staff role, that role becomes
533
+ * governed at BOTH ends. That is the intended behaviour, and it is the one case
534
+ * to check before granting: a staff role that already holds a partial list is
535
+ * enforced immediately.
536
+ *
537
+ * ## WIDENING ONLY
538
+ *
539
+ * Every check here is layered ON TOP of the staff identity test, never in place
540
+ * of it — nobody who was refused before is admitted now. And the match accepts
541
+ * ANY shipped spelling of a grant, the rule
542
+ * `layer-common utils/permission-spellings.ts` already applies on the client:
543
+ * `-admin`'s role editor writes `roles-and-permissions:add-role` while eight
544
+ * apps write `roles:add-role`, and a role holding either must pass. Accepting
545
+ * both costs nothing and needs no role migration; picking one would silently
546
+ * un-grant every role holding the other.
547
+ */
548
+ /** Console resource -> the actions a staff role can be granted on it. */
549
+ declare const CONSOLE_PERMISSIONS: Readonly<Record<string, readonly string[]>>;
550
+ /** Every shipped spelling of `resource:action`. */
551
+ declare function consoleSpellings(resource: string, action: string): readonly string[];
552
+ /** True when this staff role is ungoverned and reaches the whole console. */
553
+ declare function consoleRoleAllowsAll(held?: readonly string[] | null): boolean;
554
+ /**
555
+ * May a staff role holding `held` take `action` on `resource`?
556
+ *
557
+ * Omit `action` to ask the SCREEN question — "does this role reach the resource
558
+ * at all" — which is `consoleCanSee` on the client: any single action on the
559
+ * resource is enough. Used where the catalogue has no string for the operation
560
+ * (creating a client organisation, writing a platform role/member row), because
561
+ * inventing a `create-organization` string here would be a grant no role editor
562
+ * anywhere can tick.
563
+ *
564
+ * An unknown resource, or an action the catalogue does not carry, is REFUSED for
565
+ * a governed role — the same answer `hasPermission` gives on the client, and the
566
+ * control the tests assert.
567
+ */
568
+ declare function consoleRoleAllows(held: readonly string[] | null | undefined, resource: string, action?: string): boolean;
569
+ /**
570
+ * THE CROSS-CLIENT GRANT — the one string that lets Seven365 staff out of
571
+ * tenant scoping.
572
+ *
573
+ * Every tenant-scoping helper in this package (`requireSiteReach`,
574
+ * `siteReachOf`, `entitledSites`, `requireOwnUnit`, `requireOrgReach`) opened
575
+ * with `if (actor.isSuperAdmin) return`. That is an IDENTITY test: it asks who
576
+ * the caller is and never asks what their staff role is ticked for. So a staff
577
+ * account onboarded onto a role holding Promo Codes alone still read and wrote
578
+ * every client's sites, people, files, documents, forms and facilities — the
579
+ * console gate shipped at revision 35 governs the console's OWN endpoints, and
580
+ * these are the tenant ones behind it.
581
+ *
582
+ * `organizations` is the catalogue string that already means "this staff role
583
+ * reaches across clients" (`CONSOLE_PERMISSIONS.organizations` =
584
+ * `see-all-organizations` / `see-organization-details`), and it is a tick-box
585
+ * the admin role editor can actually grant. No new vocabulary is invented — a
586
+ * string the server enforces that no editor can grant is the
587
+ * `visitor:create` mistake, and this deliberately avoids it. The SCREEN
588
+ * question is asked (no `action`), so either tick is enough.
589
+ */
590
+ declare const CROSS_CLIENT_GRANT: {
591
+ resource: string;
592
+ action?: string;
593
+ };
594
+ /**
595
+ * May this staff caller skip tenant scoping?
596
+ *
597
+ * **This never refuses anybody by itself.** It answers one question, and the
598
+ * caller falls through to the ORDINARY tenant scoping when the answer is no —
599
+ * so a staff member who is also a member of the target organisation, or who
600
+ * reaches the site through a live `customer.sites` engagement, is served
601
+ * exactly as they are today. The change is that platform identity alone stops
602
+ * being a skeleton key.
603
+ *
604
+ * ## ZERO LOCKOUT
605
+ *
606
+ * The rule is `consoleRoleAllows`, unchanged and already shipped: an EMPTY
607
+ * permission list means everything (that is what `createDefaultUser` seeds) and
608
+ * `"*"` means everything (that is what the live staff account holds). Both
609
+ * spellings a real staff role can carry today allow all, so no role, member or
610
+ * user document has to be written for this to ship and nobody loses access on
611
+ * deploy.
612
+ *
613
+ * The one population this governs is a staff role holding a NON-EMPTY PARTIAL
614
+ * list — which is the intended behaviour, and the same population revision 35
615
+ * already began governing on the console endpoints. Such a role keeps every
616
+ * client it holds a membership or engagement in; it loses only the reach it was
617
+ * never ticked for.
618
+ */
619
+ declare function staffMayBypass(actor: {
620
+ isSuperAdmin: boolean;
621
+ staffPermissions?: string[];
622
+ }, grant?: {
623
+ resource: string;
624
+ action?: string;
625
+ }): boolean;
626
+
627
+ /**
628
+ * ONE console module, optionally ONE action on it.
629
+ *
630
+ * `{ resource }` alone is the SCREEN question — "does this role reach the module
631
+ * at all" — which is `consoleCanSee` on the client. Used where the catalogue
632
+ * carries no string for the operation; see `console-permission.util.ts`.
633
+ */
634
+ type ConsoleGrant = {
635
+ resource: string;
636
+ action?: string;
637
+ };
638
+
639
+ /**
640
+ * Seven365 staff only, and — when a grant is named — staff whose role holds it.
641
+ *
642
+ * Returns the caller's id so a handler can attribute the write to them rather
643
+ * than to whatever the request body claimed.
644
+ *
645
+ * The `grant` argument is the whole of the console-permission change. Omitting
646
+ * it is exactly the behaviour this function has always had, so every call site
647
+ * that has not been mapped to a module is untouched rather than guessed at. A
648
+ * role with an EMPTY permission list — which is what `createDefaultUser` seeds —
649
+ * passes every grant, so naming one locks nobody out. See
650
+ * `console-permission.util.ts` for why that rule is what makes this shippable
651
+ * with no write to any role document.
652
+ */
653
+ declare function requirePlatformStaff(req: Request, grant?: ConsoleGrant): Promise<string>;
654
+ /**
655
+ * Seven365 staff who hold this console module.
656
+ *
657
+ * The name the controllers use. `requirePlatformStaff` still decides staff
658
+ * identity, unchanged — this is a layer ON TOP of it, never a replacement, so
659
+ * nobody who was refused before is admitted now.
660
+ */
661
+ declare function requireConsolePermission(req: Request, resource: string, action?: string): Promise<string>;
662
+ /**
663
+ * The person themselves, or Seven365 staff.
664
+ *
665
+ * A user record belongs to one person, so the id in the URL must be the
666
+ * caller's own — unless the caller is Seven365 staff, who run the client
667
+ * console. Used by both `/api/users` and its twin `/api/users/v2`, whose
668
+ * handlers are separate files with the same routes.
669
+ *
670
+ * `PATCH /api/users/field/:id` is why this exists: its allow-list includes
671
+ * `email`, `nric`, `status` and `defaultOrg`, so pointing it at somebody else's
672
+ * id rewrote their sign-in address — and the forgot-password flow then delivers
673
+ * to the new one.
674
+ */
675
+ declare function requireSelfOrPlatformStaff(req: Request, userId?: string | null, grant?: ConsoleGrant): Promise<string>;
676
+
677
+ /**
678
+ * What the Seven365 staff console records, as pure functions.
679
+ *
680
+ * Everything here is decidable without a database, a network or an Express
681
+ * request, which is the point: the rules that decide **what is allowed into an
682
+ * audit row** must be testable on their own. The row is written by
683
+ * `console-audit.repo.ts`; this file decides its shape and its contents.
684
+ *
685
+ * The one rule that governs the whole file: an audit row holds **who, what,
686
+ * which object, when, and enough of the values to make sense of the change**.
687
+ * It is not a copy of the document. Fields are admitted by an **allow-list per
688
+ * action** — anything not named there is dropped, so a handler that later
689
+ * passes a whole record cannot leak an email address, a phone number, a
690
+ * password hash or a token into the audit collection by accident.
691
+ */
692
+ /** The staff actions worth keeping a record of. */
693
+ declare enum ConsoleAuditAction {
694
+ SUBSCRIPTION_CREATED = "subscription.created",
695
+ SUBSCRIPTION_UPDATED = "subscription.updated",
696
+ CLIENT_CREATED = "client.created",
697
+ CLIENT_SUSPENDED = "client.suspended",
698
+ CLIENT_REACTIVATED = "client.reactivated",
699
+ /**
700
+ * Seven365 staff changing which catalogue modules a client is offered.
701
+ *
702
+ * Recorded because it is a commercial decision about a paying client that
703
+ * somebody has to be able to answer for later, even though it grants and
704
+ * revokes nothing by itself (`org-modules.util.ts` - it narrows what a role
705
+ * editor OFFERS, and the server re-decides every request regardless).
706
+ */
707
+ CLIENT_MODULES_CHANGED = "client.modules-changed",
708
+ /**
709
+ * A site's own module list changed (`PATCH /api/sites/:id/modules`).
710
+ *
711
+ * Like the camera rows below, this is a TENANT action: the organisation sets
712
+ * its site's list, not Seven365. It is here because the row is also the
713
+ * module gate's acknowledged-save marker (`gateListHash`, see
714
+ * `module-gate.util.ts enforcedModuleList`): a site list is enforced only
715
+ * once a save through the preview-and-acknowledge path has recorded it.
716
+ */
717
+ SITE_MODULES_CHANGED = "site.modules-changed",
718
+ PROMO_CODE_CREATED = "promo-code.created",
719
+ PROMO_CODE_UPDATED = "promo-code.updated",
720
+ PROMO_CODE_STATUS_CHANGED = "promo-code.status-changed",
721
+ PROMO_CODE_REMOVED = "promo-code.removed",
722
+ PLAN_CREATED = "plan.created",
723
+ PLAN_UPDATED = "plan.updated",
724
+ PLAN_STATUS_CHANGED = "plan.status-changed",
725
+ TERMS_PUBLISHED = "terms.published",
726
+ /**
727
+ * Seven365 staff switching a client's camera on or off.
728
+ *
729
+ * The only tenant-owned object on this list, and it is here because it is the
730
+ * only one staff may touch: a faulty camera at a client's site has to be
731
+ * switchable off by us. See `updateById` in `site-camera.controller.ts` for
732
+ * the boundary that allows it and nothing else.
733
+ */
734
+ CAMERA_STATUS_CHANGED = "camera.status-changed",
735
+ /**
736
+ * A camera being added, edited or removed BY THE SITE'S OWN PEOPLE.
737
+ *
738
+ * The three below are the answer to "who changed this camera's address, and
739
+ * when" - a question that had no answer anywhere in the system. A camera
740
+ * record carries `createdAt`/`updatedAt` and no actor, and a write overwrites
741
+ * the previous `host` in place, so a wrong port number could only be traced by
742
+ * asking people what they remembered doing. At Seventh Condominium that turned
743
+ * a one-line correction into nine days.
744
+ *
745
+ * This is a widening of what the collection holds: `CAMERA_STATUS_CHANGED` is
746
+ * a Seven365 STAFF action, and these are tenant actions. That is deliberate.
747
+ * The console is where an operator goes to answer exactly this question, the
748
+ * row already carries `actor`, `target` and `createdAt`, and the alternative -
749
+ * a second audit collection with its own repository, model and indexes - is
750
+ * more moving parts for the same row. Nothing existing changes: the collection
751
+ * is append-only and every reader filters by `action`.
752
+ */
753
+ CAMERA_ADDED = "camera.added",
754
+ CAMERA_UPDATED = "camera.updated",
755
+ CAMERA_REMOVED = "camera.removed"
756
+ }
757
+ /**
758
+ * The three actions that live in `organization.controller.ts`.
759
+ *
760
+ * They are defined, labelled and tested here, but **nothing calls them yet**.
761
+ * `organization.controller.ts` is being edited by open PR #1884 (suspend), and
762
+ * editing the same handlers here would hand a reviewer a merge conflict for no
763
+ * gain. Each needs exactly one `recordConsoleAction(...)` call once #1884
764
+ * lands; the action names and labels are already in place for it.
765
+ */
766
+ declare const CLIENT_ACTIONS: ConsoleAuditAction[];
767
+ /** What a person reads on the screen. The row carries it so the screen need not map it. */
768
+ declare const CONSOLE_AUDIT_LABELS: Record<ConsoleAuditAction, string>;
769
+ /** What kind of thing the action was done to. */
770
+ declare enum ConsoleAuditTarget {
771
+ ORGANIZATION = "organization",
772
+ SUBSCRIPTION = "subscription",
773
+ PROMO_CODE = "promo-code",
774
+ PLAN = "plan",
775
+ TERMS = "terms",
776
+ CAMERA = "camera",
777
+ SITE = "site"
778
+ }
779
+ /** A stored value is a primitive or it is not stored. */
780
+ declare const AUDIT_VALUE_MAX_LENGTH = 120;
781
+ /**
782
+ * The part of a change that may be stored, for this action.
783
+ *
784
+ * Returns `undefined` rather than `{}` when nothing survives, so an empty
785
+ * object never occupies a row and a reader can tell "nothing recorded" from
786
+ * "recorded as empty".
787
+ */
788
+ declare function pickAuditFields(action: ConsoleAuditAction, value?: Record<string, unknown> | null): Record<string, string | number | boolean> | undefined;
789
+
790
+ /**
791
+ * Every module key a list can deny: the keys the Seven365 console's module card
792
+ * can offer, minus `ALWAYS_ALLOWED`, plus the alias spellings in
793
+ * `SPELLING_GROUPS`.
794
+ *
795
+ * GENERATED 2026-09-11 from layer-common `origin/main` 5a96f95, not
796
+ * hand-written: bundled with esbuild, then
797
+ * union(Object.keys(PERMISSIONS) constants/permissions.ts,
798
+ * applicationModules().flatMap(a => a.modules) utils/module-applications.ts)
799
+ * which is `MODULE_KEYS` in web-app-org `pages/super-admin/client-details.vue`.
800
+ * Then added the alias resources of `LEGACY_PERMISSION_ALIASES` that are not
801
+ * already keys (`facility-booking`, `service-provider`, `work-orders`), and
802
+ * removed `ALWAYS_ALLOWED`.
803
+ *
804
+ * Deliberately NOT included: resource keys of catalogues the card cannot offer
805
+ * (`useAdminPermission`: `organizations`, `users`, `promo-codes`, …;
806
+ * `useRecapPermission`: `request`). A governed key the card cannot tick could
807
+ * never be allowed again once a client had a list.
808
+ *
809
+ * Regenerate when a composable gains a module; until then the new module is
810
+ * simply ungoverned, so it stays visible.
811
+ */
812
+ declare const GOVERNED_MODULES: readonly string[];
813
+ /** A list, cleaned and widened so every spelling of a listed module is in it. */
814
+ declare function expandModules(list: readonly unknown[] | null | undefined): string[];
815
+ /**
816
+ * The modules this caller's apps must hide, given the organisation's list and
817
+ * the site's list. `[]` means hide nothing.
818
+ *
819
+ * Both tiers are widened through the spelling groups BEFORE the existing
820
+ * `effectiveSiteModules` intersects them, so `workOrder` at one tier and
821
+ * `work_orders` at the other still meet.
822
+ */
823
+ declare function deniedModules(orgList: readonly unknown[] | null | undefined, siteList: readonly unknown[] | null | undefined): string[];
824
+ type TImpactMember = {
825
+ _id?: unknown;
826
+ name?: string;
827
+ type?: string;
828
+ role?: unknown;
829
+ };
830
+ type TImpactRole = {
831
+ _id?: unknown;
832
+ name?: string;
833
+ permissions?: unknown;
834
+ };
835
+ type TModuleImpactEntry = {
836
+ /** The module's first spelling in `SPELLING_GROUPS`, or the key itself. */
837
+ module: string;
838
+ /** Every newly denied spelling of it. */
839
+ spellings: string[];
840
+ memberCount: number;
841
+ members: Array<{
842
+ _id: string;
843
+ name: string;
844
+ }>;
845
+ roleCount: number;
846
+ roles: Array<{
847
+ _id: string;
848
+ name: string;
849
+ }>;
850
+ };
851
+ type TModuleImpact = {
852
+ /** Distinct members who lose at least one module. */
853
+ memberCount: number;
854
+ modules: TModuleImpactEntry[];
855
+ };
856
+ /**
857
+ * Who would lose what if the denied list went from `currentDenied` to
858
+ * `proposedDenied`: the preview that must come before any narrowing save.
859
+ *
860
+ * - A role holding `"*"` holds every module. So does an EMPTY role, which is the
861
+ * estate rule (`createDefaultUser` seeds `permissions: []`), so a preview
862
+ * over-counts rather than under-counts.
863
+ * - An enumerated role holds the resource half of each string, under any
864
+ * spelling. A string for an ungoverned resource never loses anything.
865
+ * - Residents are excluded: they hold no staff role. A member whose role is not
866
+ * in `rolesById` is skipped. Filter out inactive members before calling.
867
+ */
868
+ declare function moduleImpact({ currentDenied, proposedDenied, members, rolesById, }: {
869
+ currentDenied: readonly unknown[] | null | undefined;
870
+ proposedDenied: readonly unknown[] | null | undefined;
871
+ members: readonly TImpactMember[] | null | undefined;
872
+ rolesById: Record<string, TImpactRole | null | undefined> | null | undefined;
873
+ }): TModuleImpact;
874
+ /**
875
+ * THE ONE SWITCH (master plan rule 2). `MODULE_LIST_GATE=off` turns the whole
876
+ * gate off everywhere at once, with no app build: the `/modules` deny list that
877
+ * every web and mobile app ANDs, the Q7 notification filter and the Q3 server
878
+ * refusal all check this before computing anything, and answer "nothing
879
+ * denied".
880
+ *
881
+ * Read on every call rather than once at load, so a lead's emergency env
882
+ * override takes effect on restart. OUR flips change the code default below,
883
+ * by PR, staging first: setting an env on DigitalOcean is the leads' job.
884
+ */
885
+ declare const MODULE_LIST_GATE_DEFAULT = "on";
886
+ declare function moduleListGateOn(env?: Record<string, string | undefined>): boolean;
887
+ /** The latest console-audit row that saved a list: its `after` and `createdAt`. */
888
+ type TModuleListSave = {
889
+ after?: Record<string, unknown> | null;
890
+ createdAt?: string | null;
891
+ } | null | undefined;
892
+
893
+ /**
894
+ * THE MODULE GATE, READ FROM THE DATABASE.
895
+ *
896
+ * The pure rules live in `utils/module-gate.util.ts`. This file only fetches
897
+ * what they need: memberships, the organisation and the site, the latest
898
+ * console-audit save row (the acknowledged-save marker) and roles. Every read
899
+ * is a plain `find`/`findOne` or a cached repository getter. Nothing here
900
+ * writes, and roles are never read through `GET /api/roles`, whose heal path
901
+ * writes.
902
+ *
903
+ * Every lookup is injectable (`TModuleGateData`), so the rules are tested
904
+ * against the shipped code with no database.
905
+ */
906
+ type TRow = {
907
+ _id?: unknown;
908
+ user?: unknown;
909
+ org?: unknown;
910
+ siteId?: unknown;
911
+ type?: string;
912
+ status?: string;
913
+ deletedAt?: unknown;
914
+ role?: unknown;
915
+ name?: string;
916
+ };
917
+ type TOrgDoc = {
918
+ _id?: unknown;
919
+ modules?: unknown;
920
+ } | null;
921
+ type TSiteDoc = {
922
+ _id?: unknown;
923
+ orgId?: unknown;
924
+ metadata?: {
925
+ modules?: unknown;
926
+ } | null;
927
+ } | null;
928
+ type TRoleDoc = {
929
+ _id?: unknown;
930
+ name?: string;
931
+ permissions?: unknown;
932
+ };
933
+ type TModuleGateData = {
934
+ /** Every membership row of these users, any status. */
935
+ membershipsOf(userIds: string[]): Promise<TRow[]>;
936
+ org(id: string): Promise<TOrgDoc>;
937
+ site(id: string): Promise<TSiteDoc>;
938
+ /** The latest console-audit row saving this list. */
939
+ latestSave(action: ConsoleAuditAction, org: string, target: string): Promise<TModuleListSave>;
940
+ /** Seven365 staff whose console role may skip tenant scoping. */
941
+ isPlatformStaff(userId: string): Promise<boolean>;
942
+ /** Non-resident memberships in `org`; with `site`, those pinned there or org-wide. */
943
+ staffMembers(query: {
944
+ org: string;
945
+ site?: string;
946
+ }): Promise<TRow[]>;
947
+ roles(ids: string[]): Promise<Record<string, TRoleDoc>>;
948
+ };
949
+
950
+ /** Injected so a unit test runs the handler with no database. */
951
+ type TMemberModulesDeps = {
952
+ requireSelfOrPlatformStaff: typeof requireSelfOrPlatformStaff;
953
+ gateData?: TModuleGateData;
954
+ };
955
+ declare function memberModulesHandlers({ requireSelfOrPlatformStaff, gateData, }: TMemberModulesDeps): {
956
+ getModulesByUserIdType: (req: Request, res: Response, next: NextFunction) => Promise<void>;
957
+ };
493
958
  declare function useMemberController(): {
494
959
  createMember: (req: Request, res: Response, next: NextFunction) => Promise<void>;
495
960
  getByUserId: (req: Request, res: Response, next: NextFunction) => Promise<void>;
496
961
  getByUserIdType: (req: Request, res: Response, next: NextFunction) => Promise<void>;
962
+ 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>;
497
963
  getAll: (req: Request, res: Response, next: NextFunction) => Promise<void>;
498
964
  getAllByUser: (req: Request, res: Response, next: NextFunction) => Promise<void>;
499
965
  getOrgsByMembership: (req: Request, res: Response, next: NextFunction) => Promise<void>;
@@ -949,6 +1415,94 @@ declare function useOrgRepo(): {
949
1415
  completeOnboardingById: (_id: string | ObjectId, session?: ClientSession) => Promise<string>;
950
1416
  };
951
1417
 
1418
+ /**
1419
+ * One staff action in the Seven365 console.
1420
+ *
1421
+ * A new collection. Nothing existing is changed, no field is added to any live
1422
+ * document, and there is no migration — a client, a subscription, a promo code
1423
+ * and a plan are all exactly as they were.
1424
+ *
1425
+ * `actor` is a `users._id` and it comes from the SESSION, never from the
1426
+ * request body. The body-attribution defect fixed on `POST /api/terms` earlier
1427
+ * today is the reason that is written down rather than assumed.
1428
+ */
1429
+ type TConsoleAudit = {
1430
+ _id?: ObjectId;
1431
+ action: ConsoleAuditAction;
1432
+ /** Who. A `users._id`, resolved from the session. */
1433
+ actor: string | ObjectId;
1434
+ /** Which client it affected, when the action is about one. */
1435
+ org?: string | ObjectId | null;
1436
+ /** Which object changed, and of what kind. */
1437
+ target?: string | ObjectId | null;
1438
+ targetType?: ConsoleAuditTarget | null;
1439
+ /** Enough of the change to make sense of it — never a whole document. */
1440
+ before?: Record<string, unknown> | null;
1441
+ after?: Record<string, unknown> | null;
1442
+ /** ISO-8601 UTC, so a lexicographic range filter is also a date range filter. */
1443
+ createdAt?: string;
1444
+ };
1445
+ declare const schemaConsoleAudit: Joi.ObjectSchema<any>;
1446
+ declare function MConsoleAudit(value: TConsoleAudit): TConsoleAudit;
1447
+
1448
+ declare const console_audit_namespace_collection = "console-audit";
1449
+ type TConsoleAuditQuery = {
1450
+ org?: string;
1451
+ action?: string;
1452
+ /** ISO-8601. Inclusive at both ends of the day the caller names. */
1453
+ from?: string;
1454
+ to?: string;
1455
+ page?: number;
1456
+ limit?: number;
1457
+ };
1458
+ declare function useConsoleAuditRepo(): {
1459
+ createIndexes: () => Promise<void>;
1460
+ add: (value: TConsoleAudit) => Promise<{
1461
+ _id: ObjectId;
1462
+ action: ConsoleAuditAction;
1463
+ actor: string | ObjectId;
1464
+ org?: string | ObjectId | null | undefined;
1465
+ target?: string | ObjectId | null | undefined;
1466
+ targetType?: ConsoleAuditTarget | null | undefined;
1467
+ before?: Record<string, unknown> | null | undefined;
1468
+ after?: Record<string, unknown> | null | undefined;
1469
+ createdAt?: string | undefined;
1470
+ }>;
1471
+ list: (query: TConsoleAuditQuery) => Promise<{
1472
+ items: any[];
1473
+ pages: number;
1474
+ pageRange: string;
1475
+ }>;
1476
+ };
1477
+ /**
1478
+ * Record a staff action — and never, under any circumstance, break the action
1479
+ * it describes.
1480
+ *
1481
+ * Everything is inside the catch: resolving the database, validating the row
1482
+ * and the insert itself. The returned promise **cannot reject**, so a caller
1483
+ * that `await`s it cannot be thrown out of its own success path, and a caller
1484
+ * that forgets to `await` it cannot crash the process with an unhandled
1485
+ * rejection either. A failure is logged and the operation stands.
1486
+ *
1487
+ * Called only AFTER the operation it records has succeeded, so a row can never
1488
+ * describe something that did not happen. The other direction is possible and
1489
+ * accepted: an action can happen and its row fail to be written, in which case
1490
+ * the log carries it.
1491
+ */
1492
+ declare function recordConsoleAction(entry: TConsoleAudit): Promise<void>;
1493
+
1494
+ /** What the client module-list handlers read and write; injected so a unit test runs them with no database. */
1495
+ type TOrgModulesDeps = {
1496
+ requireConsolePermission: (req: Request, resource: string) => Promise<string>;
1497
+ _getById: (id: string) => Promise<any>;
1498
+ _update: (id: string, value: any) => Promise<unknown>;
1499
+ recordConsoleAction: (entry: Parameters<typeof recordConsoleAction>[0]) => Promise<unknown>;
1500
+ gateData?: TModuleGateData;
1501
+ };
1502
+ declare function orgModulesHandlers({ requireConsolePermission, _getById, _update, recordConsoleAction, gateData, }: TOrgModulesDeps): {
1503
+ updateModules: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1504
+ previewOrgModules: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1505
+ };
952
1506
  declare function useOrgController(): {
953
1507
  add: (req: Request, res: Response, next: NextFunction) => Promise<void>;
954
1508
  addOnboardingOrg: (req: Request, res: Response, next: NextFunction) => Promise<void>;
@@ -961,7 +1515,8 @@ declare function useOrgController(): {
961
1515
  getOrgsByEmail: (req: Request, res: Response, next: NextFunction) => Promise<void>;
962
1516
  getAdminOrgForResident: (_req: Request, res: Response, next: NextFunction) => Promise<void>;
963
1517
  updateStatus: (req: Request, res: Response, next: NextFunction) => Promise<void>;
964
- updateModules: (req: Request, res: Response, next: NextFunction) => Promise<void>;
1518
+ 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>;
1519
+ 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>;
965
1520
  };
966
1521
 
967
1522
  /**
@@ -2241,85 +2796,315 @@ declare function useCustomerController(): {
2241
2796
  deleteCustomer: (req: Request, res: Response, next: NextFunction) => Promise<void>;
2242
2797
  };
2243
2798
 
2244
- declare function useSiteRepo(): {
2245
- createIndexes: () => Promise<void>;
2246
- createSite: (value: TSite, session?: ClientSession) => Promise<ObjectId>;
2247
- getSites: ({ page, limit, search, sort, org, }: {
2248
- page?: number | undefined;
2249
- limit?: number | undefined;
2250
- search?: string | undefined;
2251
- sort?: Record<string, any> | undefined;
2252
- org: string | ObjectId;
2253
- }) => Promise<{}>;
2254
- getAllSites: ({ page, limit, }: {
2255
- page: number;
2256
- limit: number;
2257
- }) => Promise<{
2258
- items: {
2259
- _id: ObjectId;
2260
- name: string;
2261
- }[];
2262
- pages: number;
2263
- pageRange: string;
2264
- }>;
2265
- getSiteById: (_id: string | ObjectId) => Promise<TSite>;
2266
- updateSiteBlock: (_id: string | ObjectId, block: TSiteUpdateBlock) => Promise<number>;
2267
- deleteSite: (_id: string | ObjectId, session?: ClientSession) => Promise<number>;
2268
- updateById: ({ _id, field, value, type }?: {
2269
- _id: string | ObjectId;
2270
- field: string;
2271
- value: string | number | ObjectId;
2272
- type?: string | undefined;
2273
- }, session?: ClientSession) => Promise<string>;
2274
- getByName: (name?: string) => Promise<TSite[]>;
2275
- getByExactName: (name: string, orgId: string | ObjectId) => Promise<TSite[]>;
2276
- updateSiteIncidentCounter: (_id: string | ObjectId, incidentCounter: number, session?: ClientSession) => Promise<number>;
2277
- updateSiteById: (id: string | ObjectId, payload: TSite, session?: ClientSession) => Promise<number>;
2278
- getAllSitesUnpaginated: () => Promise<bson.Document[]>;
2279
- siteInformation: ({ id, payload, }: {
2280
- id: string;
2281
- payload: TSiteInformation;
2282
- }) => Promise<number>;
2283
- getAllSitesForResidentCreation: ({ search, page, limit, }: {
2284
- search: string;
2285
- page: number;
2286
- limit: number;
2287
- }) => Promise<{
2288
- items: {
2289
- _id: ObjectId;
2290
- name: string;
2291
- }[];
2292
- pages: number;
2293
- pageRange: string;
2294
- }>;
2799
+ declare function useSiteRepo(): {
2800
+ createIndexes: () => Promise<void>;
2801
+ createSite: (value: TSite, session?: ClientSession) => Promise<ObjectId>;
2802
+ getSites: ({ page, limit, search, sort, org, }: {
2803
+ page?: number | undefined;
2804
+ limit?: number | undefined;
2805
+ search?: string | undefined;
2806
+ sort?: Record<string, any> | undefined;
2807
+ org: string | ObjectId;
2808
+ }) => Promise<{}>;
2809
+ getAllSites: ({ page, limit, }: {
2810
+ page: number;
2811
+ limit: number;
2812
+ }) => Promise<{
2813
+ items: {
2814
+ _id: ObjectId;
2815
+ name: string;
2816
+ }[];
2817
+ pages: number;
2818
+ pageRange: string;
2819
+ }>;
2820
+ getSiteById: (_id: string | ObjectId) => Promise<TSite>;
2821
+ updateSiteBlock: (_id: string | ObjectId, block: TSiteUpdateBlock) => Promise<number>;
2822
+ deleteSite: (_id: string | ObjectId, session?: ClientSession) => Promise<number>;
2823
+ updateById: ({ _id, field, value, type }?: {
2824
+ _id: string | ObjectId;
2825
+ field: string;
2826
+ value: string | number | ObjectId;
2827
+ type?: string | undefined;
2828
+ }, session?: ClientSession) => Promise<string>;
2829
+ getByName: (name?: string) => Promise<TSite[]>;
2830
+ getByExactName: (name: string, orgId: string | ObjectId) => Promise<TSite[]>;
2831
+ updateSiteIncidentCounter: (_id: string | ObjectId, incidentCounter: number, session?: ClientSession) => Promise<number>;
2832
+ updateSiteById: (id: string | ObjectId, payload: TSite, session?: ClientSession) => Promise<number>;
2833
+ getAllSitesUnpaginated: () => Promise<bson.Document[]>;
2834
+ siteInformation: ({ id, payload, }: {
2835
+ id: string;
2836
+ payload: TSiteInformation;
2837
+ }) => Promise<number>;
2838
+ getAllSitesForResidentCreation: ({ search, page, limit, }: {
2839
+ search: string;
2840
+ page: number;
2841
+ limit: number;
2842
+ }) => Promise<{
2843
+ items: {
2844
+ _id: ObjectId;
2845
+ name: string;
2846
+ }[];
2847
+ pages: number;
2848
+ pageRange: string;
2849
+ }>;
2850
+ };
2851
+
2852
+ declare function useSiteService(): {
2853
+ createSite: (value: {
2854
+ orgId: string;
2855
+ name: string;
2856
+ description?: string | undefined;
2857
+ customerId: string;
2858
+ category: SiteCategories;
2859
+ address: {
2860
+ line1: string;
2861
+ line2?: string;
2862
+ city: string;
2863
+ state?: string;
2864
+ postalCode: string;
2865
+ country: string;
2866
+ };
2867
+ }) => Promise<{
2868
+ site: bson.ObjectId;
2869
+ }>;
2870
+ updateGuardPostById: (site: string, guardPost: number) => Promise<void>;
2871
+ updateById: (_id: string, payload: TSite) => Promise<void>;
2872
+ siteInformation: ({ id, payload }: {
2873
+ id: string;
2874
+ payload: TSiteInformation;
2875
+ }) => Promise<number>;
2876
+ };
2877
+
2878
+ /**
2879
+ * Who is asking, resolved from the session id alone.
2880
+ *
2881
+ * Every invitation action re-derives this — the caller never states who they
2882
+ * are in a body or a query field.
2883
+ *
2884
+ * **Super admin is a membership, not an email address.** `createDefaultUser()`
2885
+ * seeds a role named "Super Admin" with `type: "admin"` and a `members` row with
2886
+ * `type: "admin"` and NO organisation; the user behind it is whatever
2887
+ * `DEFAULT_USER_EMAIL` is set to in that environment (`admin@gmail.com` on
2888
+ * staging, something else in production). Gating on the email address would
2889
+ * therefore work on staging and fail in production, and would break the day the
2890
+ * account is rotated. Both halves are required — a `members` row of type
2891
+ * "admin" whose role is also of type "admin" — because staging carries a second
2892
+ * role merely NAMED "Super Admin" that is an ordinary organisation role.
2893
+ */
2894
+ type InviteActor = {
2895
+ id: string;
2896
+ name: string;
2897
+ isSuperAdmin: boolean;
2898
+ /** every organisation this user is a live member of */
2899
+ orgIds: string[];
2900
+ /** organisations this user represents as a property management company */
2901
+ propertyManagementOrgIds: string[];
2902
+ /**
2903
+ * Every live membership as an `(org, siteId)` pair, `siteId` empty when the
2904
+ * membership carries no site — i.e. when it is an org-wide role.
2905
+ *
2906
+ * `orgIds` above flattens this and throws the site away, which is right for
2907
+ * the organisation-level gates that read it. The LISTING paths need the site
2908
+ * back: `GET /api/customer-sites?org=` authorises at organisation level and
2909
+ * then returned the organisation's whole estate, so a user invited to one
2910
+ * site was offered every site in the client. See `orgSiteScope`.
2911
+ *
2912
+ * `orgLevelRole` is true when the membership's ROLE is organisation-level —
2913
+ * the `roles` document carries no `site` of its own. Owner decision of
2914
+ * 2026-09-02: an org-level role sees every site EVEN IF its membership row
2915
+ * also names one, so the stray `siteId` on an Org Owner row must not narrow
2916
+ * them. It fails closed: a missing, soft-deleted or unreadable role is not
2917
+ * org-level.
2918
+ */
2919
+ memberships: Array<{
2920
+ org: string;
2921
+ siteId: string;
2922
+ orgLevelRole: boolean;
2923
+ /** The membership's `type` (`resident`, `security_agency`, …); `""` when absent. */
2924
+ type?: string;
2925
+ }>;
2926
+ /**
2927
+ * The `permissions` array of the LIVE staff role behind `isSuperAdmin`, or
2928
+ * undefined when the caller is not Seven365 staff.
2929
+ *
2930
+ * The role document is already read two lines below to decide
2931
+ * `isSuperAdmin`; only its `permissions` field was being thrown away. Carrying
2932
+ * it costs no extra query and is what lets `staffMayBypass` ask the console
2933
+ * catalogue's question instead of identity alone. Undefined and `[]` are NOT
2934
+ * the same thing: `[]` is a staff role that holds everything (the empty-list
2935
+ * rule), undefined is somebody who is not staff at all.
2936
+ */
2937
+ staffPermissions?: string[];
2938
+ };
2939
+ declare function resolveInviteActor(userId?: string | ObjectId | null): Promise<InviteActor>;
2940
+ /**
2941
+ * Does this person hold an invitation naming this organisation?
2942
+ *
2943
+ * The org-scoping rule on roles and memberships is "Seven365 staff, or a live
2944
+ * member of this organisation" — but three live flows legitimately reach an
2945
+ * organisation the caller is **not yet** a member of, because joining it is the
2946
+ * whole point:
2947
+ *
2948
+ * - the service-provider signing in against a `service-provider-invite`
2949
+ * (`web-app-main pages/sign-in.vue:298,428`), who looks up that customer's
2950
+ * "Admin Service Provider" role and then enrols;
2951
+ * - the admin member finishing sign-up from a `member-invite`
2952
+ * (`web-app-main pages/verify/email/index.vue:462`);
2953
+ * - the client owner walking the onboarding wizard
2954
+ * (`web-app-org pages/onboarding/getting-started/index.vue`).
2955
+ *
2956
+ * All three are holding an invitation addressed to their OWN email whose
2957
+ * `metadata.org` is the organisation being reached, so that invitation is the
2958
+ * relationship the rule tests. Both string and ObjectId shapes are matched,
2959
+ * because `MVerification` casts `metadata.org` to an ObjectId while older rows
2960
+ * carry a string — the same pair `completePendingInvites` matches on.
2961
+ *
2962
+ * Any status counts: `completeOrgAdminAccount` marks the verification complete
2963
+ * before the member row is written, so a pending-only test would refuse the
2964
+ * flow it exists to protect.
2965
+ */
2966
+ declare function hasOrgInvitation(userId?: string | ObjectId | null, orgId?: string | ObjectId | null): Promise<boolean>;
2967
+ /**
2968
+ * Does one of this person's own invitations into this organisation OFFER this
2969
+ * role?
2970
+ *
2971
+ * `hasOrgInvitation` answers "may you reach the organisation"; this answers
2972
+ * "may you wear THIS role there". An invitation that names a role offers that
2973
+ * role and nothing else. An invitation that names NO role — the
2974
+ * service-provider invite, whose sign-in then finds or creates the org's
2975
+ * "Admin Service Provider" role (`web-app-main pages/sign-in.vue`) — offers a
2976
+ * role of this organisation whose `type` is the invitation's own `app`, which
2977
+ * is exactly what that flow can pick.
2978
+ *
2979
+ * A `cancelled` invitation offers nothing: the organisation took it back. Any
2980
+ * other status counts, for the reason `hasOrgInvitation` gives (the member row
2981
+ * is written after the invitation is marked complete).
2982
+ */
2983
+ declare function invitationOffersRole(userId?: string | ObjectId | null, orgId?: string | ObjectId | null, roleId?: string | ObjectId | null): Promise<boolean>;
2984
+ /**
2985
+ * Which of these role ids are ORGANISATION-level, i.e. the `roles` document
2986
+ * carries no `site` of its own. One batched lookup, `site` the only field it
2987
+ * needs.
2988
+ *
2989
+ * Fails closed: a role that is missing, soft-deleted or unreadable is absent
2990
+ * from the set and therefore reads as SITE-level — the narrowing side, which is
2991
+ * the safe way to be wrong about a rule that widens access.
2992
+ *
2993
+ * Shared by `resolveInviteActor` (the site LIST half, `orgSiteScope`) and by
2994
+ * `resolveSiteAccess` in the camera service (the ACCESS half, `cameraGrant`),
2995
+ * because the two must answer "is this an org-level role?" identically or the
2996
+ * switcher offers sites the camera view refuses.
2997
+ */
2998
+ declare function orgLevelRoles(db: Db, roles: Array<unknown>): Promise<Set<string>>;
2999
+ /**
3000
+ * Does this person OWN this organisation — did they create it, or is it
3001
+ * registered under their own account e-mail?
3002
+ *
3003
+ * DV-0248. The client owner who signs themselves up creates the organisation
3004
+ * (`POST /api/organizations/onboarding`) and only gets their `members` row at
3005
+ * the LAST onboarding step, from `ensureCurrentUserMemberExists`. Every step in
3006
+ * between — save the org details, create the first site, create the roles,
3007
+ * invite the admins — asked for a membership or an invitation, and the owner
3008
+ * has neither. So the wizard refused its own owner at step 1, and the
3009
+ * organisation never appeared in their list either. On staging, 64 of 195
3010
+ * organisations have no member and no invitation at all.
3011
+ *
3012
+ * Two roads, because the second repairs the ones already stuck:
3013
+ *
3014
+ * - `createdBy` — stamped from the session when the organisation is created,
3015
+ * never from the request body. Fixes every NEW signup, and is the road that
3016
+ * would have been enough on its own if the field had always existed.
3017
+ * - `email` — the organisation is registered under the caller's own account
3018
+ * address. This is the SAME comparison `organization.repo getAll` already
3019
+ * makes to scope the client list, against the same session-resolved address,
3020
+ * and it is what lets the 64 existing organisations repair themselves with no
3021
+ * data backfill.
3022
+ *
3023
+ * The e-mail road is only sound because `PATCH /api/users/field/:id` no longer
3024
+ * lets a user set their own address (`requireUserFieldWrite`). While it did,
3025
+ * anyone could have typed a victim organisation's address and walked in; that
3026
+ * hole is closed in the same change, and re-opening it re-opens this.
3027
+ *
3028
+ * Case-insensitive by collation rather than `$regex`, for the reason
3029
+ * `hasOrgInvitation` gives: an address may contain `+` or `.` and building a
3030
+ * pattern out of one invites an escaping bug.
3031
+ */
3032
+ declare function hasOrgOwnership(userId?: string | ObjectId | null, orgId?: string | ObjectId | null): Promise<boolean>;
3033
+ /**
3034
+ * Has this account been APPROVED? `isAccountLive` (blank = an older live
3035
+ * account) minus `resubmit`: a resident applicant asked to resubmit can sign
3036
+ * in, and self-signup already gave them an active resident `members` row and
3037
+ * the site they applied for, but the client has not accepted them.
3038
+ */
3039
+ declare function readsAsApprovedAccount(status?: string | null): boolean;
3040
+ /** `readsAsApprovedAccount` for a user id. Fails closed: unreadable is "no". */
3041
+ declare function callerAccountApproved(userId?: string | ObjectId | null): Promise<boolean>;
3042
+ /**
3043
+ * Does this person LIVE at, or WORK on, one of this organisation's sites?
3044
+ *
3045
+ * The two relationships `requireOrgReach` does not see, because neither is a
3046
+ * membership OF this organisation:
3047
+ *
3048
+ * - **a resident** (`residents-are-not-members`): the Service365 app reads its
3049
+ * own client's record (`residentAppModules`, `defaultSite`) and a resident's
3050
+ * tie to the estate lives on the `users` document (`site`, `unitId`) or a
3051
+ * `site.people` row, not in `members`. Every one of those is server-written,
3052
+ * but a self-signup stores the site and unit it APPLIED for, and a rejected
3053
+ * or resubmit applicant can still sign in. So these roads count only for an
3054
+ * approved account (`readsAsApprovedAccount`), and only an
3055
+ * `active`/`approved` `site.people` row. `PATCH
3056
+ * /api/users/field` does not accept `site` or `unitId`. The organisation's
3057
+ * `defaultSite` being the resident's own site counts too — it is exactly the
3058
+ * fallback the app itself uses.
3059
+ * - **a service provider** engaged by this client: an active `customer.sites`
3060
+ * row between one of the caller's organisations and this one
3061
+ * (`customer-sites-row-is-the-engagement`).
3062
+ *
3063
+ * `memberOrgIds` is the caller's own organisations, already resolved by the
3064
+ * caller of this function. Fails closed: anything unreadable is "no".
3065
+ */
3066
+ declare function hasOrgSiteReach(userId?: string | ObjectId | null, orgId?: string | ObjectId | null, memberOrgIds?: string[]): Promise<boolean>;
3067
+ /**
3068
+ * Does this person themselves HOLD this role?
3069
+ *
3070
+ * `GET /api/roles/id/:id` is read on the hot path by every signed-in session —
3071
+ * `layer-common plugins/secure-member.client.ts` resolves the caller's own app
3072
+ * role, and the guard app's `permission.store.ts` does the same — so the only
3073
+ * scoping rule that can go on it has to keep "my own role" working. Scoping it
3074
+ * by the role's organisation alone does not: staging carries 12 roles with NO
3075
+ * `org` at all, one of which ("Org Owner") is held by 119 ordinary tenant
3076
+ * members across eight membership types. An org-less role routes to the staff
3077
+ * gate, so those 119 accounts would 401 on their own role and both callers fail
3078
+ * closed — permissions silently emptying, with nothing in the product to say
3079
+ * why.
3080
+ *
3081
+ * The relationship is a live `members` row joining the caller's user id to this
3082
+ * exact role id. **Both halves are resolved server-side**: the user id comes
3083
+ * from the session (`callerId`), never from a body or a query field, and the
3084
+ * role id is the resource being asked for. There is nothing a caller can send
3085
+ * that makes this answer yes for a role they do not hold — naming somebody
3086
+ * else's role id simply finds no row.
3087
+ *
3088
+ * `status: { $ne: "deleted" }` is the same liveness test every other membership
3089
+ * read in this package uses, so a revoked membership stops conferring the read.
3090
+ */
3091
+ declare function holdsRole(userId?: string | ObjectId | null, roleId?: string | ObjectId | null,
3092
+ /** when given, the live membership must also be in THIS organisation */
3093
+ orgId?: string | ObjectId | null): Promise<boolean>;
3094
+
3095
+ /** What the site module-list handlers read and write; injected so a unit test runs them with no database. */
3096
+ type TSiteModulesDeps = {
3097
+ requireSiteWrite: (req: Request, siteId: string) => Promise<InviteActor>;
3098
+ _getSiteById: (id: string) => Promise<any>;
3099
+ _getOrgById: (id: string) => Promise<any>;
3100
+ _updateById: (id: string, value: any) => Promise<unknown>;
3101
+ recordConsoleAction: (entry: Parameters<typeof recordConsoleAction>[0]) => Promise<unknown>;
3102
+ gateData?: TModuleGateData;
2295
3103
  };
2296
-
2297
- declare function useSiteService(): {
2298
- createSite: (value: {
2299
- orgId: string;
2300
- name: string;
2301
- description?: string | undefined;
2302
- customerId: string;
2303
- category: SiteCategories;
2304
- address: {
2305
- line1: string;
2306
- line2?: string;
2307
- city: string;
2308
- state?: string;
2309
- postalCode: string;
2310
- country: string;
2311
- };
2312
- }) => Promise<{
2313
- site: bson.ObjectId;
2314
- }>;
2315
- updateGuardPostById: (site: string, guardPost: number) => Promise<void>;
2316
- updateById: (_id: string, payload: TSite) => Promise<void>;
2317
- siteInformation: ({ id, payload }: {
2318
- id: string;
2319
- payload: TSiteInformation;
2320
- }) => Promise<number>;
3104
+ declare function siteModulesHandlers({ requireSiteWrite, _getSiteById, _getOrgById, _updateById, recordConsoleAction, gateData, }: TSiteModulesDeps): {
3105
+ updateSiteModules: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3106
+ previewSiteModules: (req: Request, res: Response, next: NextFunction) => Promise<void>;
2321
3107
  };
2322
-
2323
3108
  declare function useSiteController(): {
2324
3109
  createSite: (req: Request, res: Response, next: NextFunction) => Promise<void>;
2325
3110
  getSites: (req: Request, res: Response, next: NextFunction) => Promise<void>;
@@ -2327,7 +3112,8 @@ declare function useSiteController(): {
2327
3112
  updateSiteBlock: (req: Request, res: Response, next: NextFunction) => Promise<void>;
2328
3113
  deleteSite: (req: Request, res: Response, next: NextFunction) => Promise<void>;
2329
3114
  updateById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
2330
- updateSiteModules: (req: Request, res: Response, next: NextFunction) => Promise<void>;
3115
+ 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>;
3116
+ 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>;
2331
3117
  updateGuardPostsById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
2332
3118
  siteInformation: (req: Request, res: Response, next: NextFunction) => Promise<void>;
2333
3119
  getAllSitesForResidentCreation: (req: Request, res: Response, next: NextFunction) => Promise<void>;
@@ -6756,7 +7542,7 @@ declare function useBulletinBoardRepo(): {
6756
7542
  site: string | ObjectId;
6757
7543
  status: string;
6758
7544
  recipients: Array<string>;
6759
- expiration?: "yes" | "no" | undefined;
7545
+ expiration?: "no" | "yes" | undefined;
6760
7546
  }, session?: ClientSession) => Promise<{
6761
7547
  items: any[];
6762
7548
  pages: number;
@@ -10822,187 +11608,25 @@ type TSelfServiceResendFacts = {
10822
11608
  now: number;
10823
11609
  };
10824
11610
  type TSelfServiceResendDecision = {
10825
- ok: true;
10826
- email: string;
10827
- persistEmail: boolean;
10828
- } | {
10829
- ok: false;
10830
- httpStatus: 400 | 404 | 429;
10831
- reason: string;
10832
- };
10833
- /**
10834
- * What the public resend route may do with an id.
10835
- *
10836
- * The rule that matters: an address ALREADY on the record wins, always. A
10837
- * caller can fill in a blank one - that is what the card's inline field is for,
10838
- * and it grants no more than the id already did, since the id alone opens the
10839
- * pass page - but it can never redirect a pass that is already addressed to
10840
- * someone. Without that, a harvested id would be a way to have another
10841
- * person's check-in QR mailed anywhere.
10842
- */
10843
- declare function decideSelfServiceResend(facts: TSelfServiceResendFacts): TSelfServiceResendDecision;
10844
-
10845
- /**
10846
- * Who is asking, resolved from the session id alone.
10847
- *
10848
- * Every invitation action re-derives this — the caller never states who they
10849
- * are in a body or a query field.
10850
- *
10851
- * **Super admin is a membership, not an email address.** `createDefaultUser()`
10852
- * seeds a role named "Super Admin" with `type: "admin"` and a `members` row with
10853
- * `type: "admin"` and NO organisation; the user behind it is whatever
10854
- * `DEFAULT_USER_EMAIL` is set to in that environment (`admin@gmail.com` on
10855
- * staging, something else in production). Gating on the email address would
10856
- * therefore work on staging and fail in production, and would break the day the
10857
- * account is rotated. Both halves are required — a `members` row of type
10858
- * "admin" whose role is also of type "admin" — because staging carries a second
10859
- * role merely NAMED "Super Admin" that is an ordinary organisation role.
10860
- */
10861
- type InviteActor = {
10862
- id: string;
10863
- name: string;
10864
- isSuperAdmin: boolean;
10865
- /** every organisation this user is a live member of */
10866
- orgIds: string[];
10867
- /** organisations this user represents as a property management company */
10868
- propertyManagementOrgIds: string[];
10869
- /**
10870
- * Every live membership as an `(org, siteId)` pair, `siteId` empty when the
10871
- * membership carries no site — i.e. when it is an org-wide role.
10872
- *
10873
- * `orgIds` above flattens this and throws the site away, which is right for
10874
- * the organisation-level gates that read it. The LISTING paths need the site
10875
- * back: `GET /api/customer-sites?org=` authorises at organisation level and
10876
- * then returned the organisation's whole estate, so a user invited to one
10877
- * site was offered every site in the client. See `orgSiteScope`.
10878
- *
10879
- * `orgLevelRole` is true when the membership's ROLE is organisation-level —
10880
- * the `roles` document carries no `site` of its own. Owner decision of
10881
- * 2026-09-02: an org-level role sees every site EVEN IF its membership row
10882
- * also names one, so the stray `siteId` on an Org Owner row must not narrow
10883
- * them. It fails closed: a missing, soft-deleted or unreadable role is not
10884
- * org-level.
10885
- */
10886
- memberships: Array<{
10887
- org: string;
10888
- siteId: string;
10889
- orgLevelRole: boolean;
10890
- }>;
10891
- /**
10892
- * The `permissions` array of the LIVE staff role behind `isSuperAdmin`, or
10893
- * undefined when the caller is not Seven365 staff.
10894
- *
10895
- * The role document is already read two lines below to decide
10896
- * `isSuperAdmin`; only its `permissions` field was being thrown away. Carrying
10897
- * it costs no extra query and is what lets `staffMayBypass` ask the console
10898
- * catalogue's question instead of identity alone. Undefined and `[]` are NOT
10899
- * the same thing: `[]` is a staff role that holds everything (the empty-list
10900
- * rule), undefined is somebody who is not staff at all.
10901
- */
10902
- staffPermissions?: string[];
10903
- };
10904
- declare function resolveInviteActor(userId?: string | ObjectId | null): Promise<InviteActor>;
10905
- /**
10906
- * Does this person hold an invitation naming this organisation?
10907
- *
10908
- * The org-scoping rule on roles and memberships is "Seven365 staff, or a live
10909
- * member of this organisation" — but three live flows legitimately reach an
10910
- * organisation the caller is **not yet** a member of, because joining it is the
10911
- * whole point:
10912
- *
10913
- * - the service-provider signing in against a `service-provider-invite`
10914
- * (`web-app-main pages/sign-in.vue:298,428`), who looks up that customer's
10915
- * "Admin Service Provider" role and then enrols;
10916
- * - the admin member finishing sign-up from a `member-invite`
10917
- * (`web-app-main pages/verify/email/index.vue:462`);
10918
- * - the client owner walking the onboarding wizard
10919
- * (`web-app-org pages/onboarding/getting-started/index.vue`).
10920
- *
10921
- * All three are holding an invitation addressed to their OWN email whose
10922
- * `metadata.org` is the organisation being reached, so that invitation is the
10923
- * relationship the rule tests. Both string and ObjectId shapes are matched,
10924
- * because `MVerification` casts `metadata.org` to an ObjectId while older rows
10925
- * carry a string — the same pair `completePendingInvites` matches on.
10926
- *
10927
- * Any status counts: `completeOrgAdminAccount` marks the verification complete
10928
- * before the member row is written, so a pending-only test would refuse the
10929
- * flow it exists to protect.
10930
- */
10931
- declare function hasOrgInvitation(userId?: string | ObjectId | null, orgId?: string | ObjectId | null): Promise<boolean>;
10932
- /**
10933
- * Which of these role ids are ORGANISATION-level, i.e. the `roles` document
10934
- * carries no `site` of its own. One batched lookup, `site` the only field it
10935
- * needs.
10936
- *
10937
- * Fails closed: a role that is missing, soft-deleted or unreadable is absent
10938
- * from the set and therefore reads as SITE-level — the narrowing side, which is
10939
- * the safe way to be wrong about a rule that widens access.
10940
- *
10941
- * Shared by `resolveInviteActor` (the site LIST half, `orgSiteScope`) and by
10942
- * `resolveSiteAccess` in the camera service (the ACCESS half, `cameraGrant`),
10943
- * because the two must answer "is this an org-level role?" identically or the
10944
- * switcher offers sites the camera view refuses.
10945
- */
10946
- declare function orgLevelRoles(db: Db, roles: Array<unknown>): Promise<Set<string>>;
10947
- /**
10948
- * Does this person OWN this organisation — did they create it, or is it
10949
- * registered under their own account e-mail?
10950
- *
10951
- * DV-0248. The client owner who signs themselves up creates the organisation
10952
- * (`POST /api/organizations/onboarding`) and only gets their `members` row at
10953
- * the LAST onboarding step, from `ensureCurrentUserMemberExists`. Every step in
10954
- * between — save the org details, create the first site, create the roles,
10955
- * invite the admins — asked for a membership or an invitation, and the owner
10956
- * has neither. So the wizard refused its own owner at step 1, and the
10957
- * organisation never appeared in their list either. On staging, 64 of 195
10958
- * organisations have no member and no invitation at all.
10959
- *
10960
- * Two roads, because the second repairs the ones already stuck:
10961
- *
10962
- * - `createdBy` — stamped from the session when the organisation is created,
10963
- * never from the request body. Fixes every NEW signup, and is the road that
10964
- * would have been enough on its own if the field had always existed.
10965
- * - `email` — the organisation is registered under the caller's own account
10966
- * address. This is the SAME comparison `organization.repo getAll` already
10967
- * makes to scope the client list, against the same session-resolved address,
10968
- * and it is what lets the 64 existing organisations repair themselves with no
10969
- * data backfill.
10970
- *
10971
- * The e-mail road is only sound because `PATCH /api/users/field/:id` no longer
10972
- * lets a user set their own address (`requireUserFieldWrite`). While it did,
10973
- * anyone could have typed a victim organisation's address and walked in; that
10974
- * hole is closed in the same change, and re-opening it re-opens this.
10975
- *
10976
- * Case-insensitive by collation rather than `$regex`, for the reason
10977
- * `hasOrgInvitation` gives: an address may contain `+` or `.` and building a
10978
- * pattern out of one invites an escaping bug.
10979
- */
10980
- declare function hasOrgOwnership(userId?: string | ObjectId | null, orgId?: string | ObjectId | null): Promise<boolean>;
10981
- /**
10982
- * Does this person themselves HOLD this role?
10983
- *
10984
- * `GET /api/roles/id/:id` is read on the hot path by every signed-in session —
10985
- * `layer-common plugins/secure-member.client.ts` resolves the caller's own app
10986
- * role, and the guard app's `permission.store.ts` does the same — so the only
10987
- * scoping rule that can go on it has to keep "my own role" working. Scoping it
10988
- * by the role's organisation alone does not: staging carries 12 roles with NO
10989
- * `org` at all, one of which ("Org Owner") is held by 119 ordinary tenant
10990
- * members across eight membership types. An org-less role routes to the staff
10991
- * gate, so those 119 accounts would 401 on their own role and both callers fail
10992
- * closed — permissions silently emptying, with nothing in the product to say
10993
- * why.
10994
- *
10995
- * The relationship is a live `members` row joining the caller's user id to this
10996
- * exact role id. **Both halves are resolved server-side**: the user id comes
10997
- * from the session (`callerId`), never from a body or a query field, and the
10998
- * role id is the resource being asked for. There is nothing a caller can send
10999
- * that makes this answer yes for a role they do not hold — naming somebody
11000
- * else's role id simply finds no row.
11611
+ ok: true;
11612
+ email: string;
11613
+ persistEmail: boolean;
11614
+ } | {
11615
+ ok: false;
11616
+ httpStatus: 400 | 404 | 429;
11617
+ reason: string;
11618
+ };
11619
+ /**
11620
+ * What the public resend route may do with an id.
11001
11621
  *
11002
- * `status: { $ne: "deleted" }` is the same liveness test every other membership
11003
- * read in this package uses, so a revoked membership stops conferring the read.
11622
+ * The rule that matters: an address ALREADY on the record wins, always. A
11623
+ * caller can fill in a blank one - that is what the card's inline field is for,
11624
+ * and it grants no more than the id already did, since the id alone opens the
11625
+ * pass page - but it can never redirect a pass that is already addressed to
11626
+ * someone. Without that, a harvested id would be a way to have another
11627
+ * person's check-in QR mailed anywhere.
11004
11628
  */
11005
- declare function holdsRole(userId?: string | ObjectId | null, roleId?: string | ObjectId | null): Promise<boolean>;
11629
+ declare function decideSelfServiceResend(facts: TSelfServiceResendFacts): TSelfServiceResendDecision;
11006
11630
 
11007
11631
  declare function useAuthControllerV2(): {
11008
11632
  signUp: (req: Request, res: Response, next: NextFunction) => Promise<void>;
@@ -12006,7 +12630,7 @@ declare function MHidAmicoIdentity(value: THidAmicoIdentity): {
12006
12630
  member: ObjectId | undefined;
12007
12631
  serviceProvider: ObjectId | undefined;
12008
12632
  visitor: ObjectId | undefined;
12009
- type: "admin" | "resident" | "contractor" | "unknown" | "visitor" | "staff";
12633
+ type: "admin" | "resident" | "staff" | "contractor" | "unknown" | "visitor";
12010
12634
  status: "deleted" | "active" | "inactive";
12011
12635
  metadata: Record<string, unknown>;
12012
12636
  createdAt: string | Date;
@@ -12118,7 +12742,7 @@ declare function useHidAmicoRepo(): {
12118
12742
  member: ObjectId | undefined;
12119
12743
  serviceProvider: ObjectId | undefined;
12120
12744
  visitor: ObjectId | undefined;
12121
- type: "admin" | "resident" | "contractor" | "unknown" | "visitor" | "staff";
12745
+ type: "admin" | "resident" | "staff" | "contractor" | "unknown" | "visitor";
12122
12746
  status: "deleted" | "active" | "inactive";
12123
12747
  metadata: Record<string, unknown>;
12124
12748
  createdAt: string | Date;
@@ -12522,7 +13146,7 @@ declare function useHidAmicoService(): {
12522
13146
  member: bson.ObjectId | undefined;
12523
13147
  serviceProvider: bson.ObjectId | undefined;
12524
13148
  visitor: bson.ObjectId | undefined;
12525
- type: "admin" | "resident" | "contractor" | "unknown" | "visitor" | "staff";
13149
+ type: "admin" | "resident" | "staff" | "contractor" | "unknown" | "visitor";
12526
13150
  status: "deleted" | "active" | "inactive";
12527
13151
  metadata: Record<string, unknown>;
12528
13152
  createdAt: string | Date;
@@ -12912,267 +13536,89 @@ declare function usePlatformTermsRepo(): {
12912
13536
  }>;
12913
13537
  getById: (id: string | ObjectId) => Promise<TPlatformTerms>;
12914
13538
  getByVersion: (version: number) => Promise<mongodb.WithId<TPlatformTerms> | null>;
12915
- getLatest: () => Promise<TPlatformTerms>;
12916
- getNextVersion: () => Promise<number>;
12917
- };
12918
-
12919
- declare function usePlatformTermsService(): {
12920
- getLatest: () => Promise<{
12921
- _id: ObjectId | undefined;
12922
- version: number;
12923
- terms: string;
12924
- policies: string;
12925
- createdAt: string | undefined;
12926
- }>;
12927
- getById: (id: string | ObjectId) => Promise<{
12928
- _id: ObjectId | undefined;
12929
- version: number;
12930
- terms: string;
12931
- policies: string;
12932
- createdAt: string | undefined;
12933
- }>;
12934
- assertLatestTerms: (termsId: string | ObjectId) => Promise<TPlatformTerms>;
12935
- getStatusByUserId: (userId: string | ObjectId) => Promise<{
12936
- latestVersion: {
12937
- _id: ObjectId | undefined;
12938
- version: number;
12939
- };
12940
- acceptedTerms: string | null;
12941
- acceptedTermsAt: string | null;
12942
- isCurrent: boolean;
12943
- }>;
12944
- acceptByUserId: (userId: string | ObjectId, termsId: string | ObjectId, session?: ClientSession) => Promise<{
12945
- acceptedTerms: ObjectId | undefined;
12946
- version: number;
12947
- }>;
12948
- getStatusByPersonId: (personId: string | ObjectId) => Promise<{
12949
- latestVersion: {
12950
- _id: ObjectId | undefined;
12951
- version: number;
12952
- };
12953
- acceptedTerms: string | null;
12954
- acceptedTermsAt: string | null;
12955
- isCurrent: boolean;
12956
- }>;
12957
- acceptByPersonId: (personId: string | ObjectId, termsId: string | ObjectId) => Promise<{
12958
- acceptedTerms: ObjectId | undefined;
12959
- version: number;
12960
- }>;
12961
- listAcceptance: ({ version, accepted, page, limit, }: {
12962
- version?: number | null | undefined;
12963
- accepted?: boolean | undefined;
12964
- page?: number | undefined;
12965
- limit?: number | undefined;
12966
- }) => Promise<{
12967
- items: any[];
12968
- pages: number;
12969
- pageRange: string;
12970
- }>;
12971
- add: ({ terms, policies, createdBy, }: {
12972
- terms: string;
12973
- policies: string;
12974
- createdBy: string | ObjectId;
12975
- }) => Promise<{
12976
- _id: ObjectId;
12977
- version: number;
12978
- terms: string;
12979
- policies: string;
12980
- createdBy: string | ObjectId;
12981
- status?: string | undefined;
12982
- createdAt?: string | undefined;
12983
- updatedAt?: string | undefined;
12984
- }>;
12985
- };
12986
-
12987
- declare function usePlatformTermsController(): {
12988
- getLatest: (_req: Request, res: Response, next: NextFunction) => Promise<void>;
12989
- getById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
12990
- getStatus: (req: Request, res: Response, next: NextFunction) => Promise<void>;
12991
- getAcceptance: (req: Request, res: Response, next: NextFunction) => Promise<void>;
12992
- accept: (req: Request, res: Response, next: NextFunction) => Promise<void>;
12993
- add: (req: Request, res: Response, next: NextFunction) => Promise<void>;
12994
- };
12995
-
12996
- declare function isTermsCurrent(accepted: string | null | undefined, latestVersionId: string): boolean;
12997
- declare function normalizeAcceptedTerms(acceptedTerms: ObjectId | string | null | undefined): string | null;
12998
-
12999
- /**
13000
- * What the Seven365 staff console records, as pure functions.
13001
- *
13002
- * Everything here is decidable without a database, a network or an Express
13003
- * request, which is the point: the rules that decide **what is allowed into an
13004
- * audit row** must be testable on their own. The row is written by
13005
- * `console-audit.repo.ts`; this file decides its shape and its contents.
13006
- *
13007
- * The one rule that governs the whole file: an audit row holds **who, what,
13008
- * which object, when, and enough of the values to make sense of the change**.
13009
- * It is not a copy of the document. Fields are admitted by an **allow-list per
13010
- * action** — anything not named there is dropped, so a handler that later
13011
- * passes a whole record cannot leak an email address, a phone number, a
13012
- * password hash or a token into the audit collection by accident.
13013
- */
13014
- /** The staff actions worth keeping a record of. */
13015
- declare enum ConsoleAuditAction {
13016
- SUBSCRIPTION_CREATED = "subscription.created",
13017
- SUBSCRIPTION_UPDATED = "subscription.updated",
13018
- CLIENT_CREATED = "client.created",
13019
- CLIENT_SUSPENDED = "client.suspended",
13020
- CLIENT_REACTIVATED = "client.reactivated",
13021
- /**
13022
- * Seven365 staff changing which catalogue modules a client is offered.
13023
- *
13024
- * Recorded because it is a commercial decision about a paying client that
13025
- * somebody has to be able to answer for later, even though it grants and
13026
- * revokes nothing by itself (`org-modules.util.ts` - it narrows what a role
13027
- * editor OFFERS, and the server re-decides every request regardless).
13028
- */
13029
- CLIENT_MODULES_CHANGED = "client.modules-changed",
13030
- PROMO_CODE_CREATED = "promo-code.created",
13031
- PROMO_CODE_UPDATED = "promo-code.updated",
13032
- PROMO_CODE_STATUS_CHANGED = "promo-code.status-changed",
13033
- PROMO_CODE_REMOVED = "promo-code.removed",
13034
- PLAN_CREATED = "plan.created",
13035
- PLAN_UPDATED = "plan.updated",
13036
- PLAN_STATUS_CHANGED = "plan.status-changed",
13037
- TERMS_PUBLISHED = "terms.published",
13038
- /**
13039
- * Seven365 staff switching a client's camera on or off.
13040
- *
13041
- * The only tenant-owned object on this list, and it is here because it is the
13042
- * only one staff may touch: a faulty camera at a client's site has to be
13043
- * switchable off by us. See `updateById` in `site-camera.controller.ts` for
13044
- * the boundary that allows it and nothing else.
13045
- */
13046
- CAMERA_STATUS_CHANGED = "camera.status-changed",
13047
- /**
13048
- * A camera being added, edited or removed BY THE SITE'S OWN PEOPLE.
13049
- *
13050
- * The three below are the answer to "who changed this camera's address, and
13051
- * when" - a question that had no answer anywhere in the system. A camera
13052
- * record carries `createdAt`/`updatedAt` and no actor, and a write overwrites
13053
- * the previous `host` in place, so a wrong port number could only be traced by
13054
- * asking people what they remembered doing. At Seventh Condominium that turned
13055
- * a one-line correction into nine days.
13056
- *
13057
- * This is a widening of what the collection holds: `CAMERA_STATUS_CHANGED` is
13058
- * a Seven365 STAFF action, and these are tenant actions. That is deliberate.
13059
- * The console is where an operator goes to answer exactly this question, the
13060
- * row already carries `actor`, `target` and `createdAt`, and the alternative -
13061
- * a second audit collection with its own repository, model and indexes - is
13062
- * more moving parts for the same row. Nothing existing changes: the collection
13063
- * is append-only and every reader filters by `action`.
13064
- */
13065
- CAMERA_ADDED = "camera.added",
13066
- CAMERA_UPDATED = "camera.updated",
13067
- CAMERA_REMOVED = "camera.removed"
13068
- }
13069
- /**
13070
- * The three actions that live in `organization.controller.ts`.
13071
- *
13072
- * They are defined, labelled and tested here, but **nothing calls them yet**.
13073
- * `organization.controller.ts` is being edited by open PR #1884 (suspend), and
13074
- * editing the same handlers here would hand a reviewer a merge conflict for no
13075
- * gain. Each needs exactly one `recordConsoleAction(...)` call once #1884
13076
- * lands; the action names and labels are already in place for it.
13077
- */
13078
- declare const CLIENT_ACTIONS: ConsoleAuditAction[];
13079
- /** What a person reads on the screen. The row carries it so the screen need not map it. */
13080
- declare const CONSOLE_AUDIT_LABELS: Record<ConsoleAuditAction, string>;
13081
- /** What kind of thing the action was done to. */
13082
- declare enum ConsoleAuditTarget {
13083
- ORGANIZATION = "organization",
13084
- SUBSCRIPTION = "subscription",
13085
- PROMO_CODE = "promo-code",
13086
- PLAN = "plan",
13087
- TERMS = "terms",
13088
- CAMERA = "camera"
13089
- }
13090
- /** A stored value is a primitive or it is not stored. */
13091
- declare const AUDIT_VALUE_MAX_LENGTH = 120;
13092
- /**
13093
- * The part of a change that may be stored, for this action.
13094
- *
13095
- * Returns `undefined` rather than `{}` when nothing survives, so an empty
13096
- * object never occupies a row and a reader can tell "nothing recorded" from
13097
- * "recorded as empty".
13098
- */
13099
- declare function pickAuditFields(action: ConsoleAuditAction, value?: Record<string, unknown> | null): Record<string, string | number | boolean> | undefined;
13100
-
13101
- /**
13102
- * One staff action in the Seven365 console.
13103
- *
13104
- * A new collection. Nothing existing is changed, no field is added to any live
13105
- * document, and there is no migration — a client, a subscription, a promo code
13106
- * and a plan are all exactly as they were.
13107
- *
13108
- * `actor` is a `users._id` and it comes from the SESSION, never from the
13109
- * request body. The body-attribution defect fixed on `POST /api/terms` earlier
13110
- * today is the reason that is written down rather than assumed.
13111
- */
13112
- type TConsoleAudit = {
13113
- _id?: ObjectId;
13114
- action: ConsoleAuditAction;
13115
- /** Who. A `users._id`, resolved from the session. */
13116
- actor: string | ObjectId;
13117
- /** Which client it affected, when the action is about one. */
13118
- org?: string | ObjectId | null;
13119
- /** Which object changed, and of what kind. */
13120
- target?: string | ObjectId | null;
13121
- targetType?: ConsoleAuditTarget | null;
13122
- /** Enough of the change to make sense of it — never a whole document. */
13123
- before?: Record<string, unknown> | null;
13124
- after?: Record<string, unknown> | null;
13125
- /** ISO-8601 UTC, so a lexicographic range filter is also a date range filter. */
13126
- createdAt?: string;
13127
- };
13128
- declare const schemaConsoleAudit: Joi.ObjectSchema<any>;
13129
- declare function MConsoleAudit(value: TConsoleAudit): TConsoleAudit;
13130
-
13131
- declare const console_audit_namespace_collection = "console-audit";
13132
- type TConsoleAuditQuery = {
13133
- org?: string;
13134
- action?: string;
13135
- /** ISO-8601. Inclusive at both ends of the day the caller names. */
13136
- from?: string;
13137
- to?: string;
13138
- page?: number;
13139
- limit?: number;
13140
- };
13141
- declare function useConsoleAuditRepo(): {
13142
- createIndexes: () => Promise<void>;
13143
- add: (value: TConsoleAudit) => Promise<{
13144
- _id: ObjectId;
13145
- action: ConsoleAuditAction;
13146
- actor: string | ObjectId;
13147
- org?: string | ObjectId | null | undefined;
13148
- target?: string | ObjectId | null | undefined;
13149
- targetType?: ConsoleAuditTarget | null | undefined;
13150
- before?: Record<string, unknown> | null | undefined;
13151
- after?: Record<string, unknown> | null | undefined;
13152
- createdAt?: string | undefined;
13539
+ getLatest: () => Promise<TPlatformTerms>;
13540
+ getNextVersion: () => Promise<number>;
13541
+ };
13542
+
13543
+ declare function usePlatformTermsService(): {
13544
+ getLatest: () => Promise<{
13545
+ _id: ObjectId | undefined;
13546
+ version: number;
13547
+ terms: string;
13548
+ policies: string;
13549
+ createdAt: string | undefined;
13153
13550
  }>;
13154
- list: (query: TConsoleAuditQuery) => Promise<{
13551
+ getById: (id: string | ObjectId) => Promise<{
13552
+ _id: ObjectId | undefined;
13553
+ version: number;
13554
+ terms: string;
13555
+ policies: string;
13556
+ createdAt: string | undefined;
13557
+ }>;
13558
+ assertLatestTerms: (termsId: string | ObjectId) => Promise<TPlatformTerms>;
13559
+ getStatusByUserId: (userId: string | ObjectId) => Promise<{
13560
+ latestVersion: {
13561
+ _id: ObjectId | undefined;
13562
+ version: number;
13563
+ };
13564
+ acceptedTerms: string | null;
13565
+ acceptedTermsAt: string | null;
13566
+ isCurrent: boolean;
13567
+ }>;
13568
+ acceptByUserId: (userId: string | ObjectId, termsId: string | ObjectId, session?: ClientSession) => Promise<{
13569
+ acceptedTerms: ObjectId | undefined;
13570
+ version: number;
13571
+ }>;
13572
+ getStatusByPersonId: (personId: string | ObjectId) => Promise<{
13573
+ latestVersion: {
13574
+ _id: ObjectId | undefined;
13575
+ version: number;
13576
+ };
13577
+ acceptedTerms: string | null;
13578
+ acceptedTermsAt: string | null;
13579
+ isCurrent: boolean;
13580
+ }>;
13581
+ acceptByPersonId: (personId: string | ObjectId, termsId: string | ObjectId) => Promise<{
13582
+ acceptedTerms: ObjectId | undefined;
13583
+ version: number;
13584
+ }>;
13585
+ listAcceptance: ({ version, accepted, page, limit, }: {
13586
+ version?: number | null | undefined;
13587
+ accepted?: boolean | undefined;
13588
+ page?: number | undefined;
13589
+ limit?: number | undefined;
13590
+ }) => Promise<{
13155
13591
  items: any[];
13156
13592
  pages: number;
13157
13593
  pageRange: string;
13158
13594
  }>;
13595
+ add: ({ terms, policies, createdBy, }: {
13596
+ terms: string;
13597
+ policies: string;
13598
+ createdBy: string | ObjectId;
13599
+ }) => Promise<{
13600
+ _id: ObjectId;
13601
+ version: number;
13602
+ terms: string;
13603
+ policies: string;
13604
+ createdBy: string | ObjectId;
13605
+ status?: string | undefined;
13606
+ createdAt?: string | undefined;
13607
+ updatedAt?: string | undefined;
13608
+ }>;
13159
13609
  };
13160
- /**
13161
- * Record a staff action — and never, under any circumstance, break the action
13162
- * it describes.
13163
- *
13164
- * Everything is inside the catch: resolving the database, validating the row
13165
- * and the insert itself. The returned promise **cannot reject**, so a caller
13166
- * that `await`s it cannot be thrown out of its own success path, and a caller
13167
- * that forgets to `await` it cannot crash the process with an unhandled
13168
- * rejection either. A failure is logged and the operation stands.
13169
- *
13170
- * Called only AFTER the operation it records has succeeded, so a row can never
13171
- * describe something that did not happen. The other direction is possible and
13172
- * accepted: an action can happen and its row fail to be written, in which case
13173
- * the log carries it.
13174
- */
13175
- declare function recordConsoleAction(entry: TConsoleAudit): Promise<void>;
13610
+
13611
+ declare function usePlatformTermsController(): {
13612
+ getLatest: (_req: Request, res: Response, next: NextFunction) => Promise<void>;
13613
+ getById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
13614
+ getStatus: (req: Request, res: Response, next: NextFunction) => Promise<void>;
13615
+ getAcceptance: (req: Request, res: Response, next: NextFunction) => Promise<void>;
13616
+ accept: (req: Request, res: Response, next: NextFunction) => Promise<void>;
13617
+ add: (req: Request, res: Response, next: NextFunction) => Promise<void>;
13618
+ };
13619
+
13620
+ declare function isTermsCurrent(accepted: string | null | undefined, latestVersionId: string): boolean;
13621
+ declare function normalizeAcceptedTerms(acceptedTerms: ObjectId | string | null | undefined): string | null;
13176
13622
 
13177
13623
  /**
13178
13624
  * The staff console's own history: who did what, to which client, and when.
@@ -13447,172 +13893,104 @@ declare function isSuperAdmin(userId?: string | ObjectId | null): Promise<boolea
13447
13893
  declare function isPlatformOwner(userId?: string | ObjectId | null): Promise<boolean>;
13448
13894
 
13449
13895
  /**
13450
- * THE SEVEN365 STAFF CONSOLE CATALOGUE, ON THE SERVER.
13451
- *
13452
- * `console-authz.util.ts` `requirePlatformStaff` answers ONE question — is this
13453
- * session a Seven365 staff membership — and twelve controllers ask it before
13454
- * every console write. It has never read which modules the staff role holds, so
13455
- * a staff account onboarded onto a role ticked for Promo Codes alone could still
13456
- * suspend a client, publish platform Terms, mint a subscription and read every
13457
- * user on the platform. The console's own guard
13458
- * (`web-app-org middleware/console-tier.global.ts` + `composables/useConsoleGate.ts`,
13459
- * shipped in org #186) hides those screens from that role, but hiding a screen
13460
- * is drawing, not securing: the endpoint behind it answered anybody with a staff
13461
- * session. This file is the server half.
13462
- *
13463
- * ## The catalogue is a MIRROR, and it is pinned as one
13464
- *
13465
- * The strings below are `web-app-org composables/useAdminPermission.ts` — the
13466
- * tick-boxes a `type: "admin"` role is actually built from — plus the two
13467
- * families that composable pulls out of layer-common's `useCommonPermissions`
13468
- * (`members`, `roles-and-permissions`). It is copied rather than imported
13469
- * because `core` is a backend package and cannot depend on a Nuxt layer; a
13470
- * server that invented its own vocabulary would be the
13471
- * `visitor:create`/`visitor-mgmt:add-visitor` split all over again — a string
13472
- * the server enforces that no role editor can grant.
13473
- *
13474
- * ## THE EMPTY-LIST RULE — why switching this on locks nobody out
13475
- *
13476
- * `user.service.ts createDefaultUser()` seeds the platform-staff role with
13477
- * `permissions: []`, NOT `["*"]`. A plain membership test over this catalogue
13478
- * would therefore refuse the Seven365 owner's own account on the day it shipped.
13479
- *
13480
- * So an EMPTY list means "everything", exactly as it does today, and `"*"` keeps
13481
- * the short-circuit it has everywhere else in the estate. Both spellings the
13482
- * staging owner role and the seeder can produce (`["*"]` and `[]`) allow all, so
13483
- * **no role, member or user document has to be written for this to ship** —
13484
- * which matters, because nothing in a repo may write one.
13485
- *
13486
- * The moment somebody ticks a module on a staff role, that role becomes
13487
- * governed at BOTH ends. That is the intended behaviour, and it is the one case
13488
- * to check before granting: a staff role that already holds a partial list is
13489
- * enforced immediately.
13490
- *
13491
- * ## WIDENING ONLY
13492
- *
13493
- * Every check here is layered ON TOP of the staff identity test, never in place
13494
- * of it — nobody who was refused before is admitted now. And the match accepts
13495
- * ANY shipped spelling of a grant, the rule
13496
- * `layer-common utils/permission-spellings.ts` already applies on the client:
13497
- * `-admin`'s role editor writes `roles-and-permissions:add-role` while eight
13498
- * apps write `roles:add-role`, and a role holding either must pass. Accepting
13499
- * both costs nothing and needs no role migration; picking one would silently
13500
- * un-grant every role holding the other.
13501
- */
13502
- /** Console resource -> the actions a staff role can be granted on it. */
13503
- declare const CONSOLE_PERMISSIONS: Readonly<Record<string, readonly string[]>>;
13504
- /** Every shipped spelling of `resource:action`. */
13505
- declare function consoleSpellings(resource: string, action: string): readonly string[];
13506
- /** True when this staff role is ungoverned and reaches the whole console. */
13507
- declare function consoleRoleAllowsAll(held?: readonly string[] | null): boolean;
13508
- /**
13509
- * May a staff role holding `held` take `action` on `resource`?
13510
- *
13511
- * Omit `action` to ask the SCREEN question — "does this role reach the resource
13512
- * at all" — which is `consoleCanSee` on the client: any single action on the
13513
- * resource is enough. Used where the catalogue has no string for the operation
13514
- * (creating a client organisation, writing a platform role/member row), because
13515
- * inventing a `create-organization` string here would be a grant no role editor
13516
- * anywhere can tick.
13517
- *
13518
- * An unknown resource, or an action the catalogue does not carry, is REFUSED for
13519
- * a governed role — the same answer `hasPermission` gives on the client, and the
13520
- * control the tests assert.
13521
- */
13522
- declare function consoleRoleAllows(held: readonly string[] | null | undefined, resource: string, action?: string): boolean;
13523
- /**
13524
- * THE CROSS-CLIENT GRANT — the one string that lets Seven365 staff out of
13525
- * tenant scoping.
13526
- *
13527
- * Every tenant-scoping helper in this package (`requireSiteReach`,
13528
- * `siteReachOf`, `entitledSites`, `requireOwnUnit`, `requireOrgReach`) opened
13529
- * with `if (actor.isSuperAdmin) return`. That is an IDENTITY test: it asks who
13530
- * the caller is and never asks what their staff role is ticked for. So a staff
13531
- * account onboarded onto a role holding Promo Codes alone still read and wrote
13532
- * every client's sites, people, files, documents, forms and facilities — the
13533
- * console gate shipped at revision 35 governs the console's OWN endpoints, and
13534
- * these are the tenant ones behind it.
13535
- *
13536
- * `organizations` is the catalogue string that already means "this staff role
13537
- * reaches across clients" (`CONSOLE_PERMISSIONS.organizations` =
13538
- * `see-all-organizations` / `see-organization-details`), and it is a tick-box
13539
- * the admin role editor can actually grant. No new vocabulary is invented — a
13540
- * string the server enforces that no editor can grant is the
13541
- * `visitor:create` mistake, and this deliberately avoids it. The SCREEN
13542
- * question is asked (no `action`), so either tick is enough.
13543
- */
13544
- declare const CROSS_CLIENT_GRANT: {
13545
- resource: string;
13546
- action?: string;
13547
- };
13548
- /**
13549
- * May this staff caller skip tenant scoping?
13896
+ * Q7 (owner, 2026-09-11): staff get NO notifications for modules they cannot
13897
+ * open.
13550
13898
  *
13551
- * **This never refuses anybody by itself.** It answers one question, and the
13552
- * caller falls through to the ORDINARY tenant scoping when the answer is no —
13553
- * so a staff member who is also a member of the target organisation, or who
13554
- * reaches the site through a live `customer.sites` engagement, is served
13555
- * exactly as they are today. The change is that platform identity alone stops
13556
- * being a skeleton key.
13899
+ * Only the Super Admin module list drops anybody: a recipient is dropped when
13900
+ * EVERY membership they hold at the site denies EVERY module the category is
13901
+ * about. A resource the list does not govern (`site-settings` for camera
13902
+ * faults) is never denied, so it always keeps the notification.
13557
13903
  *
13558
- * ## ZERO LOCKOUT
13904
+ * The role check is computed and LOGGED only (master plan rule 3). The apps do
13905
+ * not enforce most role gates today, so a role-based drop would hide alerts for
13906
+ * screens people can open, and RP-5 forbids that loss.
13559
13907
  *
13560
- * The rule is `consoleRoleAllows`, unchanged and already shipped: an EMPTY
13561
- * permission list means everything (that is what `createDefaultUser` seeds) and
13562
- * `"*"` means everything (that is what the live staff account holds). Both
13563
- * spellings a real staff role can carry today allow all, so no role, member or
13564
- * user document has to be written for this to ship and nobody loses access on
13565
- * deploy.
13908
+ * Exempt, never dropped: residents; anyone with no membership at the site
13909
+ * (invitees, a push-token user with no member row); Seven365 staff; a send
13910
+ * with no site (marketplace, broadcasts); a category not in the catalogue or
13911
+ * with no permission resources (resident-only and marketplace ones).
13566
13912
  *
13567
- * The one population this governs is a staff role holding a NON-EMPTY PARTIAL
13568
- * list which is the intended behaviour, and the same population revision 35
13569
- * already began governing on the console endpoints. Such a role keeps every
13570
- * client it holds a membership or engagement in; it loses only the reach it was
13571
- * never ticked for.
13572
- */
13573
- declare function staffMayBypass(actor: {
13574
- isSuperAdmin: boolean;
13575
- staffPermissions?: string[];
13576
- }, grant?: {
13577
- resource: string;
13578
- action?: string;
13579
- }): boolean;
13580
-
13581
- /**
13582
- * ONE console module, optionally ONE action on it.
13913
+ * `NOTIFY_ACCESS_FILTER`: `log` (code default) counts, logs and SENDS TO
13914
+ * EVERYONE; `on` drops; `off` reads nothing. `MODULE_LIST_GATE=off` is the
13915
+ * same as `off`. Any error sends to everyone.
13583
13916
  *
13584
- * `{ resource }` alone is the SCREEN question — "does this role reach the module
13585
- * at all" — which is `consoleCanSee` on the client. Used where the catalogue
13586
- * carries no string for the operation; see `console-permission.util.ts`.
13917
+ * Both senders call this: core's `notification.service.ts send()` here, and
13918
+ * API-core's own `send()` (a separate class; memory
13919
+ * `two-notification-senders-not-one`), which must call it the same way.
13587
13920
  */
13588
- type ConsoleGrant = {
13589
- resource: string;
13590
- action?: string;
13921
+ type TNotifyAccessMode = "log" | "on" | "off";
13922
+ declare const NOTIFY_ACCESS_FILTER_DEFAULT: TNotifyAccessMode;
13923
+ declare function notifyAccessMode(env?: Record<string, string | undefined>): TNotifyAccessMode;
13924
+ type TNotifyAccessContext = {
13925
+ category?: string | null;
13926
+ siteId?: unknown;
13591
13927
  };
13592
-
13593
- /**
13594
- * Seven365 staff only, and when a grant is named — staff whose role holds it.
13595
- *
13596
- * Returns the caller's id so a handler can attribute the write to them rather
13597
- * than to whatever the request body claimed.
13598
- *
13599
- * The `grant` argument is the whole of the console-permission change. Omitting
13600
- * it is exactly the behaviour this function has always had, so every call site
13601
- * that has not been mapped to a module is untouched rather than guessed at. A
13602
- * role with an EMPTY permission list which is what `createDefaultUser` seeds
13603
- * passes every grant, so naming one locks nobody out. See
13604
- * `console-permission.util.ts` for why that rule is what makes this shippable
13605
- * with no write to any role document.
13606
- */
13607
- declare function requirePlatformStaff(req: Request, grant?: ConsoleGrant): Promise<string>;
13608
- /**
13609
- * Seven365 staff who hold this console module.
13610
- *
13611
- * The name the controllers use. `requirePlatformStaff` still decides staff
13612
- * identity, unchanged this is a layer ON TOP of it, never a replacement, so
13613
- * nobody who was refused before is admitted now.
13614
- */
13615
- declare function requireConsolePermission(req: Request, resource: string, action?: string): Promise<string>;
13928
+ type TNotifyAccessReport = {
13929
+ dropByModule: string[];
13930
+ /** Logged only, never dropped. */
13931
+ dropByRole: string[];
13932
+ /** No membership at the site: counted, never dropped. */
13933
+ noMember: string[];
13934
+ };
13935
+ /** Who this send would drop, and why. `null` when the send is exempt as a whole. */
13936
+ declare function notificationAccessReport(userIds: readonly unknown[], context: TNotifyAccessContext, data?: TModuleGateData): Promise<TNotifyAccessReport | null>;
13937
+ /**
13938
+ * The recipients this send may reach. In `log` mode (the default) that is
13939
+ * always all of them. Never throws.
13940
+ */
13941
+ declare function filterByAccess<T extends string | {
13942
+ toString(): string;
13943
+ }>(userIds: T[], context: TNotifyAccessContext, data?: TModuleGateData): Promise<T[]>;
13944
+
13945
+ /**
13946
+ * Q3 (owner, 2026-09-11): the server must ALSO refuse modules a client has not
13947
+ * been given. This is the primitive. API-core's `requireSiteAccess` maps a
13948
+ * route to its module and asks here once the site is resolved.
13949
+ *
13950
+ * `MODULE_GATE_MODE`: `log` (code default) never refuses anything, it logs a
13951
+ * `would-refuse` line; `enforce` refuses only the modules listed in
13952
+ * `MODULE_GATE_ENFORCE_KEYS`; `off` reads nothing. `MODULE_LIST_GATE=off` is
13953
+ * the same as `off`.
13954
+ *
13955
+ * Allowed, always: Seven365 staff, residents, anyone with no membership at the
13956
+ * site, an ungoverned or unmapped module, a module only SOME of the person's
13957
+ * memberships at the site deny, and every error.
13958
+ *
13959
+ * OFFLINE WORK (owner, 2026-09-11): work done while the person still had
13960
+ * access is accepted. A queued offline item carries its original, frozen
13961
+ * timestamp (memory `isecure365-offline-mode`); pass it as `at`. It is refused
13962
+ * only if it was stamped at or after the acknowledged save that denied the
13963
+ * module. With no `at`, the request is treated as happening now.
13964
+ *
13965
+ * ponytail: `at` is the client's own clock, so a forged old timestamp slips
13966
+ * through. That fails open, which is the rule everywhere here; bound it by a
13967
+ * maximum queue age when enforcement starts.
13968
+ */
13969
+ type TModuleGateMode = "log" | "enforce" | "off";
13970
+ declare const MODULE_GATE_MODE_DEFAULT: TModuleGateMode;
13971
+ declare function moduleGateMode(env?: Record<string, string | undefined>): TModuleGateMode;
13972
+ /** The modules `enforce` refuses: comma-separated, any spelling. Empty = none. */
13973
+ declare function moduleGateEnforceKeys(env?: Record<string, string | undefined>): string[];
13974
+ type TModuleAccess = {
13975
+ /** Answer 403: only in `enforce` mode, and only for an enforced key. */
13976
+ refuse: boolean;
13977
+ /** The client's list denies this module for this person, at the time of the work. */
13978
+ denied: boolean;
13979
+ };
13980
+ declare function moduleDeniedForCaller({ userId, site, module, at, }: {
13981
+ userId?: unknown;
13982
+ /** The site id, or the site document when the caller already has it. */
13983
+ site?: {
13984
+ _id?: unknown;
13985
+ orgId?: unknown;
13986
+ metadata?: {
13987
+ modules?: unknown;
13988
+ } | null;
13989
+ } | string | null;
13990
+ module?: string | null;
13991
+ /** When the work was done: an offline item's original timestamp. */
13992
+ at?: Date | string | number | null;
13993
+ }, data?: TModuleGateData): Promise<TModuleAccess>;
13616
13994
 
13617
13995
  type Recipient = string | ObjectId | Array<string | ObjectId>;
13618
13996
  declare class NotificationService {
@@ -14234,4 +14612,4 @@ declare function usePersonalEmergencyChainController(): {
14234
14612
  update: (req: Request, res: Response, next: NextFunction) => Promise<void>;
14235
14613
  };
14236
14614
 
14237
- export { ANPRMode, APP_BASE_URLS, AUDIT_VALUE_MAX_LENGTH, AccessTypeProps, AppKey, AppServiceType, AssignCardConfig, BULK_CAMERA_COLUMNS, BidStatus, BidType, BuildingLevelStatus, BuildingStatus, BulkCameraAccepted, BulkCameraOutcome, BulkCameraPlan, BulkCameraResult, BulkCardUpdate, BulletinOrder, BulletinRecipient, BulletinSort, BulletinStatus, BulletinVideoOrder, BulletinVideoSort, CAMERA_ANPR_PERMISSIONS, CAMERA_CAPABILITIES, CAMERA_CAPABILITY_REASONS, CAMERA_MANAGE_ANY_PERMISSIONS, CAMERA_NOT_PATROL_OR_CCTV, CAMERA_NO_SUB_STREAM_TTL_SECONDS, CAMERA_PTZ_PERMISSIONS, CAMERA_REQUEST_TIMEOUT_MS, CAMERA_RTSP_TIMEOUT_MS, CAMERA_SETUP_PERMISSIONS, CAMERA_SNAPSHOT_CACHE_SECONDS, CAMERA_SNAPSHOT_MAX_BYTES, CAMERA_TEST_MIN_INTERVAL_SECONDS, CAMERA_TEST_ROUND_LIMIT, CAMERA_TEST_ROUND_SECONDS, CAMERA_TYPE_ANPR, CAMERA_TYPE_IP, CAMERA_VIEW_PERMISSIONS, CLIENT_ACTIONS, CLOCK_DRIFT_WARN_SECONDS, CONSOLE_AUDIT_LABELS, CONSOLE_PERMISSIONS, CONTRACTOR_TYPE_LABELS, CROSS_CLIENT_GRANT, CURRENT_TIME_ENDPOINT, Camera, CameraAddressInput, CameraCapability, CameraCapabilityContext, CameraCapabilityDescriptor, CameraCapabilityEntry, CameraCapabilityReason, CameraCapabilityState, CameraCapabilityTrace, CameraDevice, CameraFrame, CameraMembership, CameraStream, CameraTestStatus, CameraTransport, CameraType, ConsoleAuditAction, ConsoleAuditTarget, ConsoleGrant, DEFAULT_RING_SECONDS, DEFAULT_SITE_TIMEZONE, DEVICE_STATUS, DOBStatus, DUPLICATE_TERMS_VERSION_MESSAGE, DayOfWeek, DeviceHttpTarget, DeviceProbeResult, DynamicFormFields, E164, EAccessCardTypes, EAccessCardUserTypes, EmailSender, EntryOrder, EntrySort, EventOrder, EventSort, EventStatus, EventType, FacilitySort, FacilityStatus, FormEntryStatus, GuestSort, GuestStatus, HID_CARD_VALUE_FACTOR, HID_PERMISSION_CATEGORIES, HID_UINT32_MAX, HID_UINT64_MAX, HidRawUint64, IAccessCard, IAccessCardTransaction, InviteActor, LIVE_ROLE, MAX_BULK_CAMERA_ROWS, MAX_CAMERA_CHANNEL, MAX_CAMERA_NAME_LENGTH, MAX_PERSONAL_EMERGENCY_CONTACTS, MAX_RING_SECONDS, MAccessCard, MAccessCardTransaction, MAddress, MAttendance, MAttendanceSettings, MBidPreloved, MBillingConfiguration, MBillingItem, MBuilding, MBuildingLevel, MBuildingUnit, MBulletinBoard, MBulletinVideo, MCategoryPreloved, MChannelPreloved, MChat, MChatPreloved, MConsoleAudit, MCustomer, MCustomerSite, MDocumentManagement, MEMBER_TYPES, MEntryPassSettings, MEventManagement, MFeedback, MFile, MFormEntry, MGuestManagement, MHidAmicoEvent, MHidAmicoIdentity, MHidAmicoReader, MHidSipAccount, MHidSitePermissions, MIN_RING_SECONDS, MIncidentReport, MManpowerDesignations, MManpowerMonitoring, MManpowerRemarks, MManpowerSites, MMember, MNfcPatrolLog, MNfcPatrolRoute, MNfcPatrolSettings, MNfcPatrolSettingsUpdate, MNfcPatrolTag, MNotification, MNotificationPreference, MOccurrenceBook, MOccurrenceEntry, MOccurrenceSubject, MOnlineForm, MOrg, MOvernightParkingApprovalHours, MOvernightParkingRequest, MPatrolEmail, MPatrolLog, MPatrolQuestion, MPatrolRoute, MPerson, MPersonalEmergencyChain, MPlatformTerms, MPost, MPostFavorite, MPromoCode, MRobot, MRole, MRoleV2, MServiceProvider, MServiceProviderBilling, MSession, MSite, MSiteCamera, MSiteFacility, MSiteFacilityBooking, MStatementOfAccount, MSubcategoryPreloved, MSubscription, MSubscriptionPlan, MUnitBilling, MUser, MVehicle, MVehicleTransaction, MVerification, MVerificationV2, MVisitorTransaction, MWorkOrder, NOTIFICATION_CATEGORIES, NOTIFICATION_CHANNELS, NOTIFICATION_CHANNEL_LABELS, NOTIFICATION_NAMESPACE, NotificationAppSlug, NotificationCategory, NotificationChannel, NotificationModule, NotificationPreferenceView, NotificationService, ORG_MARKETPLACE_VENDOR_FIELD, OrgNature, OvernightParkingRequestSort, OvernightParkingRequestStatus, PATROL_CCTV_CAMERA_FILTER, PATROL_EMAIL_MAX_LOGS, PATROL_EMAIL_MAX_PER_HOUR, PATROL_EMAIL_MAX_RECIPIENTS, PERSON_TYPES, PLATFORM_STAFF_MEMBER_TYPE, PLATFORM_STAFF_ROLE_TYPE, PROPERTY_MANAGEMENT_MEMBER_TYPES, PStatus, PTZ_ALLOWED_ACTIONS, PTZ_ALLOWED_CODES, Period, PersonStatus, PersonType, PersonTypes, PlatformTermsStatus, PostOrder, PostSort, PostStatus, QrTagProps, REALTIME_MAX_FANOUT, ResidentAppModuleKey, SELF_SERVICE_RESEND_COOLDOWN_MS, SELF_SIGNUP_PLATFORM, SELF_SIGNUP_STATUS, SELF_SIGNUP_TYPES, SERVICE_PROVIDER_INVITE_LABELS, SERVICE_PROVIDER_INVITE_TRANSITIONS, SERVICE_PROVIDER_SIGN_IN_SUBJECT, SERVICE_PROVIDER_SIGN_IN_TYPE, SERVICE_PROVIDER_SIGN_UP_SUBJECT, SERVICE_PROVIDER_SIGN_UP_TYPE, SOFTWARE_VERSION_ENDPOINT, ServiceProviderInviteAction, ServiceProviderInviteDecision, ServiceProviderInviteFacts, SiteAddress, SiteCategories, SiteStatus, SortFields, SortOrder, Status, SubjectOrder, SubjectSort, SubscriptionBillingMode, SubscriptionType, TAccessMngmntSettings, TActionStatus, TAddress, TAffectedEntities, TAffectedInjured, TAppServiceType, TApprovedBy, TApprover, TAttendance, TAttendanceCheckIn, TAttendanceCheckOut, TAttendanceCheckTime, TAttendanceLocation, TAttendanceSettings, TAttendanceSettingsGetBySite, TAuthorities, TAuthoritiesCalled, TBidPreloved, TBilling, TBillingConfiguration, TBillingItem, TBuilding, TBuildingLevel, TBuildingUnit, TBulletinBoard, TBulletinVideo, TCamera, TCameraHealthClaim, TCategoryPreloved, TChannelPreloved, TChat, TChatPreloved, TCheckPoint$1 as TCheckPoint, TComplaintInfo, TComplaintReceivedTo, TConsoleAudit, TConsoleAuditQuery, TCounter, TCreateNfcPatrolLog, TCustomer, TCustomerSite, TCustomerSitePropertyField, TDayNumber, TDaySchedule, TDefaultAccessCard, TDesignations, TDocs, TDocumentCreate, TDocumentManagement, TEntryPassSettings, TEventManagement, TFeedback, TFeedbackMetadata, TFeedbackUpdate, TFeedbackUpdateCategory, TFeedbackUpdateServiceProvider, TFeedbackUpdateStatus, TFeedbackUpdateToCompleted, TFile, TFiles, TFolderUpdate, TFormEntry, TGetAttendancesByUserQuery, TGetAttendancesQuery, TGuestManagement, THidAmicoEvent, THidAmicoGatewayJob, THidAmicoIdentity, THidAmicoPhysicalCard, THidAmicoReader, THidPermissionAssignment, THidPermissionCategory, THidPermissionUserBinding, THidPhysicalCardInput, THidPhysicalCardType$1 as THidPhysicalCardType, THidSipAccount, THidSitePermissions, TIncidentInformation, TIncidentReport, TIncidentTypeAndTime, TInvoice, TKeyRef, TManpowerDesignations, TManpowerDesignationsUpdate, TManpowerMonitoring, TManpowerMonitoringUpdate, TManpowerRemarks, TManpowerRemarksStatusUpdate, TManpowerRemarksUpdate, TManpowerSearchFilter, TManpowerSites, TMember, TMemberUpdateStatus, TMessagePreloved, TMiniRole, TNfcPatrolLog, TNfcPatrolRoute, TNfcPatrolRouteEdit, TNfcPatrolSettings, TNfcPatrolSettingsGetBySite, TNfcPatrolSettingsUpdate, TNfcPatrolTag, TNfcPatrolTagConfigureReset, TNfcPatrolTagEdit, TNfcPatrolTagUpdateData, TNotification, TNotificationPreference, TNotificationPreferenceOff, TOccurrenceBook, TOccurrenceEntry, TOccurrenceSubject, TOnlineForm, TOrg, TOvernightParkingApprovalHours, TOvernightParkingRequest, TPatrolEmail, TPatrolEmailCreatedBy, TPatrolEmailLogRef, TPatrolLog, TPatrolQuestion, TPatrolRoute, TPerson, TPersonalEmergencyChain, TPersonalEmergencyContact, TPlaceOfIncident, TPlates, TPlatformTerms, TPost, TPostFavorite, TPrice, TPriceType, TPromoCode, TPromoCurrencyInput, TPromoTier, TRANSPORT_DEVICE_HTTP, TRANSPORT_RELAY_PLAYER, TRANSPORT_RTSP_FRAME, TRecipientOfComplaint, TRemarks, TResident, TResidentAppModules, TRobot, TRobotMetadata, TRole, TRolePermissionHistoryEntry, TRoleV2, TRoute, TSOABillingItem, TSOAStatus, TSelfServiceEmailOccasion, TSelfServiceEmailRecord, TSelfServiceResendDecision, TSelfServiceResendFacts, TServiceProvider, TServiceProviderBilling, TSession, TSessionCreate, TShifts, TSignNfcPatrolLog, TSite, TSiteCamera, TSiteDayBounds, TSiteFacility, TSiteFacilityBooking, TSiteInfo, TSiteInformation, TSiteMetadata, TSiteUpdateBlock, TStatementOfAccount, TSubcategoryPreloved, TSubmissionForm, TSubscription, TSubscriptionPlan, TSubscriptionPlanApplication, TUnitBilling, TUnits, TUpdateFormEntry, TUpdateName, TUser, TUserCreate, TVehicle, TVehicleTransaction, TVehicleUpdate, TVerification, TVerificationCode, TVerificationEvent, TVerificationMetadata, TVerificationMetadataV2, TVerificationOnboarding, TVerificationV2, TVisitorTransaction, TWorkOrder, TWorkOrderMetadata, TWorkOrderUpdate, TWorkOrderUpdateStatus, TWorkOrderUpdateToCompleted, TanyoneDamageToProperty, UNSTORED_COLUMNS, UseAccessManagementRepo, UserStatus, VERIFICATION_OPEN_STATUSES, VehicleCategory, VehicleOrder, VehicleSort, VehicleStatus, VehicleType, VerificationLinkType, VerificationStatus, VerificationSubjectType, VerificationType, VisitorSort, VisitorStatus, addressSchema, allowedFieldsSite, allowedNatures, allowedPlanApplications, attendanceSchema, attendanceSettingsSchema, buildSelfServiceEmailContext, building_level_namespace_collection, building_units_namespace_collection, buildings_namespace_collection, bulletin_boards_namespace_collection, callerId, cameraBaseUrl, cameraCapabilitiesFor, cameraDevices, cameraGrant, cameraHealthClaim, cameraHealthSummary, cameraManagePermissions, cameraProbeCacheKey, cameraTransports, canRevokeRefreshTokenFamily, categoriesForPermissions, categorySupportsChannel, chatPrelovedEvents, chatSchema, clampPtzSpeed, clockDriftSeconds, consoleRoleAllows, consoleRoleAllowsAll, consoleSpellings, console_audit_namespace_collection, createManpowerRemarksDaily, customerSchema, customerSitePropertyFields, decideSelfServiceResend, decideServiceProviderInvite, decodeHidPacsCard, deriveBulletinStatus, deriveCameraHost, describeCameraCapabilities, designationsSchema, deviceControlEnabled, deviceHttpEnabled, deviceHttpTargets, deviceHttpTimeoutMs, deviceProbeTtlSeconds, emitNotificationCreated, emptyPersonalEmergencyChain, encodeHidPacsCard, entitledSiteScope, events_namespace_collection, expiredBulletinSweepFilter, expiredVehicleSweepFilter, facility_bookings_namespace_collection, feedbackSchema, feedbacks2_namespace_collection, feedbacks_namespace_collection, ffmpegFrameArgs, ffmpegPath, formatCapabilityTrace, formatDahuaDate, getIO, getSessionIdFromRequest, grabWithSubStreamFallback, guests_namespace_collection, hasAnyCapability, hasAnyPermission, hasOrgInvitation, hasOrgOwnership, hidRawUint64, holdsRole, incidentReport, incidentReportLog, incidents_namespace_collection, isCameraEntitled, isDuplicateVersionError, isLikelySelfServiceEmail, isPatrolCctvCamera, isPlatformOwner, isPromoCodeExpired, isRelayPlayerUrl, isSafeRelativePath, isSuperAdmin, isTermsCurrent, isValidTimezone, logCamera, manpowerDesignationsSchema, manpowerEvents, manpowerMonitoringSchema, manpowerRemarksSchema, manpowerSitesSchema, mapWithLimit, maskNric, nfcPatrolSettingsSchema, nfcPatrolSettingsSchemaUpdate, normalizeAcceptedTerms, normalizeHidCardValue, notificationCategory, notificationCategoryLabel, notificationEvents, notificationRoom, occasionForStatus, occurrence_book_namespace_collection, online_forms_namespace_collection, orgLevelRoles, orgSchema, overnight_parking_requests_namespace_collection, parseCameraChannel, parseCameraHost, parseDahuaFind, parseDeviceTime, parseHidJsonLossless, parsePromoExpiry, parseSoftwareVersion, pickAuditFields, pickCustomerSiteProperties, planBulkCameraImport, platform_terms_namespace_collection, promoCodeRefusal, promoCodeSchema, promoCodeStatusSchema, promoCodeUpdate, promoCodeUpdateSchema, ptzEndpoint, publicCameraFields, recordConsoleAction, refuseServiceProviderInviteAction, registerCameraTransport, relayForRecorder, remarksSchema, renderPagePdf, requireConsolePermission, requirePlatformStaff, resetCameraTransports, residentAppModuleKeys, residentAppModulesSchema, residentFormEntry, resolutionRefusalReason, resolveCamera, resolveDeviceHttp, resolveHidPhysicalCardValue, resolveInviteActor, resolveSiteTimezone, resolveStaffRole, robotSchema, rtspUrl, schema, schemaAppSlugNotification, schemaApprovedBy, schemaApprover, schemaBidPreloved, schemaBilling, schemaBillingConfiguration, schemaBillingItem, schemaBuilding, schemaBuildingLevel, schemaBuildingUnit, schemaBuildingUpdateOptions, schemaBulletinBoard, schemaBulletinVideo, schemaCategoryPreloved, schemaChannelPreloved, schemaChatPreloved, schemaConsoleAudit, schemaCreateHidAmicoIdentity, schemaCreateNfcPatrolLog, schemaCreateNotification, schemaCustomerSite, schemaDiscoverHidAmicoReader, schemaDocumentManagement, schemaEntryPassSettings, schemaEventManagement, schemaFiles, schemaFormEntry, schemaGuestManagement, schemaHidAmicoAccessLogQuery, schemaHidAmicoAssignUserCard, schemaHidAmicoConfiguration, schemaHidAmicoEnrollUserCard, schemaHidAmicoEvent, schemaHidAmicoExecuteActions, schemaHidAmicoIdentity, schemaHidAmicoIdentityIdParams, schemaHidAmicoIdentityQuery, schemaHidAmicoIntercomCall, schemaHidAmicoLogQuery, schemaHidAmicoMonitor, schemaHidAmicoNotificationParams, schemaHidAmicoObjectOperation, schemaHidAmicoOperatingMode, schemaHidAmicoReader, schemaHidAmicoReaderIdParams, schemaHidAmicoReaderListQuery, schemaHidAmicoReaderUserQuery, schemaHidAmicoSetConfiguration, schemaHidAmicoSiteIdParams, schemaHidAmicoSync, schemaHidAmicoUserCardIdParams, schemaHidAmicoUserCardParams, schemaHidAmicoUserImageParams, schemaHidAmicoUserImageUploadQuery, schemaHidAmicoUserPin, schemaHidAmicoUserPinParams, schemaHidAmicoVisitorImageParams, schemaHidAmicoVisitorImageUploadQuery, schemaHidAmicoVisitorQr, schemaHidPermissionCandidateQuery, schemaHidPermissionScopeQuery, schemaHidSipAccountRequest, schemaIncidentReport, schemaListNotification, schemaMultipleDocumentManagement, schemaNfcPatrolLog, schemaNfcPatrolRoute, schemaNfcPatrolTag, schemaNfcPatrolTagUpdateData, schemaNotification, schemaNotificationPreference, schemaNotificationPreferenceOff, schemaOccurrenceBook, schemaOccurrenceEntry, schemaOccurrenceSubject, schemaOnlineForm, schemaOvernightParkingApprovalHours, schemaOvernightParkingRequest, schemaPatrolEmail, schemaPatrolEmailCreatedBy, schemaPatrolEmailLogRef, schemaPatrolEmailQuery, schemaPatrolLog, schemaPatrolQuestion, schemaPatrolRoute, schemaPerson, schemaPersonalEmergencyContact, schemaPlate, schemaPlatformTerms, schemaPost, schemaPostFavorite, schemaResendPatrolEmail, schemaResidentSelfSignUp, schemaSelfServiceVisitor, schemaSendPatrolEmail, schemaServiceProvider, schemaServiceProviderBilling, schemaSignNfcPatrolLog, schemaSiteCamera, schemaSiteFacility, schemaSiteFacilityBooking, schemaStatementOfAccount, schemaSubcategoryPreloved, schemaUnitBilling, schemaUpdateBidPreloved, schemaUpdateBuildingLevel, schemaUpdateBulletinBoard, schemaUpdateBulletinVideo, schemaUpdateCategoryPreloved, schemaUpdateChatPreloved, schemaUpdateDocumentManagement, schemaUpdateEntryPassSettings, schemaUpdateEventManagement, schemaUpdateFolderManagement, schemaUpdateFormEntry, schemaUpdateGuestManagement, schemaUpdateHidAmicoIdentity, schemaUpdateHidAmicoReader, schemaUpdateHidSitePermissions, schemaUpdateIncidentReport, schemaUpdateNotification, schemaUpdateNotificationPreference, schemaUpdateOccurrenceBook, schemaUpdateOccurrenceEntry, schemaUpdateOccurrenceSubject, schemaUpdateOnlineForm, schemaUpdateOptions, schemaUpdateOvernightParkingRequest, schemaUpdatePatrolLog, schemaUpdatePatrolQuestion, schemaUpdatePatrolRoute, schemaUpdatePerson, schemaUpdatePersonalEmergencyChain, schemaUpdatePost, schemaUpdatePostFavorite, schemaUpdateServiceProviderBilling, schemaUpdateSiteBillingConfiguration, schemaUpdateSiteBillingItem, schemaUpdateSiteCamera, schemaUpdateSiteFacility, schemaUpdateSiteFacilityBooking, schemaUpdateSiteUnitBilling, schemaUpdateStatementOfAccount, schemaUpdateSubcategoryPreloved, schemaUpdateVisTrans, schemaVehicleTransaction, schemaVisitorTransaction, schemeCamera, schemeLogCamera, selectHealthTargets, selfServiceEmailSubject, serviceProviderInviteLabel, sessionSchema, setIO, shiftSchema, siteDayBounds, siteSchema, site_people_namespace_collection, snapshotEndpoint, snapshotRefusalReason, staffMayBypass, stringifyHidJson, stripFacialImageMetadata, subscriptionPlanSchema, summariseBulkCameraPlan, updateRemarksStatusEod, updateRemarksisAcknowledged, updateSiteSchema, useAccessManagementController, useAddressRepo, useAttendanceController, useAttendanceRepository, useAttendanceSettingsController, useAttendanceSettingsRepository, useAttendanceSettingsService, useAuthController, useAuthControllerV2, useAuthService, useAuthServiceV2, useBidPrelovedController, useBidPrelovedRepo, useBidPrelovedService, useBuildingController, useBuildingLevelController, useBuildingLevelRepo, useBuildingLevelService, useBuildingRepo, useBuildingService, useBuildingUnitController, useBuildingUnitRepo, useBuildingUnitService, useBulletinBoardController, useBulletinBoardRepo, useBulletinBoardService, useBulletinVideoController, useBulletinVideoRepo, useBulletinVideoService, useCameraViewController, useCameraViewService, useCategoryPrelovedController, useCategoryPrelovedRepo, useChannelPrelovedController, useChannelPrelovedRepo, useChatController, useChatPrelovedController, useChatPrelovedRepo, useChatPrelovedService, useChatRepo, useConsoleAuditController, useConsoleAuditRepo, useCounterModel, useCounterRepo, useCustomerController, useCustomerRepo, useCustomerSiteController, useCustomerSiteRepo, useCustomerSiteService, useDahuaService, useDashboardController, useDashboardRepo, useDocumentManagementController, useDocumentManagementRepo, useDocumentManagementService, useEntryPassSettingsController, useEntryPassSettingsRepo, useEventManagementController, useEventManagementRepo, useEventManagementService, useFeedbackController, useFeedbackRepo, useFeedbackService, useFileController, useFileRepo, useFileService, useFormEntryController, useFormEntryRepo, useGuestManagementController, useGuestManagementRepo, useGuestManagementService, useHidAmicoController, useHidAmicoRepo, useHidAmicoService, useHrmLabsAttendanceCtrl, useHrmLabsAttendanceSrvc, useIncidentReportController, useIncidentReportRepo, useIncidentReportService, useInvoiceController, useInvoiceModel, useInvoiceRepo, useManpowerDesignationCtrl, useManpowerDesignationRepo, useManpowerMonitoringCtrl, useManpowerMonitoringRepo, useManpowerMonitoringSrvc, useManpowerRemarkCtrl, useManpowerRemarksRepo, useManpowerSitesCtrl, useManpowerSitesRepo, useManpowerSitesSrvc, useMemberController, useMemberRepo, useMemberService, useNewDashboardController, useNewDashboardRepo, useNfcPatrolLogController, useNfcPatrolLogRepo, useNfcPatrolLogService, useNfcPatrolRouteController, useNfcPatrolRouteRepo, useNfcPatrolRouteService, useNfcPatrolSettingsController, useNfcPatrolSettingsRepository, useNfcPatrolSettingsService, useNfcPatrolTagController, useNfcPatrolTagRepo, useNfcPatrolTagService, useNotificationController, useNotificationPreferenceController, useNotificationPreferenceRepo, useNotificationPreferenceService, useNotificationRepo, useOccurrenceBookController, useOccurrenceBookRepo, useOccurrenceBookService, useOccurrenceEntryController, useOccurrenceEntryRepo, useOccurrenceEntryService, useOccurrenceSubjectController, useOccurrenceSubjectRepo, useOccurrenceSubjectService, useOnlineFormController, useOnlineFormRepo, useOrgController, useOrgControllerV2, useOrgRepo, useOvernightParkingController, useOvernightParkingRepo, useOvernightParkingRequestController, useOvernightParkingRequestRepo, useOvernightParkingRequestService, usePatrolEmailController, usePatrolEmailRepo, usePatrolEmailService, usePatrolLogController, usePatrolLogRepo, usePatrolLogService, usePatrolQuestionController, usePatrolQuestionRepo, usePatrolRouteController, usePatrolRouteRepo, usePersonController, usePersonRepo, usePersonalEmergencyChainController, usePersonalEmergencyChainRepo, usePersonalEmergencyChainService, usePlatformTermsController, usePlatformTermsRepo, usePlatformTermsService, usePostFavoriteController, usePostFavoriteRepo, usePostFavoriteService, usePostPrelovedController, usePostPrelovedRepo, usePriceController, usePriceModel, usePriceRepo, usePromoCodeController, usePromoCodeRepo, useRedDotPaymentController, useRedDotPaymentRepo, useRedDotPaymentSvc, useRobotController, useRobotRepo, useRobotService, useRoleController, useRoleControllerV2, useRoleRepo, useRoleRepoV2, useRoleServiceV2, useServiceProviderBillingController, useServiceProviderBillingRepo, useServiceProviderBillingService, useServiceProviderController, useServiceProviderInviteController, useServiceProviderInviteService, useServiceProviderRepo, useSessionRepo, useSiteBillingConfigurationController, useSiteBillingConfigurationRepo, useSiteBillingItemController, useSiteBillingItemRepo, useSiteCameraController, useSiteCameraRepo, useSiteCameraService, useSiteController, useSiteFacilityBookingController, useSiteFacilityBookingRepo, useSiteFacilityBookingService, useSiteFacilityController, useSiteFacilityRepo, useSiteFacilityService, useSiteRepo, useSiteService, useSiteUnitBillingController, useSiteUnitBillingRepo, useSiteUnitBillingService, useStatementOfAccountController, useStatementOfAccountRepo, useSubcategoryPrelovedController, useSubcategoryPrelovedRepo, useSubscriptionController, useSubscriptionPlanController, useSubscriptionPlanRepo, useSubscriptionRepo, useSubscriptionService, useUserController, useUserControllerV2, useUserRepo, useUserRepoV2, useUserService, useUserServiceV2, useVehicleController, useVehicleRepo, useVehicleService, useVerificationController, useVerificationControllerV2, useVerificationRepo, useVerificationRepoV2, useVerificationService, useVerificationServiceV2, useVisitorTransactionController, useVisitorTransactionRepo, useVisitorTransactionService, useWorkOrderController, useWorkOrderRepo, useWorkOrderService, userSchema, vehicleSchema, vehicles_namespace_collection, visitorPersonRepo, visitorPersonService, visitorType, visitors_namespace_collection, wallConfig, workOrderSchema, work_orders2_namespace_collection, work_orders_namespace_collection };
14615
+ export { ANPRMode, APP_BASE_URLS, AUDIT_VALUE_MAX_LENGTH, AccessTypeProps, AppKey, AppServiceType, AssignCardConfig, BULK_CAMERA_COLUMNS, BidStatus, BidType, BuildingLevelStatus, BuildingStatus, BulkCameraAccepted, BulkCameraOutcome, BulkCameraPlan, BulkCameraResult, BulkCardUpdate, BulletinOrder, BulletinRecipient, BulletinSort, BulletinStatus, BulletinVideoOrder, BulletinVideoSort, CAMERA_ANPR_PERMISSIONS, CAMERA_CAPABILITIES, CAMERA_CAPABILITY_REASONS, CAMERA_MANAGE_ANY_PERMISSIONS, CAMERA_NOT_PATROL_OR_CCTV, CAMERA_NO_SUB_STREAM_TTL_SECONDS, CAMERA_PTZ_PERMISSIONS, CAMERA_REQUEST_TIMEOUT_MS, CAMERA_RTSP_TIMEOUT_MS, CAMERA_SETUP_PERMISSIONS, CAMERA_SNAPSHOT_CACHE_SECONDS, CAMERA_SNAPSHOT_MAX_BYTES, CAMERA_TEST_MIN_INTERVAL_SECONDS, CAMERA_TEST_ROUND_LIMIT, CAMERA_TEST_ROUND_SECONDS, CAMERA_TYPE_ANPR, CAMERA_TYPE_IP, CAMERA_VIEW_PERMISSIONS, CLIENT_ACTIONS, CLOCK_DRIFT_WARN_SECONDS, CONSOLE_AUDIT_LABELS, CONSOLE_PERMISSIONS, CONTRACTOR_TYPE_LABELS, CROSS_CLIENT_GRANT, CURRENT_TIME_ENDPOINT, Camera, CameraAddressInput, CameraCapability, CameraCapabilityContext, CameraCapabilityDescriptor, CameraCapabilityEntry, CameraCapabilityReason, CameraCapabilityState, CameraCapabilityTrace, CameraDevice, CameraFrame, CameraMembership, CameraStream, CameraTestStatus, CameraTransport, CameraType, ConsoleAuditAction, ConsoleAuditTarget, ConsoleGrant, DEFAULT_RING_SECONDS, DEFAULT_SITE_TIMEZONE, DEVICE_STATUS, DOBStatus, DUPLICATE_TERMS_VERSION_MESSAGE, DayOfWeek, DeviceHttpTarget, DeviceProbeResult, DynamicFormFields, E164, EAccessCardTypes, EAccessCardUserTypes, EmailSender, EntryOrder, EntrySort, EventOrder, EventSort, EventStatus, EventType, FacilitySort, FacilityStatus, FormEntryStatus, GOVERNED_MODULES, GuestSort, GuestStatus, HID_CARD_VALUE_FACTOR, HID_PERMISSION_CATEGORIES, HID_UINT32_MAX, HID_UINT64_MAX, HidRawUint64, IAccessCard, IAccessCardTransaction, InviteActor, LIVE_ROLE, MAX_BULK_CAMERA_ROWS, MAX_CAMERA_CHANNEL, MAX_CAMERA_NAME_LENGTH, MAX_PERSONAL_EMERGENCY_CONTACTS, MAX_RING_SECONDS, MAccessCard, MAccessCardTransaction, MAddress, MAttendance, MAttendanceSettings, MBidPreloved, MBillingConfiguration, MBillingItem, MBuilding, MBuildingLevel, MBuildingUnit, MBulletinBoard, MBulletinVideo, MCategoryPreloved, MChannelPreloved, MChat, MChatPreloved, MConsoleAudit, MCustomer, MCustomerSite, MDocumentManagement, MEMBER_TYPES, MEntryPassSettings, MEventManagement, MFeedback, MFile, MFormEntry, MGuestManagement, MHidAmicoEvent, MHidAmicoIdentity, MHidAmicoReader, MHidSipAccount, MHidSitePermissions, MIN_RING_SECONDS, MIncidentReport, MManpowerDesignations, MManpowerMonitoring, MManpowerRemarks, MManpowerSites, MMember, MNfcPatrolLog, MNfcPatrolRoute, MNfcPatrolSettings, MNfcPatrolSettingsUpdate, MNfcPatrolTag, MNotification, MNotificationPreference, MODULE_GATE_MODE_DEFAULT, MODULE_LIST_GATE_DEFAULT, MOccurrenceBook, MOccurrenceEntry, MOccurrenceSubject, MOnlineForm, MOrg, MOvernightParkingApprovalHours, MOvernightParkingRequest, MPatrolEmail, MPatrolLog, MPatrolQuestion, MPatrolRoute, MPerson, MPersonalEmergencyChain, MPlatformTerms, MPost, MPostFavorite, MPromoCode, MRobot, MRole, MRoleV2, MServiceProvider, MServiceProviderBilling, MSession, MSite, MSiteCamera, MSiteFacility, MSiteFacilityBooking, MStatementOfAccount, MSubcategoryPreloved, MSubscription, MSubscriptionPlan, MUnitBilling, MUser, MVehicle, MVehicleTransaction, MVerification, MVerificationV2, MVisitorTransaction, MWorkOrder, NOTIFICATION_CATEGORIES, NOTIFICATION_CHANNELS, NOTIFICATION_CHANNEL_LABELS, NOTIFICATION_NAMESPACE, NOTIFY_ACCESS_FILTER_DEFAULT, NotificationAppSlug, NotificationCategory, NotificationChannel, NotificationModule, NotificationPreferenceView, NotificationService, ORG_MARKETPLACE_VENDOR_FIELD, OrgNature, OvernightParkingRequestSort, OvernightParkingRequestStatus, PATROL_CCTV_CAMERA_FILTER, PATROL_EMAIL_MAX_LOGS, PATROL_EMAIL_MAX_PER_HOUR, PATROL_EMAIL_MAX_RECIPIENTS, PERSON_TYPES, PLATFORM_STAFF_MEMBER_TYPE, PLATFORM_STAFF_ROLE_TYPE, PROPERTY_MANAGEMENT_MEMBER_TYPES, PStatus, PTZ_ALLOWED_ACTIONS, PTZ_ALLOWED_CODES, Period, PersonStatus, PersonType, PersonTypes, PlatformTermsStatus, PostOrder, PostSort, PostStatus, QrTagProps, REALTIME_MAX_FANOUT, ResidentAppModuleKey, SELF_SERVICE_RESEND_COOLDOWN_MS, SELF_SIGNUP_PLATFORM, SELF_SIGNUP_STATUS, SELF_SIGNUP_TYPES, SERVICE_PROVIDER_INVITE_LABELS, SERVICE_PROVIDER_INVITE_TRANSITIONS, SERVICE_PROVIDER_SIGN_IN_SUBJECT, SERVICE_PROVIDER_SIGN_IN_TYPE, SERVICE_PROVIDER_SIGN_UP_SUBJECT, SERVICE_PROVIDER_SIGN_UP_TYPE, SOFTWARE_VERSION_ENDPOINT, ServiceProviderInviteAction, ServiceProviderInviteDecision, ServiceProviderInviteFacts, SiteAddress, SiteCategories, SiteStatus, SortFields, SortOrder, Status, SubjectOrder, SubjectSort, SubscriptionBillingMode, SubscriptionType, TAccessMngmntSettings, TActionStatus, TAddress, TAffectedEntities, TAffectedInjured, TAppServiceType, TApprovedBy, TApprover, TAttendance, TAttendanceCheckIn, TAttendanceCheckOut, TAttendanceCheckTime, TAttendanceLocation, TAttendanceSettings, TAttendanceSettingsGetBySite, TAuthorities, TAuthoritiesCalled, TBidPreloved, TBilling, TBillingConfiguration, TBillingItem, TBuilding, TBuildingLevel, TBuildingUnit, TBulletinBoard, TBulletinVideo, TCamera, TCameraHealthClaim, TCategoryPreloved, TChannelPreloved, TChat, TChatPreloved, TCheckPoint$1 as TCheckPoint, TComplaintInfo, TComplaintReceivedTo, TConsoleAudit, TConsoleAuditQuery, TCounter, TCreateNfcPatrolLog, TCustomer, TCustomerSite, TCustomerSitePropertyField, TDayNumber, TDaySchedule, TDefaultAccessCard, TDesignations, TDocs, TDocumentCreate, TDocumentManagement, TEntryPassSettings, TEventManagement, TFeedback, TFeedbackMetadata, TFeedbackUpdate, TFeedbackUpdateCategory, TFeedbackUpdateServiceProvider, TFeedbackUpdateStatus, TFeedbackUpdateToCompleted, TFile, TFiles, TFolderUpdate, TFormEntry, TGetAttendancesByUserQuery, TGetAttendancesQuery, TGuestManagement, THidAmicoEvent, THidAmicoGatewayJob, THidAmicoIdentity, THidAmicoPhysicalCard, THidAmicoReader, THidPermissionAssignment, THidPermissionCategory, THidPermissionUserBinding, THidPhysicalCardInput, THidPhysicalCardType$1 as THidPhysicalCardType, THidSipAccount, THidSitePermissions, TIncidentInformation, TIncidentReport, TIncidentTypeAndTime, TInvoice, TKeyRef, TManpowerDesignations, TManpowerDesignationsUpdate, TManpowerMonitoring, TManpowerMonitoringUpdate, TManpowerRemarks, TManpowerRemarksStatusUpdate, TManpowerRemarksUpdate, TManpowerSearchFilter, TManpowerSites, TMember, TMemberModulesDeps, TMemberUpdateStatus, TMessagePreloved, TMiniRole, TModuleAccess, TModuleGateMode, TModuleImpact, TNfcPatrolLog, TNfcPatrolRoute, TNfcPatrolRouteEdit, TNfcPatrolSettings, TNfcPatrolSettingsGetBySite, TNfcPatrolSettingsUpdate, TNfcPatrolTag, TNfcPatrolTagConfigureReset, TNfcPatrolTagEdit, TNfcPatrolTagUpdateData, TNotification, TNotificationPreference, TNotificationPreferenceOff, TNotifyAccessContext, TNotifyAccessMode, TNotifyAccessReport, TOccurrenceBook, TOccurrenceEntry, TOccurrenceSubject, TOnlineForm, TOrg, TOrgModulesDeps, TOvernightParkingApprovalHours, TOvernightParkingRequest, TPatrolEmail, TPatrolEmailCreatedBy, TPatrolEmailLogRef, TPatrolLog, TPatrolQuestion, TPatrolRoute, TPerson, TPersonalEmergencyChain, TPersonalEmergencyContact, TPlaceOfIncident, TPlates, TPlatformTerms, TPost, TPostFavorite, TPrice, TPriceType, TPromoCode, TPromoCurrencyInput, TPromoTier, TRANSPORT_DEVICE_HTTP, TRANSPORT_RELAY_PLAYER, TRANSPORT_RTSP_FRAME, TRecipientOfComplaint, TRemarks, TResident, TResidentAppModules, TRobot, TRobotMetadata, TRole, TRolePermissionHistoryEntry, TRoleV2, TRoute, TSOABillingItem, TSOAStatus, TSelfServiceEmailOccasion, TSelfServiceEmailRecord, TSelfServiceResendDecision, TSelfServiceResendFacts, TServiceProvider, TServiceProviderBilling, TSession, TSessionCreate, TShifts, TSignNfcPatrolLog, TSite, TSiteCamera, TSiteDayBounds, TSiteFacility, TSiteFacilityBooking, TSiteInfo, TSiteInformation, TSiteMetadata, TSiteModulesDeps, TSiteUpdateBlock, TStatementOfAccount, TSubcategoryPreloved, TSubmissionForm, TSubscription, TSubscriptionPlan, TSubscriptionPlanApplication, TUnitBilling, TUnits, TUpdateFormEntry, TUpdateName, TUser, TUserCreate, TVehicle, TVehicleTransaction, TVehicleUpdate, TVerification, TVerificationCode, TVerificationEvent, TVerificationMetadata, TVerificationMetadataV2, TVerificationOnboarding, TVerificationV2, TVisitorTransaction, TWorkOrder, TWorkOrderMetadata, TWorkOrderUpdate, TWorkOrderUpdateStatus, TWorkOrderUpdateToCompleted, TanyoneDamageToProperty, UNSTORED_COLUMNS, UseAccessManagementRepo, UserStatus, VERIFICATION_OPEN_STATUSES, VehicleCategory, VehicleOrder, VehicleSort, VehicleStatus, VehicleType, VerificationLinkType, VerificationStatus, VerificationSubjectType, VerificationType, VisitorSort, VisitorStatus, addressSchema, allowedFieldsSite, allowedNatures, allowedPlanApplications, attendanceSchema, attendanceSettingsSchema, buildSelfServiceEmailContext, building_level_namespace_collection, building_units_namespace_collection, buildings_namespace_collection, bulletin_boards_namespace_collection, callerAccountApproved, callerId, cameraBaseUrl, cameraCapabilitiesFor, cameraDevices, cameraGrant, cameraHealthClaim, cameraHealthSummary, cameraManagePermissions, cameraProbeCacheKey, cameraTransports, canRevokeRefreshTokenFamily, categoriesForPermissions, categorySupportsChannel, chatPrelovedEvents, chatSchema, clampPtzSpeed, clockDriftSeconds, consoleRoleAllows, consoleRoleAllowsAll, consoleSpellings, console_audit_namespace_collection, createManpowerRemarksDaily, customerSchema, customerSitePropertyFields, decideSelfServiceResend, decideServiceProviderInvite, decodeHidPacsCard, deniedModules, deriveBulletinStatus, deriveCameraHost, describeCameraCapabilities, designationsSchema, deviceControlEnabled, deviceHttpEnabled, deviceHttpTargets, deviceHttpTimeoutMs, deviceProbeTtlSeconds, emitNotificationCreated, emptyPersonalEmergencyChain, encodeHidPacsCard, entitledSiteScope, events_namespace_collection, expandModules, expiredBulletinSweepFilter, expiredVehicleSweepFilter, facility_bookings_namespace_collection, feedbackSchema, feedbacks2_namespace_collection, feedbacks_namespace_collection, ffmpegFrameArgs, ffmpegPath, filterByAccess, formatCapabilityTrace, formatDahuaDate, getIO, getSessionIdFromRequest, grabWithSubStreamFallback, guests_namespace_collection, hasAnyCapability, hasAnyPermission, hasOrgInvitation, hasOrgOwnership, hasOrgSiteReach, hidRawUint64, holdsRole, incidentReport, incidentReportLog, incidents_namespace_collection, invitationOffersRole, isCameraEntitled, isDuplicateVersionError, isLikelySelfServiceEmail, isPatrolCctvCamera, isPlatformOwner, isPromoCodeExpired, isRelayPlayerUrl, isSafeRelativePath, isSuperAdmin, isTermsCurrent, isValidTimezone, logCamera, manpowerDesignationsSchema, manpowerEvents, manpowerMonitoringSchema, manpowerRemarksSchema, manpowerSitesSchema, mapWithLimit, maskNric, memberModulesHandlers, moduleDeniedForCaller, moduleGateEnforceKeys, moduleGateMode, moduleImpact, moduleListGateOn, nfcPatrolSettingsSchema, nfcPatrolSettingsSchemaUpdate, normalizeAcceptedTerms, normalizeHidCardValue, notificationAccessReport, notificationCategory, notificationCategoryLabel, notificationEvents, notificationRoom, notifyAccessMode, occasionForStatus, occurrence_book_namespace_collection, online_forms_namespace_collection, orgLevelRoles, orgModulesHandlers, orgSchema, overnight_parking_requests_namespace_collection, parseCameraChannel, parseCameraHost, parseDahuaFind, parseDeviceTime, parseHidJsonLossless, parsePromoExpiry, parseSoftwareVersion, pickAuditFields, pickCustomerSiteProperties, planBulkCameraImport, platform_terms_namespace_collection, promoCodeRefusal, promoCodeSchema, promoCodeStatusSchema, promoCodeUpdate, promoCodeUpdateSchema, ptzEndpoint, publicCameraFields, readsAsApprovedAccount, recordConsoleAction, refuseServiceProviderInviteAction, registerCameraTransport, relayForRecorder, remarksSchema, renderPagePdf, requireConsolePermission, requirePlatformStaff, resetCameraTransports, residentAppModuleKeys, residentAppModulesSchema, residentFormEntry, resolutionRefusalReason, resolveCamera, resolveDeviceHttp, resolveHidPhysicalCardValue, resolveInviteActor, resolveSiteTimezone, resolveStaffRole, robotSchema, rtspUrl, schema, schemaAppSlugNotification, schemaApprovedBy, schemaApprover, schemaBidPreloved, schemaBilling, schemaBillingConfiguration, schemaBillingItem, schemaBuilding, schemaBuildingLevel, schemaBuildingUnit, schemaBuildingUpdateOptions, schemaBulletinBoard, schemaBulletinVideo, schemaCategoryPreloved, schemaChannelPreloved, schemaChatPreloved, schemaConsoleAudit, schemaCreateHidAmicoIdentity, schemaCreateNfcPatrolLog, schemaCreateNotification, schemaCustomerSite, schemaDiscoverHidAmicoReader, schemaDocumentManagement, schemaEntryPassSettings, schemaEventManagement, schemaFiles, schemaFormEntry, schemaGuestManagement, schemaHidAmicoAccessLogQuery, schemaHidAmicoAssignUserCard, schemaHidAmicoConfiguration, schemaHidAmicoEnrollUserCard, schemaHidAmicoEvent, schemaHidAmicoExecuteActions, schemaHidAmicoIdentity, schemaHidAmicoIdentityIdParams, schemaHidAmicoIdentityQuery, schemaHidAmicoIntercomCall, schemaHidAmicoLogQuery, schemaHidAmicoMonitor, schemaHidAmicoNotificationParams, schemaHidAmicoObjectOperation, schemaHidAmicoOperatingMode, schemaHidAmicoReader, schemaHidAmicoReaderIdParams, schemaHidAmicoReaderListQuery, schemaHidAmicoReaderUserQuery, schemaHidAmicoSetConfiguration, schemaHidAmicoSiteIdParams, schemaHidAmicoSync, schemaHidAmicoUserCardIdParams, schemaHidAmicoUserCardParams, schemaHidAmicoUserImageParams, schemaHidAmicoUserImageUploadQuery, schemaHidAmicoUserPin, schemaHidAmicoUserPinParams, schemaHidAmicoVisitorImageParams, schemaHidAmicoVisitorImageUploadQuery, schemaHidAmicoVisitorQr, schemaHidPermissionCandidateQuery, schemaHidPermissionScopeQuery, schemaHidSipAccountRequest, schemaIncidentReport, schemaListNotification, schemaMultipleDocumentManagement, schemaNfcPatrolLog, schemaNfcPatrolRoute, schemaNfcPatrolTag, schemaNfcPatrolTagUpdateData, schemaNotification, schemaNotificationPreference, schemaNotificationPreferenceOff, schemaOccurrenceBook, schemaOccurrenceEntry, schemaOccurrenceSubject, schemaOnlineForm, schemaOvernightParkingApprovalHours, schemaOvernightParkingRequest, schemaPatrolEmail, schemaPatrolEmailCreatedBy, schemaPatrolEmailLogRef, schemaPatrolEmailQuery, schemaPatrolLog, schemaPatrolQuestion, schemaPatrolRoute, schemaPerson, schemaPersonalEmergencyContact, schemaPlate, schemaPlatformTerms, schemaPost, schemaPostFavorite, schemaResendPatrolEmail, schemaResidentSelfSignUp, schemaSelfServiceVisitor, schemaSendPatrolEmail, schemaServiceProvider, schemaServiceProviderBilling, schemaSignNfcPatrolLog, schemaSiteCamera, schemaSiteFacility, schemaSiteFacilityBooking, schemaStatementOfAccount, schemaSubcategoryPreloved, schemaUnitBilling, schemaUpdateBidPreloved, schemaUpdateBuildingLevel, schemaUpdateBulletinBoard, schemaUpdateBulletinVideo, schemaUpdateCategoryPreloved, schemaUpdateChatPreloved, schemaUpdateDocumentManagement, schemaUpdateEntryPassSettings, schemaUpdateEventManagement, schemaUpdateFolderManagement, schemaUpdateFormEntry, schemaUpdateGuestManagement, schemaUpdateHidAmicoIdentity, schemaUpdateHidAmicoReader, schemaUpdateHidSitePermissions, schemaUpdateIncidentReport, schemaUpdateNotification, schemaUpdateNotificationPreference, schemaUpdateOccurrenceBook, schemaUpdateOccurrenceEntry, schemaUpdateOccurrenceSubject, schemaUpdateOnlineForm, schemaUpdateOptions, schemaUpdateOvernightParkingRequest, schemaUpdatePatrolLog, schemaUpdatePatrolQuestion, schemaUpdatePatrolRoute, schemaUpdatePerson, schemaUpdatePersonalEmergencyChain, schemaUpdatePost, schemaUpdatePostFavorite, schemaUpdateServiceProviderBilling, schemaUpdateSiteBillingConfiguration, schemaUpdateSiteBillingItem, schemaUpdateSiteCamera, schemaUpdateSiteFacility, schemaUpdateSiteFacilityBooking, schemaUpdateSiteUnitBilling, schemaUpdateStatementOfAccount, schemaUpdateSubcategoryPreloved, schemaUpdateVisTrans, schemaVehicleTransaction, schemaVisitorTransaction, schemeCamera, schemeLogCamera, selectHealthTargets, selfServiceEmailSubject, serviceProviderInviteLabel, sessionSchema, setIO, shiftSchema, siteDayBounds, siteModulesHandlers, siteSchema, site_people_namespace_collection, snapshotEndpoint, snapshotRefusalReason, staffMayBypass, stringifyHidJson, stripFacialImageMetadata, subscriptionPlanSchema, summariseBulkCameraPlan, updateRemarksStatusEod, updateRemarksisAcknowledged, updateSiteSchema, useAccessManagementController, useAddressRepo, useAttendanceController, useAttendanceRepository, useAttendanceSettingsController, useAttendanceSettingsRepository, useAttendanceSettingsService, useAuthController, useAuthControllerV2, useAuthService, useAuthServiceV2, useBidPrelovedController, useBidPrelovedRepo, useBidPrelovedService, useBuildingController, useBuildingLevelController, useBuildingLevelRepo, useBuildingLevelService, useBuildingRepo, useBuildingService, useBuildingUnitController, useBuildingUnitRepo, useBuildingUnitService, useBulletinBoardController, useBulletinBoardRepo, useBulletinBoardService, useBulletinVideoController, useBulletinVideoRepo, useBulletinVideoService, useCameraViewController, useCameraViewService, useCategoryPrelovedController, useCategoryPrelovedRepo, useChannelPrelovedController, useChannelPrelovedRepo, useChatController, useChatPrelovedController, useChatPrelovedRepo, useChatPrelovedService, useChatRepo, useConsoleAuditController, useConsoleAuditRepo, useCounterModel, useCounterRepo, useCustomerController, useCustomerRepo, useCustomerSiteController, useCustomerSiteRepo, useCustomerSiteService, useDahuaService, useDashboardController, useDashboardRepo, useDocumentManagementController, useDocumentManagementRepo, useDocumentManagementService, useEntryPassSettingsController, useEntryPassSettingsRepo, useEventManagementController, useEventManagementRepo, useEventManagementService, useFeedbackController, useFeedbackRepo, useFeedbackService, useFileController, useFileRepo, useFileService, useFormEntryController, useFormEntryRepo, useGuestManagementController, useGuestManagementRepo, useGuestManagementService, useHidAmicoController, useHidAmicoRepo, useHidAmicoService, useHrmLabsAttendanceCtrl, useHrmLabsAttendanceSrvc, useIncidentReportController, useIncidentReportRepo, useIncidentReportService, useInvoiceController, useInvoiceModel, useInvoiceRepo, useManpowerDesignationCtrl, useManpowerDesignationRepo, useManpowerMonitoringCtrl, useManpowerMonitoringRepo, useManpowerMonitoringSrvc, useManpowerRemarkCtrl, useManpowerRemarksRepo, useManpowerSitesCtrl, useManpowerSitesRepo, useManpowerSitesSrvc, useMemberController, useMemberRepo, useMemberService, useNewDashboardController, useNewDashboardRepo, useNfcPatrolLogController, useNfcPatrolLogRepo, useNfcPatrolLogService, useNfcPatrolRouteController, useNfcPatrolRouteRepo, useNfcPatrolRouteService, useNfcPatrolSettingsController, useNfcPatrolSettingsRepository, useNfcPatrolSettingsService, useNfcPatrolTagController, useNfcPatrolTagRepo, useNfcPatrolTagService, useNotificationController, useNotificationPreferenceController, useNotificationPreferenceRepo, useNotificationPreferenceService, useNotificationRepo, useOccurrenceBookController, useOccurrenceBookRepo, useOccurrenceBookService, useOccurrenceEntryController, useOccurrenceEntryRepo, useOccurrenceEntryService, useOccurrenceSubjectController, useOccurrenceSubjectRepo, useOccurrenceSubjectService, useOnlineFormController, useOnlineFormRepo, useOrgController, useOrgControllerV2, useOrgRepo, useOvernightParkingController, useOvernightParkingRepo, useOvernightParkingRequestController, useOvernightParkingRequestRepo, useOvernightParkingRequestService, usePatrolEmailController, usePatrolEmailRepo, usePatrolEmailService, usePatrolLogController, usePatrolLogRepo, usePatrolLogService, usePatrolQuestionController, usePatrolQuestionRepo, usePatrolRouteController, usePatrolRouteRepo, usePersonController, usePersonRepo, usePersonalEmergencyChainController, usePersonalEmergencyChainRepo, usePersonalEmergencyChainService, usePlatformTermsController, usePlatformTermsRepo, usePlatformTermsService, usePostFavoriteController, usePostFavoriteRepo, usePostFavoriteService, usePostPrelovedController, usePostPrelovedRepo, usePriceController, usePriceModel, usePriceRepo, usePromoCodeController, usePromoCodeRepo, useRedDotPaymentController, useRedDotPaymentRepo, useRedDotPaymentSvc, useRobotController, useRobotRepo, useRobotService, useRoleController, useRoleControllerV2, useRoleRepo, useRoleRepoV2, useRoleServiceV2, useServiceProviderBillingController, useServiceProviderBillingRepo, useServiceProviderBillingService, useServiceProviderController, useServiceProviderInviteController, useServiceProviderInviteService, useServiceProviderRepo, useSessionRepo, useSiteBillingConfigurationController, useSiteBillingConfigurationRepo, useSiteBillingItemController, useSiteBillingItemRepo, useSiteCameraController, useSiteCameraRepo, useSiteCameraService, useSiteController, useSiteFacilityBookingController, useSiteFacilityBookingRepo, useSiteFacilityBookingService, useSiteFacilityController, useSiteFacilityRepo, useSiteFacilityService, useSiteRepo, useSiteService, useSiteUnitBillingController, useSiteUnitBillingRepo, useSiteUnitBillingService, useStatementOfAccountController, useStatementOfAccountRepo, useSubcategoryPrelovedController, useSubcategoryPrelovedRepo, useSubscriptionController, useSubscriptionPlanController, useSubscriptionPlanRepo, useSubscriptionRepo, useSubscriptionService, useUserController, useUserControllerV2, useUserRepo, useUserRepoV2, useUserService, useUserServiceV2, useVehicleController, useVehicleRepo, useVehicleService, useVerificationController, useVerificationControllerV2, useVerificationRepo, useVerificationRepoV2, useVerificationService, useVerificationServiceV2, useVisitorTransactionController, useVisitorTransactionRepo, useVisitorTransactionService, useWorkOrderController, useWorkOrderRepo, useWorkOrderService, userSchema, vehicleSchema, vehicles_namespace_collection, visitorPersonRepo, visitorPersonService, visitorType, visitors_namespace_collection, wallConfig, workOrderSchema, work_orders2_namespace_collection, work_orders_namespace_collection };