@endora-commerce/mod-customers 0.100.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.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/admin/index.d.ts +26 -0
  4. package/dist/admin/index.d.ts.map +1 -0
  5. package/dist/admin/index.js +68 -0
  6. package/dist/admin/index.js.map +1 -0
  7. package/dist/admin/pages/CustomerDetail.d.ts +9 -0
  8. package/dist/admin/pages/CustomerDetail.d.ts.map +1 -0
  9. package/dist/admin/pages/CustomerDetail.js +72 -0
  10. package/dist/admin/pages/CustomerDetail.js.map +1 -0
  11. package/dist/admin/pages/CustomersList.d.ts +9 -0
  12. package/dist/admin/pages/CustomersList.d.ts.map +1 -0
  13. package/dist/admin/pages/CustomersList.js +115 -0
  14. package/dist/admin/pages/CustomersList.js.map +1 -0
  15. package/dist/admin/pages/OnlineCustomers.d.ts +9 -0
  16. package/dist/admin/pages/OnlineCustomers.d.ts.map +1 -0
  17. package/dist/admin/pages/OnlineCustomers.js +77 -0
  18. package/dist/admin/pages/OnlineCustomers.js.map +1 -0
  19. package/dist/admin/panels/HistoryPanels.d.ts +11 -0
  20. package/dist/admin/panels/HistoryPanels.d.ts.map +1 -0
  21. package/dist/admin/panels/HistoryPanels.js +64 -0
  22. package/dist/admin/panels/HistoryPanels.js.map +1 -0
  23. package/dist/admin/panels/ManagementPanels.d.ts +14 -0
  24. package/dist/admin/panels/ManagementPanels.d.ts.map +1 -0
  25. package/dist/admin/panels/ManagementPanels.js +93 -0
  26. package/dist/admin/panels/ManagementPanels.js.map +1 -0
  27. package/dist/backend/entities/customer-address.entity.d.ts +25 -0
  28. package/dist/backend/entities/customer-address.entity.d.ts.map +1 -0
  29. package/dist/backend/entities/customer-address.entity.js +95 -0
  30. package/dist/backend/entities/customer-address.entity.js.map +1 -0
  31. package/dist/backend/index.d.ts +91 -0
  32. package/dist/backend/index.d.ts.map +1 -0
  33. package/dist/backend/index.js +201 -0
  34. package/dist/backend/index.js.map +1 -0
  35. package/dist/backend/plugin.d.ts +168 -0
  36. package/dist/backend/plugin.d.ts.map +1 -0
  37. package/dist/backend/plugin.js +83 -0
  38. package/dist/backend/plugin.js.map +1 -0
  39. package/dist/backend/routes.admin.d.ts +70 -0
  40. package/dist/backend/routes.admin.d.ts.map +1 -0
  41. package/dist/backend/routes.admin.js +313 -0
  42. package/dist/backend/routes.admin.js.map +1 -0
  43. package/dist/backend/routes.register.d.ts +12 -0
  44. package/dist/backend/routes.register.d.ts.map +1 -0
  45. package/dist/backend/routes.register.js +40 -0
  46. package/dist/backend/routes.register.js.map +1 -0
  47. package/dist/backend/routes.self.d.ts +46 -0
  48. package/dist/backend/routes.self.d.ts.map +1 -0
  49. package/dist/backend/routes.self.js +145 -0
  50. package/dist/backend/routes.self.js.map +1 -0
  51. package/dist/backend/serializers.d.ts +13 -0
  52. package/dist/backend/serializers.d.ts.map +1 -0
  53. package/dist/backend/serializers.js +39 -0
  54. package/dist/backend/serializers.js.map +1 -0
  55. package/dist/backend/services/customer-address-read-port.d.ts +29 -0
  56. package/dist/backend/services/customer-address-read-port.d.ts.map +1 -0
  57. package/dist/backend/services/customer-address-read-port.js +53 -0
  58. package/dist/backend/services/customer-address-read-port.js.map +1 -0
  59. package/dist/backend/services/customer-address-service.d.ts +94 -0
  60. package/dist/backend/services/customer-address-service.d.ts.map +1 -0
  61. package/dist/backend/services/customer-address-service.js +176 -0
  62. package/dist/backend/services/customer-address-service.js.map +1 -0
  63. package/dist/backend/services/customer-admin-query-service.d.ts +57 -0
  64. package/dist/backend/services/customer-admin-query-service.d.ts.map +1 -0
  65. package/dist/backend/services/customer-admin-query-service.js +97 -0
  66. package/dist/backend/services/customer-admin-query-service.js.map +1 -0
  67. package/dist/backend/services/customer-authority-service.d.ts +46 -0
  68. package/dist/backend/services/customer-authority-service.d.ts.map +1 -0
  69. package/dist/backend/services/customer-authority-service.js +42 -0
  70. package/dist/backend/services/customer-authority-service.js.map +1 -0
  71. package/dist/backend/services/customer-defaults-service.d.ts +48 -0
  72. package/dist/backend/services/customer-defaults-service.d.ts.map +1 -0
  73. package/dist/backend/services/customer-defaults-service.js +71 -0
  74. package/dist/backend/services/customer-defaults-service.js.map +1 -0
  75. package/dist/backend/services/customer-deletion-service.d.ts +39 -0
  76. package/dist/backend/services/customer-deletion-service.d.ts.map +1 -0
  77. package/dist/backend/services/customer-deletion-service.js +94 -0
  78. package/dist/backend/services/customer-deletion-service.js.map +1 -0
  79. package/dist/backend/services/customer-moderation-service.d.ts +58 -0
  80. package/dist/backend/services/customer-moderation-service.d.ts.map +1 -0
  81. package/dist/backend/services/customer-moderation-service.js +70 -0
  82. package/dist/backend/services/customer-moderation-service.js.map +1 -0
  83. package/dist/backend/services/customer-org-assignment-service.d.ts +52 -0
  84. package/dist/backend/services/customer-org-assignment-service.d.ts.map +1 -0
  85. package/dist/backend/services/customer-org-assignment-service.js +106 -0
  86. package/dist/backend/services/customer-org-assignment-service.js.map +1 -0
  87. package/dist/backend/services/customer-presence-service.d.ts +44 -0
  88. package/dist/backend/services/customer-presence-service.d.ts.map +1 -0
  89. package/dist/backend/services/customer-presence-service.js +47 -0
  90. package/dist/backend/services/customer-presence-service.js.map +1 -0
  91. package/dist/backend/services/customer-registration-service.d.ts +56 -0
  92. package/dist/backend/services/customer-registration-service.d.ts.map +1 -0
  93. package/dist/backend/services/customer-registration-service.js +43 -0
  94. package/dist/backend/services/customer-registration-service.js.map +1 -0
  95. package/dist/backend/workers/anonymization-sweep-worker.d.ts +15 -0
  96. package/dist/backend/workers/anonymization-sweep-worker.d.ts.map +1 -0
  97. package/dist/backend/workers/anonymization-sweep-worker.js +20 -0
  98. package/dist/backend/workers/anonymization-sweep-worker.js.map +1 -0
  99. package/dist/manifest.d.ts +181 -0
  100. package/dist/manifest.d.ts.map +1 -0
  101. package/dist/manifest.js +192 -0
  102. package/dist/manifest.js.map +1 -0
  103. package/dist/migrations/20260611T140404_customers_customer_addresses_init.d.ts +14 -0
  104. package/dist/migrations/20260611T140404_customers_customer_addresses_init.d.ts.map +1 -0
  105. package/dist/migrations/20260611T140404_customers_customer_addresses_init.js +40 -0
  106. package/dist/migrations/20260611T140404_customers_customer_addresses_init.js.map +1 -0
  107. package/dist/migrations/index.d.ts +27 -0
  108. package/dist/migrations/index.d.ts.map +1 -0
  109. package/dist/migrations/index.js +29 -0
  110. package/dist/migrations/index.js.map +1 -0
  111. package/docs/customers.md +108 -0
  112. package/i18n/en.json +94 -0
  113. package/i18n/pl.json +94 -0
  114. package/package.json +101 -0
  115. package/tailwind.css +14 -0
@@ -0,0 +1,44 @@
1
+ import type { AuthSessionReadPort, CustomerAccountReadPort, OnlineCustomer } from '@endora-commerce/contracts';
2
+ /**
3
+ * CustomerPresenceService — the admin "online customers" view (feature 040,
4
+ * US7 / FR-034). A customer is online if a session of theirs was active within
5
+ * the configurable freshness window.
6
+ */
7
+ export interface RecentActivityPort {
8
+ listRecentlyActiveCustomers(windowMinutes: number): Promise<string[]>;
9
+ }
10
+ export declare class CustomerPresenceService {
11
+ private readonly sessions;
12
+ /**
13
+ * Feature 075 — `auth`'s published read, where this service ran
14
+ * `em.find(Session, …)` over that module's table to work out when each
15
+ * account was last seen. The port answers the same question and carries no
16
+ * `Session` entity, so the "who is online" panel no longer needs an
17
+ * `EntityManager` at all.
18
+ */
19
+ private readonly sessionReads;
20
+ private readonly resolveFreshnessMinutes;
21
+ /**
22
+ * Feature 075 — `customer_accounts`' published read, where this service ran
23
+ * `em.find(CustomerAccount, …)` over that module's table. The four fields
24
+ * it renders are all on the record.
25
+ */
26
+ private readonly accounts;
27
+ constructor(sessions: RecentActivityPort,
28
+ /**
29
+ * Feature 075 — `auth`'s published read, where this service ran
30
+ * `em.find(Session, …)` over that module's table to work out when each
31
+ * account was last seen. The port answers the same question and carries no
32
+ * `Session` entity, so the "who is online" panel no longer needs an
33
+ * `EntityManager` at all.
34
+ */
35
+ sessionReads: AuthSessionReadPort, resolveFreshnessMinutes: () => Promise<number>,
36
+ /**
37
+ * Feature 075 — `customer_accounts`' published read, where this service ran
38
+ * `em.find(CustomerAccount, …)` over that module's table. The four fields
39
+ * it renders are all on the record.
40
+ */
41
+ accounts: CustomerAccountReadPort);
42
+ listOnline(): Promise<OnlineCustomer[]>;
43
+ }
44
+ //# sourceMappingURL=customer-presence-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customer-presence-service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/customer-presence-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACf,MAAM,4BAA4B,CAAC;AAEpC;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACvE;AAED,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAfR,QAAQ,EAAE,kBAAkB;IAC7C;;;;;;OAMG;IACc,YAAY,EAAE,mBAAmB,EACjC,uBAAuB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC;IAC/D;;;;OAIG;IACc,QAAQ,EAAE,uBAAuB;IAG9C,UAAU,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;CAqB9C"}
@@ -0,0 +1,47 @@
1
+ export class CustomerPresenceService {
2
+ sessions;
3
+ sessionReads;
4
+ resolveFreshnessMinutes;
5
+ accounts;
6
+ constructor(sessions,
7
+ /**
8
+ * Feature 075 — `auth`'s published read, where this service ran
9
+ * `em.find(Session, …)` over that module's table to work out when each
10
+ * account was last seen. The port answers the same question and carries no
11
+ * `Session` entity, so the "who is online" panel no longer needs an
12
+ * `EntityManager` at all.
13
+ */
14
+ sessionReads, resolveFreshnessMinutes,
15
+ /**
16
+ * Feature 075 — `customer_accounts`' published read, where this service ran
17
+ * `em.find(CustomerAccount, …)` over that module's table. The four fields
18
+ * it renders are all on the record.
19
+ */
20
+ accounts) {
21
+ this.sessions = sessions;
22
+ this.sessionReads = sessionReads;
23
+ this.resolveFreshnessMinutes = resolveFreshnessMinutes;
24
+ this.accounts = accounts;
25
+ }
26
+ async listOnline() {
27
+ const windowMinutes = await this.resolveFreshnessMinutes();
28
+ const ids = await this.sessions.listRecentlyActiveCustomers(windowMinutes);
29
+ if (ids.length === 0)
30
+ return [];
31
+ const customers = await this.accounts.findByIds(ids, { activeOnly: true });
32
+ // Latest activity per customer, for the displayed timestamp.
33
+ const cutoff = new Date(Date.now() - windowMinutes * 60 * 1000);
34
+ const lastSeen = new Map();
35
+ for (const row of await this.sessionReads.lastSeenByCustomerAccount(ids, cutoff)) {
36
+ lastSeen.set(row.customerAccountId, row.lastSeenAt);
37
+ }
38
+ return customers.map((c) => ({
39
+ id: c.id,
40
+ email: c.email,
41
+ firstName: c.firstName,
42
+ lastName: c.lastName,
43
+ lastSeenAt: (lastSeen.get(c.id) ?? new Date()).toISOString(),
44
+ }));
45
+ }
46
+ }
47
+ //# sourceMappingURL=customer-presence-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customer-presence-service.js","sourceRoot":"","sources":["../../../src/backend/services/customer-presence-service.ts"],"names":[],"mappings":"AAeA,MAAM,OAAO,uBAAuB;IAEf;IAQA;IACA;IAMA;IAhBnB,YACmB,QAA4B;IAC7C;;;;;;OAMG;IACc,YAAiC,EACjC,uBAA8C;IAC/D;;;;OAIG;IACc,QAAiC;QAfjC,aAAQ,GAAR,QAAQ,CAAoB;QAQ5B,iBAAY,GAAZ,YAAY,CAAqB;QACjC,4BAAuB,GAAvB,uBAAuB,CAAuB;QAM9C,aAAQ,GAAR,QAAQ,CAAyB;IACjD,CAAC;IAEJ,KAAK,CAAC,UAAU;QACd,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC3D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,2BAA2B,CAAC,aAAa,CAAC,CAAC;QAC3E,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEhC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3E,6DAA6D;QAC7D,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAChE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAgB,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,MAAM,IAAI,CAAC,YAAY,CAAC,yBAAyB,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC;YACjF,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,UAAU,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE;SAC7D,CAAC,CAAC,CAAC;IACN,CAAC;CACF"}
@@ -0,0 +1,56 @@
1
+ import { type AuthSessionPort, type CustomerAccountLifecycleWritePort, type CustomerAccountRecord } from '@endora-commerce/contracts';
2
+ /**
3
+ * CustomerRegistrationService — standalone (org-less) sign-up (feature 040,
4
+ * US1 / FR-002/FR-004).
5
+ *
6
+ * Gated by the `customers.allow_registration_without_organization` setting:
7
+ * when disabled, registration is refused with a clear, actionable error so
8
+ * the storefront can steer the visitor toward Organization registration.
9
+ *
10
+ * On success the new account and the individual's single-member personal
11
+ * organization are written in one transaction by `customer_accounts` (D-178),
12
+ * and an auto-login session is minted (parity with the Organization
13
+ * registration flow, which also logs the first user straight in).
14
+ *
15
+ * **Feature 075, Phase C — this service writes no table.** It used to create
16
+ * `customer_accounts`' entity itself, hash the password with `auth`'s hasher,
17
+ * and hand its own `EntityManager` to `organizations`' provisioner. All three
18
+ * are owner-side now: the account and its audit row come from
19
+ * `customerAccountLifecycleWritePort`, the hashing goes with them (a caller
20
+ * that hashes is a caller that has to be told which algorithm the owner uses),
21
+ * and the organisation is provisioned inside that same write (D-178). What is left
22
+ * here is the policy — whether a registration outside a company organization is
23
+ * allowed at all — which is this module's setting.
24
+ */
25
+ export interface CustomerRegistrationDeps {
26
+ /** `customer_accounts`' account lifecycle. Creates the row and audits it. */
27
+ accounts: CustomerAccountLifecycleWritePort;
28
+ /**
29
+ * `auth`'s published session port (D-98.2), not the `SessionService` class
30
+ * this used to import: the only method reached here is `createSession`, the
31
+ * port declares it, and `authSessionPort` is the name the contract
32
+ * publishes.
33
+ */
34
+ sessionService: AuthSessionPort;
35
+ /** Reads `customers.allow_registration_without_organization` (the per-channel B2C gate). */
36
+ resolveAllowRegistrationWithoutOrganization: () => Promise<boolean>;
37
+ }
38
+ export interface RegisterStandaloneInput {
39
+ email: string;
40
+ password: string;
41
+ firstName: string;
42
+ lastName: string;
43
+ ip?: string;
44
+ userAgent?: string;
45
+ }
46
+ export interface RegisterStandaloneResult {
47
+ customerAccount: CustomerAccountRecord;
48
+ sessionCookieValue: string;
49
+ sessionExpiresAt: Date;
50
+ }
51
+ export declare class CustomerRegistrationService {
52
+ private readonly deps;
53
+ constructor(deps: CustomerRegistrationDeps);
54
+ registerStandalone(input: RegisterStandaloneInput): Promise<RegisterStandaloneResult>;
55
+ }
56
+ //# sourceMappingURL=customer-registration-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customer-registration-service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/customer-registration-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,iCAAiC,EACtC,KAAK,qBAAqB,EAC3B,MAAM,4BAA4B,CAAC;AAGpC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,wBAAwB;IACvC,6EAA6E;IAC7E,QAAQ,EAAE,iCAAiC,CAAC;IAC5C;;;;;OAKG;IACH,cAAc,EAAE,eAAe,CAAC;IAChC,4FAA4F;IAC5F,2CAA2C,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACrE;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,eAAe,EAAE,qBAAqB,CAAC;IACvC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,IAAI,CAAC;CACxB;AAED,qBAAa,2BAA2B;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,wBAAwB;IAErD,kBAAkB,CACtB,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,wBAAwB,CAAC;CA0CrC"}
@@ -0,0 +1,43 @@
1
+ import { ERROR_CODES, } from '@endora-commerce/contracts';
2
+ import { HttpError } from '@endora-commerce/platform/http';
3
+ export class CustomerRegistrationService {
4
+ deps;
5
+ constructor(deps) {
6
+ this.deps = deps;
7
+ }
8
+ async registerStandalone(input) {
9
+ const allowed = await this.deps.resolveAllowRegistrationWithoutOrganization();
10
+ if (!allowed) {
11
+ throw new HttpError(403, ERROR_CODES.REGISTRATION_REQUIRES_ORGANIZATION, 'Registration without an Organization is currently disabled. Please register your Organization instead.');
12
+ }
13
+ // The duplicate-address refusal is inside the write, so a registration
14
+ // racing its own pre-check still answers 409 rather than a 500 off the
15
+ // unique index.
16
+ //
17
+ // D-178 — the personal organization feature 051 requires is provisioned
18
+ // inside that call, in the same transaction as the account, so the record
19
+ // that comes back already carries it. This service used to call
20
+ // `personalOrganizationPort.ensureForCustomerAccount` on the next line, and
21
+ // that second unit of work is exactly what left a committed account with no
22
+ // organization whenever it failed: the visitor had no session to retry from
23
+ // and nothing anywhere re-ran the provisioning.
24
+ const customerAccount = await this.deps.accounts.createStandalone({
25
+ email: input.email,
26
+ password: input.password,
27
+ firstName: input.firstName,
28
+ lastName: input.lastName,
29
+ });
30
+ const session = await this.deps.sessionService.createSession({
31
+ kind: 'customer',
32
+ customerAccountId: customerAccount.id,
33
+ ...(input.ip !== undefined ? { ipAddress: input.ip } : {}),
34
+ ...(input.userAgent !== undefined ? { userAgent: input.userAgent } : {}),
35
+ });
36
+ return {
37
+ customerAccount,
38
+ sessionCookieValue: session.cookieValue,
39
+ sessionExpiresAt: session.expiresAt,
40
+ };
41
+ }
42
+ }
43
+ //# sourceMappingURL=customer-registration-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customer-registration-service.js","sourceRoot":"","sources":["../../../src/backend/services/customer-registration-service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,GAIZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAsD3D,MAAM,OAAO,2BAA2B;IACT;IAA7B,YAA6B,IAA8B;QAA9B,SAAI,GAAJ,IAAI,CAA0B;IAAG,CAAC;IAE/D,KAAK,CAAC,kBAAkB,CACtB,KAA8B;QAE9B,MAAM,OAAO,GACX,MAAM,IAAI,CAAC,IAAI,CAAC,2CAA2C,EAAE,CAAC;QAChE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,kCAAkC,EAC9C,wGAAwG,CACzG,CAAC;QACJ,CAAC;QAED,uEAAuE;QACvE,uEAAuE;QACvE,gBAAgB;QAChB,EAAE;QACF,wEAAwE;QACxE,0EAA0E;QAC1E,gEAAgE;QAChE,4EAA4E;QAC5E,4EAA4E;QAC5E,4EAA4E;QAC5E,gDAAgD;QAChD,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAChE,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC;YAC3D,IAAI,EAAE,UAAU;YAChB,iBAAiB,EAAE,eAAe,CAAC,EAAE;YACrC,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzE,CAAC,CAAC;QAEH,OAAO;YACL,eAAe;YACf,kBAAkB,EAAE,OAAO,CAAC,WAAW;YACvC,gBAAgB,EAAE,OAAO,CAAC,SAAS;SACpC,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ import type { CustomerDeletionService } from '../services/customer-deletion-service.js';
2
+ /**
3
+ * AnonymizationSweepWorker — repeatable job that permanently anonymizes
4
+ * soft-deleted customer accounts once their retention window has elapsed
5
+ * (feature 040, US7 / FR-040). Mirrors the carts abandonment-sweep pattern:
6
+ * a thin class exposing `sweep()` so it can be driven by a scheduler or a CLI
7
+ * entry point. Returns the number of accounts anonymized.
8
+ */
9
+ export declare class AnonymizationSweepWorker {
10
+ private readonly deletion;
11
+ private readonly resolveRetentionDays;
12
+ constructor(deletion: CustomerDeletionService, resolveRetentionDays: () => Promise<number>);
13
+ sweep(now?: Date): Promise<number>;
14
+ }
15
+ //# sourceMappingURL=anonymization-sweep-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymization-sweep-worker.d.ts","sourceRoot":"","sources":["../../../src/backend/workers/anonymization-sweep-worker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AAExF;;;;;;GAMG;AACH,qBAAa,wBAAwB;IAEjC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,oBAAoB;gBADpB,QAAQ,EAAE,uBAAuB,EACjC,oBAAoB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC;IAGxD,KAAK,CAAC,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;CAIrD"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * AnonymizationSweepWorker — repeatable job that permanently anonymizes
3
+ * soft-deleted customer accounts once their retention window has elapsed
4
+ * (feature 040, US7 / FR-040). Mirrors the carts abandonment-sweep pattern:
5
+ * a thin class exposing `sweep()` so it can be driven by a scheduler or a CLI
6
+ * entry point. Returns the number of accounts anonymized.
7
+ */
8
+ export class AnonymizationSweepWorker {
9
+ deletion;
10
+ resolveRetentionDays;
11
+ constructor(deletion, resolveRetentionDays) {
12
+ this.deletion = deletion;
13
+ this.resolveRetentionDays = resolveRetentionDays;
14
+ }
15
+ async sweep(now = new Date()) {
16
+ const retentionDays = await this.resolveRetentionDays();
17
+ return this.deletion.sweep(retentionDays, now);
18
+ }
19
+ }
20
+ //# sourceMappingURL=anonymization-sweep-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymization-sweep-worker.js","sourceRoot":"","sources":["../../../src/backend/workers/anonymization-sweep-worker.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,OAAO,wBAAwB;IAEhB;IACA;IAFnB,YACmB,QAAiC,EACjC,oBAA2C;QAD3C,aAAQ,GAAR,QAAQ,CAAyB;QACjC,yBAAoB,GAApB,oBAAoB,CAAuB;IAC3D,CAAC;IAEJ,KAAK,CAAC,KAAK,CAAC,MAAY,IAAI,IAAI,EAAE;QAChC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;CACF"}
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Customers (Klienci) module — feature 040.
3
+ *
4
+ * Owns the customer-lifecycle business logic and the admin + storefront
5
+ * surfaces on top of the `customer_accounts` data module: standalone
6
+ * registration, self-service (addresses, defaults, history), and admin
7
+ * oversight (block/unblock, impersonation, detail view, customer groups,
8
+ * password reset, soft-delete + restore, online presence).
9
+ *
10
+ * Three platform-wide settings are registered here and seeded by the
11
+ * module-lifecycle ManifestReconciler on boot.
12
+ */
13
+ export declare const CUSTOMERS_SETTING_CODES: {
14
+ /** Gate standalone (org-less) registration (FR-001/FR-004). */
15
+ readonly ALLOW_REGISTRATION_WITHOUT_ORGANIZATION: "customers.allow_registration_without_organization";
16
+ /** Restore window (days) before permanent anonymization (FR-041). */
17
+ readonly DELETION_RETENTION_DAYS: "customers.deletion_retention_days";
18
+ /** "Online" threshold (minutes) for the admin presence view. */
19
+ readonly PRESENCE_FRESHNESS_MINUTES: "customers.presence_freshness_minutes";
20
+ };
21
+ export declare const manifest: {
22
+ id: string;
23
+ name: string;
24
+ version: string;
25
+ dependencies: string[];
26
+ description?: string | undefined;
27
+ acknowledgedDependencies?: {
28
+ moduleId: string;
29
+ port: string;
30
+ reason: string;
31
+ }[] | undefined;
32
+ nonBindingDependencies?: {
33
+ moduleId: string;
34
+ name: string;
35
+ kind: "contributes-to" | "degrades-without" | "refuses-without";
36
+ reason: string;
37
+ whenAbsent?: string | undefined;
38
+ }[] | undefined;
39
+ activation?: {
40
+ settingCode: string;
41
+ default: boolean;
42
+ } | {
43
+ nonDeactivatable: true;
44
+ reason: string;
45
+ } | undefined;
46
+ settings?: {
47
+ moduleCode: string;
48
+ groups: {
49
+ code: string;
50
+ name: string;
51
+ salesChannelCodes?: string[] | undefined;
52
+ isSystemProtected?: boolean | undefined;
53
+ }[];
54
+ settings: {
55
+ code: string;
56
+ name: string;
57
+ valueType: "string" | "number" | "boolean" | "json" | "string_list" | "secret" | "credential_ref";
58
+ defaultValue: unknown;
59
+ description?: string | undefined;
60
+ groupCode?: string | undefined;
61
+ previousDefaultValues?: unknown[] | undefined;
62
+ salesChannelCodes?: string[] | undefined;
63
+ enumOptions?: string[] | undefined;
64
+ configurationType?: string | undefined;
65
+ hidden?: boolean | undefined;
66
+ }[];
67
+ } | undefined;
68
+ i18n?: {
69
+ bundlesDir: string;
70
+ } | undefined;
71
+ docs?: false | {
72
+ dir: string;
73
+ } | undefined;
74
+ demo?: false | {
75
+ summary: string;
76
+ seed: (context: import("@endora-commerce/contracts").ModuleDemoContext<never>) => Promise<import("@endora-commerce/contracts").DemoSeedResult>;
77
+ reset: (context: import("@endora-commerce/contracts").ModuleDemoContext<never>) => Promise<import("@endora-commerce/contracts").DemoResetResult>;
78
+ after?: readonly string[] | undefined;
79
+ package?: string | undefined;
80
+ } | undefined;
81
+ actions?: {
82
+ id: string;
83
+ labelKey: string;
84
+ icon: "Plus" | "Sparkles" | "Settings" | "Search" | "Boxes" | "Layers" | "Menu" | "PlusCircle" | "PlusSquare" | "FilePlus" | "FolderPlus" | "Upload" | "FileUp" | "CloudUpload" | "Download" | "FileDown" | "FileText" | "BookOpen" | "Rss" | "Package" | "Tag" | "ShoppingCart" | "Receipt" | "CreditCard" | "Users" | "UserPlus" | "Inbox" | "ListChecks" | "ClipboardList" | "Image" | "Video" | "LayoutDashboard" | "PanelLeft" | "KeyRound" | "ShieldCheck" | "Edit" | "Archive" | "Box" | "Truck" | "CircleDollarSign" | "Activity" | "LineChart" | "Smartphone" | "Webhook" | "Scale" | "PlugZap" | "PercentDiamond" | "Newspaper" | "Languages" | "Eraser" | "Warehouse" | "TrendingDown" | "Bell" | "PackageOpen" | "Building2" | "Store" | "ClipboardCheck";
85
+ targetRoute: string;
86
+ keywords: string[];
87
+ weight: number;
88
+ descriptionKey?: string | undefined;
89
+ requiredPermission?: string | undefined;
90
+ }[] | undefined;
91
+ permissions?: {
92
+ code: string;
93
+ label: string;
94
+ module?: string | undefined;
95
+ description?: string | undefined;
96
+ requires?: string[] | undefined;
97
+ }[] | undefined;
98
+ transactionalEmails?: {
99
+ code: string;
100
+ name: string;
101
+ variables: {
102
+ key: string;
103
+ label: string;
104
+ sampleValue?: string | undefined;
105
+ description?: string | undefined;
106
+ }[];
107
+ description?: string | undefined;
108
+ group?: string | undefined;
109
+ }[] | undefined;
110
+ capabilities?: string[] | undefined;
111
+ exclusiveCapabilities?: {
112
+ key: string;
113
+ errorCode: string;
114
+ }[] | undefined;
115
+ errorCodes?: {
116
+ code: string;
117
+ tokens?: string[] | undefined;
118
+ }[] | undefined;
119
+ blocks?: {
120
+ name: string;
121
+ labelKey: string;
122
+ category: string;
123
+ contexts: ("email" | "invoice" | "cms" | "newsletter")[];
124
+ fields: Record<string, {
125
+ type: "number" | "object" | "array" | "text" | "textarea" | "select" | "radio" | "external" | "uuid" | "richtext";
126
+ label?: string | undefined;
127
+ required?: boolean | undefined;
128
+ options?: {
129
+ label: string;
130
+ value: string | number;
131
+ }[] | undefined;
132
+ refKind?: string | undefined;
133
+ }>;
134
+ descriptionKey?: string | undefined;
135
+ defaultProps?: Record<string, unknown> | undefined;
136
+ responsiveFields?: string[] | undefined;
137
+ previewIcon?: string | undefined;
138
+ weight?: number | undefined;
139
+ }[] | undefined;
140
+ blockCategories?: {
141
+ key: string;
142
+ titleKey: string;
143
+ contexts: ("email" | "invoice" | "cms" | "newsletter")[];
144
+ weight?: number | undefined;
145
+ visible?: boolean | undefined;
146
+ }[] | undefined;
147
+ env?: {
148
+ name: string;
149
+ describes: {
150
+ en: string;
151
+ pl: string;
152
+ };
153
+ requirement: {
154
+ kind: "required";
155
+ } | {
156
+ kind: "requiredWhen";
157
+ input: string;
158
+ equals: string;
159
+ } | {
160
+ kind: "optional";
161
+ without: {
162
+ en: string;
163
+ pl: string;
164
+ };
165
+ };
166
+ secret: boolean;
167
+ generable: boolean;
168
+ owner: {
169
+ kind: "platform";
170
+ } | {
171
+ kind: "application";
172
+ application: "admin" | "backend" | "storefront";
173
+ } | {
174
+ kind: "module";
175
+ moduleId: string;
176
+ };
177
+ consumers: ("admin" | "backend" | "storefront")[];
178
+ addressOf: "admin" | "backend" | "storefront" | null;
179
+ }[] | undefined;
180
+ };
181
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,uBAAuB;IAClC,+DAA+D;;IAG/D,qEAAqE;;IAErE,gEAAgE;;CAExD,CAAC;AAoCX,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4InB,CAAC"}
@@ -0,0 +1,192 @@
1
+ import { defineModuleManifest, defineModuleSettingsManifest, } from '@endora-commerce/contracts';
2
+ /**
3
+ * Customers (Klienci) module — feature 040.
4
+ *
5
+ * Owns the customer-lifecycle business logic and the admin + storefront
6
+ * surfaces on top of the `customer_accounts` data module: standalone
7
+ * registration, self-service (addresses, defaults, history), and admin
8
+ * oversight (block/unblock, impersonation, detail view, customer groups,
9
+ * password reset, soft-delete + restore, online presence).
10
+ *
11
+ * Three platform-wide settings are registered here and seeded by the
12
+ * module-lifecycle ManifestReconciler on boot.
13
+ */
14
+ export const CUSTOMERS_SETTING_CODES = {
15
+ /** Gate standalone (org-less) registration (FR-001/FR-004). */
16
+ ALLOW_REGISTRATION_WITHOUT_ORGANIZATION: 'customers.allow_registration_without_organization',
17
+ /** Restore window (days) before permanent anonymization (FR-041). */
18
+ DELETION_RETENTION_DAYS: 'customers.deletion_retention_days',
19
+ /** "Online" threshold (minutes) for the admin presence view. */
20
+ PRESENCE_FRESHNESS_MINUTES: 'customers.presence_freshness_minutes',
21
+ };
22
+ const settings = defineModuleSettingsManifest({
23
+ moduleCode: 'customers',
24
+ groups: [{ code: 'customers', name: 'Customers' }],
25
+ settings: [
26
+ {
27
+ code: CUSTOMERS_SETTING_CODES.ALLOW_REGISTRATION_WITHOUT_ORGANIZATION,
28
+ name: 'Allow registration without organization',
29
+ description: 'When enabled, visitors may register a standalone Customer account that is not attached to any Organization. When disabled, registration requires Organization context.',
30
+ groupCode: 'customers',
31
+ valueType: 'boolean',
32
+ defaultValue: false,
33
+ },
34
+ {
35
+ code: CUSTOMERS_SETTING_CODES.DELETION_RETENTION_DAYS,
36
+ name: 'Customer deletion retention window (days)',
37
+ description: 'Number of days a deleted Customer account can be restored before its personal data is permanently anonymized. Default 365 (1 year).',
38
+ groupCode: 'customers',
39
+ valueType: 'number',
40
+ defaultValue: 365,
41
+ },
42
+ {
43
+ code: CUSTOMERS_SETTING_CODES.PRESENCE_FRESHNESS_MINUTES,
44
+ name: 'Online customers freshness (minutes)',
45
+ description: 'A Customer counts as "online" if their session was active within this many minutes. Default 10.',
46
+ groupCode: 'customers',
47
+ valueType: 'number',
48
+ defaultValue: 10,
49
+ },
50
+ ],
51
+ });
52
+ export const manifest = defineModuleManifest({
53
+ id: 'customers',
54
+ name: 'Customers',
55
+ description: 'Customer lifecycle business logic: registration, self-service, blocking, impersonation, groups, deletion, and presence.',
56
+ version: '1.0.0',
57
+ // Feature 072 (T140) — the edges the module actually resolves. `auth`
58
+ // (sessions), `email` (the set-password mail), `quote_requests` (the RFQ
59
+ // history surface) and `custom_fields` were all reached through options a
60
+ // root passed down, which is why none of them appeared here.
61
+ // Feature 073 (Constitution XVII) — the operator's activation control. This
62
+ // is the *management* surface over customer accounts: the admin CRM screens,
63
+ // moderation, self-service profile and deletion. The accounts themselves live
64
+ // in `customer_accounts`, which is non-deactivatable, so switching this off
65
+ // removes screens and self-service rather than the ability to log in.
66
+ activation: { settingCode: 'customers.enabled', default: true },
67
+ //
68
+ // Issue #216 adds `quick_order`: the customer-detail screen and the
69
+ // self-service profile render and edit a buyer's default payment and
70
+ // delivery method, and those live in `quick_order`'s preference store. This
71
+ // module used to build a second instance of that module's service instead of
72
+ // resolving the port published for it, so the edge existed and was declared
73
+ // nowhere. Binding rather than `degrades-without`, because that is what
74
+ // `DefaultPreferencePort`'s contract says its seam does when the owner is
75
+ // off, and because a half-written set of ordering defaults is worse than a
76
+ // refusal.
77
+ //
78
+ // Feature 075's Phase-C cut adds `addresses`: the self-service and admin
79
+ // address panels list the buyer's **organisation's** shared addresses beside
80
+ // their personal ones, and this module used to query that module's table
81
+ // itself. It reads `addressReadPort` now. Binding, and unremarkably so —
82
+ // `addresses` is non-deactivatable, so the edge has no absent state to
83
+ // declare a degrade for.
84
+ //
85
+ // Feature 075's cut adds three more, each replacing a second instance this
86
+ // module built from an import of the owner's directory or a query against its
87
+ // table: `admin_users` (the impersonation seam behind the "view as this
88
+ // customer" control), `carts` (the reporting read behind the customer-detail
89
+ // cart panel) and `orders` (the list behind both order-history panels).
90
+ //
91
+ // All three are binding, and unremarkably so: every one of them declares
92
+ // `nonDeactivatable`, so none has an absent state for a degrade to describe.
93
+ // The `orders` edge in particular used to be a `degrades-without` whose
94
+ // reason argued that declaring it "would make `orders` undeactivatable" — a
95
+ // sentence about a module that has never had an activation control, kept
96
+ // alive by a presence probe that could not fire. It is a declared dependency
97
+ // now, and the panels read the gated port directly.
98
+ dependencies: [
99
+ 'addresses',
100
+ // `specs/117-instance-bring-up/` Phase 6 — `customerModerationActorResolver`
101
+ // is this module's own since FR-033, and it reads the moderating admin's
102
+ // role through `adminRolePort` beside the `adminUserReadPort` already
103
+ // declared below. The production root asked the same question in
104
+ // `knex.raw` over both tables; a port needs the edge and the SQL never
105
+ // declared one. `admin_roles` declares `activation.nonDeactivatable`, so
106
+ // the edge costs no operator an activation control.
107
+ 'admin_roles',
108
+ 'admin_users',
109
+ 'auth',
110
+ 'carts',
111
+ 'custom_fields',
112
+ 'customer_accounts',
113
+ 'email',
114
+ 'orders',
115
+ 'organizations',
116
+ 'quick_order',
117
+ 'quote_requests',
118
+ 'settings',
119
+ ],
120
+ settings,
121
+ i18n: { bundlesDir: 'i18n' },
122
+ docs: { dir: 'docs' },
123
+ /**
124
+ * Two codes from the platform block — D-129's remaining sweep, Tier A
125
+ * (`specs/090-module-owned-error-codes/d129-sweep.md` §5.2, Appendix A;
126
+ * MR 3).
127
+ *
128
+ * Both were declared by `_i18n` until this merge request, not because
129
+ * anybody judged them the platform's but because the deleted prefix chain
130
+ * had no rule for them and its last line was `return 'core'`.
131
+ *
132
+ * **`CUSTOMER_ADDRESS_NOT_FOUND` is here and the four `CUSTOMER_*` record
133
+ * codes are not, and that split is a ruling rather than a reading.** D-186
134
+ * §1 (`specs/080-f4-real-scope/rulings.md`) settles the noun "customer":
135
+ * `customer_accounts` owns the **record**, this module owns
136
+ * **`CustomerAddress`**. So `CUSTOMER_NOT_FOUND`,
137
+ * `CUSTOMER_ALREADY_DELETED`, `CUSTOMER_NOT_DELETED` and
138
+ * `CUSTOMER_RESTORE_WINDOW_ELAPSED` go to `customer_accounts` in a later
139
+ * batch — two of them raised from *this* module, which is the consequence
140
+ * the ruling accepts in terms and the shape D-95.2 already ruled for
141
+ * `INVOICE_NOT_READY`: the owner of a noun is not required to be the module
142
+ * that throws about it. The prefix is the same in all five; the noun is not,
143
+ * and the noun is what decides.
144
+ *
145
+ * **`REGISTRATION_REQUIRES_ORGANIZATION` is T2, not T1.** Its noun is a
146
+ * registration and an Organization, and `organizations` owns the second — so
147
+ * T1 has two claimants and does not decide it. T2 does: the code names a
148
+ * *mechanism*, the storefront's standalone self-registration path, which
149
+ * this module implements in `customer-registration-service.ts` and is the
150
+ * only thing in the tree that raises. What it refuses is this module's own
151
+ * setting being off, not a judgement `organizations` makes.
152
+ *
153
+ * **No sentence moves with them.** Neither has a sentence in either language
154
+ * anywhere in the tree; both were already on `UNTRANSLATED_ERROR_CODES`
155
+ * under `_i18n` and move to this module's group there, so the bundle this
156
+ * module already ships gains no key. The storefront's registration page
157
+ * carries its own copy for the refusal
158
+ * (`storefront/app/(auth)/register-customer/page.tsx`), which is a surface
159
+ * string and not the envelope's sentence.
160
+ *
161
+ * **`tokens` is derived from the raise sites, not from the bundle**
162
+ * (runbook §5), and there are none: both raises are a bare
163
+ * `HttpError(status, code, message)` with no `details`.
164
+ */
165
+ errorCodes: [
166
+ { code: 'CUSTOMER_ADDRESS_NOT_FOUND' },
167
+ { code: 'REGISTRATION_REQUIRES_ORGANIZATION' },
168
+ ],
169
+ actions: [
170
+ {
171
+ id: 'open-customers',
172
+ labelKey: 'actions.openCustomers.label',
173
+ descriptionKey: 'actions.openCustomers.description',
174
+ icon: 'Users',
175
+ targetRoute: '/customers',
176
+ requiredPermission: 'customers:read',
177
+ keywords: ['customers', 'clients', 'klienci', 'klient'],
178
+ weight: 210,
179
+ },
180
+ {
181
+ id: 'online-customers',
182
+ labelKey: 'actions.onlineCustomers.label',
183
+ descriptionKey: 'actions.onlineCustomers.description',
184
+ icon: 'Users',
185
+ targetRoute: '/customers/online',
186
+ requiredPermission: 'customers:read',
187
+ keywords: ['online', 'presence', 'aktywni', 'online klienci'],
188
+ weight: 205,
189
+ },
190
+ ],
191
+ });
192
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}