@endora-commerce/mod-customer-accounts 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.
- package/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/admin/api/customer-groups-client.d.ts +27 -0
- package/dist/admin/api/customer-groups-client.d.ts.map +1 -0
- package/dist/admin/api/customer-groups-client.js +17 -0
- package/dist/admin/api/customer-groups-client.js.map +1 -0
- package/dist/admin/index.d.ts +33 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +38 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/CustomerGroupsPage.d.ts +18 -0
- package/dist/admin/pages/CustomerGroupsPage.d.ts.map +1 -0
- package/dist/admin/pages/CustomerGroupsPage.js +108 -0
- package/dist/admin/pages/CustomerGroupsPage.js.map +1 -0
- package/dist/backend/entities/customer-account.entity.d.ts +111 -0
- package/dist/backend/entities/customer-account.entity.d.ts.map +1 -0
- package/dist/backend/entities/customer-account.entity.js +230 -0
- package/dist/backend/entities/customer-account.entity.js.map +1 -0
- package/dist/backend/entities/customer-group.entity.d.ts +29 -0
- package/dist/backend/entities/customer-group.entity.d.ts.map +1 -0
- package/dist/backend/entities/customer-group.entity.js +70 -0
- package/dist/backend/entities/customer-group.entity.js.map +1 -0
- package/dist/backend/entities/password-reset-token.entity.d.ts +16 -0
- package/dist/backend/entities/password-reset-token.entity.d.ts.map +1 -0
- package/dist/backend/entities/password-reset-token.entity.js +59 -0
- package/dist/backend/entities/password-reset-token.entity.js.map +1 -0
- package/dist/backend/index.d.ts +144 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +407 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +26 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +35 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/services/audit-references.d.ts +22 -0
- package/dist/backend/services/audit-references.d.ts.map +1 -0
- package/dist/backend/services/audit-references.js +46 -0
- package/dist/backend/services/audit-references.js.map +1 -0
- package/dist/backend/services/customer-account-lifecycle-ports.d.ts +168 -0
- package/dist/backend/services/customer-account-lifecycle-ports.d.ts.map +1 -0
- package/dist/backend/services/customer-account-lifecycle-ports.js +420 -0
- package/dist/backend/services/customer-account-lifecycle-ports.js.map +1 -0
- package/dist/backend/services/customer-account-ports.d.ts +143 -0
- package/dist/backend/services/customer-account-ports.d.ts.map +1 -0
- package/dist/backend/services/customer-account-ports.js +422 -0
- package/dist/backend/services/customer-account-ports.js.map +1 -0
- package/dist/backend/services/customer-auth-service.d.ts +62 -0
- package/dist/backend/services/customer-auth-service.d.ts.map +1 -0
- package/dist/backend/services/customer-auth-service.js +105 -0
- package/dist/backend/services/customer-auth-service.js.map +1 -0
- package/dist/backend/services/customer-group-read-port.d.ts +24 -0
- package/dist/backend/services/customer-group-read-port.d.ts.map +1 -0
- package/dist/backend/services/customer-group-read-port.js +44 -0
- package/dist/backend/services/customer-group-read-port.js.map +1 -0
- package/dist/backend/services/customer-group-service.d.ts +21 -0
- package/dist/backend/services/customer-group-service.d.ts.map +1 -0
- package/dist/backend/services/customer-group-service.js +97 -0
- package/dist/backend/services/customer-group-service.js.map +1 -0
- package/dist/backend/services/customer-rollup-scope.d.ts +30 -0
- package/dist/backend/services/customer-rollup-scope.d.ts.map +1 -0
- package/dist/backend/services/customer-rollup-scope.js +42 -0
- package/dist/backend/services/customer-rollup-scope.js.map +1 -0
- package/dist/backend/services/password-reset-service.d.ts +15 -0
- package/dist/backend/services/password-reset-service.d.ts.map +1 -0
- package/dist/backend/services/password-reset-service.js +90 -0
- package/dist/backend/services/password-reset-service.js.map +1 -0
- package/dist/backend/services/role-service.d.ts +22 -0
- package/dist/backend/services/role-service.d.ts.map +1 -0
- package/dist/backend/services/role-service.js +83 -0
- package/dist/backend/services/role-service.js.map +1 -0
- package/dist/backend/services/two-factor-enrolments.d.ts +18 -0
- package/dist/backend/services/two-factor-enrolments.d.ts.map +1 -0
- package/dist/backend/services/two-factor-enrolments.js +2 -0
- package/dist/backend/services/two-factor-enrolments.js.map +1 -0
- package/dist/manifest.d.ts +169 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +212 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260425T055041_customer_accounts_password_reset_tokens.d.ts +6 -0
- package/dist/migrations/20260425T055041_customer_accounts_password_reset_tokens.d.ts.map +1 -0
- package/dist/migrations/20260425T055041_customer_accounts_password_reset_tokens.js +25 -0
- package/dist/migrations/20260425T055041_customer_accounts_password_reset_tokens.js.map +1 -0
- package/dist/migrations/20260611T140351_customer_accounts_organization_optional.d.ts +34 -0
- package/dist/migrations/20260611T140351_customer_accounts_organization_optional.d.ts.map +1 -0
- package/dist/migrations/20260611T140351_customer_accounts_organization_optional.js +43 -0
- package/dist/migrations/20260611T140351_customer_accounts_organization_optional.js.map +1 -0
- package/dist/migrations/20260611T140403_customer_accounts_lifecycle.d.ts +54 -0
- package/dist/migrations/20260611T140403_customer_accounts_lifecycle.d.ts.map +1 -0
- package/dist/migrations/20260611T140403_customer_accounts_lifecycle.js +97 -0
- package/dist/migrations/20260611T140403_customer_accounts_lifecycle.js.map +1 -0
- package/dist/migrations/20260718T200341_customer_accounts_customer_account_custom_field_values.d.ts +12 -0
- package/dist/migrations/20260718T200341_customer_accounts_customer_account_custom_field_values.d.ts.map +1 -0
- package/dist/migrations/20260718T200341_customer_accounts_customer_account_custom_field_values.js +16 -0
- package/dist/migrations/20260718T200341_customer_accounts_customer_account_custom_field_values.js.map +1 -0
- package/dist/migrations/20260720T044255_customer_accounts_customer_subtree_rollup.d.ts +14 -0
- package/dist/migrations/20260720T044255_customer_accounts_customer_subtree_rollup.d.ts.map +1 -0
- package/dist/migrations/20260720T044255_customer_accounts_customer_subtree_rollup.js +18 -0
- package/dist/migrations/20260720T044255_customer_accounts_customer_subtree_rollup.js.map +1 -0
- package/dist/migrations/20260819T074816_customer_accounts_password_set_at.d.ts +22 -0
- package/dist/migrations/20260819T074816_customer_accounts_password_set_at.d.ts.map +1 -0
- package/dist/migrations/20260819T074816_customer_accounts_password_set_at.js +26 -0
- package/dist/migrations/20260819T074816_customer_accounts_password_set_at.js.map +1 -0
- package/dist/migrations/20260819T142837_customer_accounts_fold_email_case.d.ts +46 -0
- package/dist/migrations/20260819T142837_customer_accounts_fold_email_case.d.ts.map +1 -0
- package/dist/migrations/20260819T142837_customer_accounts_fold_email_case.js +97 -0
- package/dist/migrations/20260819T142837_customer_accounts_fold_email_case.js.map +1 -0
- package/dist/migrations/20260825T124759_customer_accounts_drop_legacy_two_factor_secret.d.ts +31 -0
- package/dist/migrations/20260825T124759_customer_accounts_drop_legacy_two_factor_secret.d.ts.map +1 -0
- package/dist/migrations/20260825T124759_customer_accounts_drop_legacy_two_factor_secret.js +35 -0
- package/dist/migrations/20260825T124759_customer_accounts_drop_legacy_two_factor_secret.js.map +1 -0
- package/dist/migrations/20260825T141659_customer_accounts_organization_required.d.ts +58 -0
- package/dist/migrations/20260825T141659_customer_accounts_organization_required.d.ts.map +1 -0
- package/dist/migrations/20260825T141659_customer_accounts_organization_required.js +133 -0
- package/dist/migrations/20260825T141659_customer_accounts_organization_required.js.map +1 -0
- package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.d.ts +27 -0
- package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.d.ts.map +1 -0
- package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.js +44 -0
- package/dist/migrations/20260912T094701_customer_accounts_sales_channel_customer_accounts.js.map +1 -0
- package/dist/migrations/index.d.ts +36 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +47 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/customer_accounts.md +38 -0
- package/i18n/en.json +30 -0
- package/i18n/pl.json +30 -0
- package/package.json +94 -0
- package/tailwind.css +14 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Entity, Index, OptionalProps, PrimaryKey, Property, Unique } from '@mikro-orm/core';
|
|
11
|
+
import { OrgScoped } from '@endora-commerce/platform/tenancy';
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
13
|
+
/**
|
|
14
|
+
* CustomerAccount — a user inside an Organization. One email ⇒ at most one
|
|
15
|
+
* CustomerAccount installation-wide (FR-041).
|
|
16
|
+
*
|
|
17
|
+
* `passwordHash` is an argon2id-derived key (see services/password-hasher.ts
|
|
18
|
+
* in the auth module).
|
|
19
|
+
*/
|
|
20
|
+
let CustomerAccount = class CustomerAccount {
|
|
21
|
+
[OptionalProps];
|
|
22
|
+
id = randomUUID();
|
|
23
|
+
/**
|
|
24
|
+
* The tenant that scopes this account, and the platform's single unit of
|
|
25
|
+
* tenancy (Principle XI).
|
|
26
|
+
*
|
|
27
|
+
* **Not nullable, since D-178.** Feature 026 US2 relaxed it so the platform
|
|
28
|
+
* could serve "no-org / guest-style" accounts falling back to platform
|
|
29
|
+
* defaults for prices, credit limit, allowed payment and delivery methods and
|
|
30
|
+
* warehouse visibility. Feature 051 replaced that design: an individual (B2C)
|
|
31
|
+
* customer is backed by a single-member **personal** organisation, so the
|
|
32
|
+
* guard always has a concrete tenant and there is no "no-organization"
|
|
33
|
+
* scoping path. The column stayed nullable for another year and three write
|
|
34
|
+
* paths went on producing NULLs — self-registration's two-flush window,
|
|
35
|
+
* federated sign-in (which provisioned no organisation at all), and an admin
|
|
36
|
+
* "un-assign" button. All three are closed, and the column is `NOT NULL`,
|
|
37
|
+
* which is the only refusal available: MikroORM applies its tenant filter to
|
|
38
|
+
* `SELECT` / `UPDATE` / `DELETE` and not to `INSERT`, so nothing in the guard
|
|
39
|
+
* can stop a tenant-less row being written.
|
|
40
|
+
*
|
|
41
|
+
* The account and its organisation are created in **one transaction** — see
|
|
42
|
+
* `CustomerAccountLifecycleWriteService.createStandalone` and the
|
|
43
|
+
* federated-sign-in `autoCreate` in this module's `backend.ts`.
|
|
44
|
+
*/
|
|
45
|
+
organizationId;
|
|
46
|
+
email;
|
|
47
|
+
passwordHash;
|
|
48
|
+
/**
|
|
49
|
+
* Issue #222 — when a password somebody supplied was last set on this
|
|
50
|
+
* account. `null` means "no such password is on record", which covers both
|
|
51
|
+
* the account federated sign-in auto-created (its hash is a random pair of
|
|
52
|
+
* UUIDs nobody was told) and every row written before this column existed.
|
|
53
|
+
*
|
|
54
|
+
* It exists because `passwordHash` is NOT NULL for *every* account and
|
|
55
|
+
* therefore answers a different question from the one that matters on a
|
|
56
|
+
* security surface: whether the holder has a credential they can actually
|
|
57
|
+
* use. `SocialLinkService` is the first reader — it refuses to sever an
|
|
58
|
+
* account's last federated identity while this is null.
|
|
59
|
+
*
|
|
60
|
+
* Stamped by every write of a caller-supplied password (registration, the
|
|
61
|
+
* member write port, a redeemed reset token, a self-service change) and
|
|
62
|
+
* deliberately **not** by the generated hash. The anonymization sweep clears
|
|
63
|
+
* it back to null with the hash it scrubs.
|
|
64
|
+
*/
|
|
65
|
+
passwordSetAt;
|
|
66
|
+
firstName;
|
|
67
|
+
lastName;
|
|
68
|
+
role = 'regular_user';
|
|
69
|
+
emailVerifiedAt;
|
|
70
|
+
/**
|
|
71
|
+
* Never written, and since 2026-08-28 never **read** either.
|
|
72
|
+
*
|
|
73
|
+
* Its only non-null writer was the superseded customer 2FA path, deleted with
|
|
74
|
+
* `two_factor_secret`, so the published `twoFactorEnabled` derived from it
|
|
75
|
+
* was a provably constant `false` — including on `GET /api/v1/me/customer`,
|
|
76
|
+
* which told a buyer their own account was unprotected while it was not.
|
|
77
|
+
* `CustomerAccountRecord.twoFactorEnabled` is now the live `mfa` enrolment,
|
|
78
|
+
* read through `mfaEnrolmentStatePort`, and nothing in the tree reads this
|
|
79
|
+
* column.
|
|
80
|
+
*
|
|
81
|
+
* It is dead schema kept for one more step: dropping it is a migration on
|
|
82
|
+
* this module's table and is deliberately not folded into the repair of the
|
|
83
|
+
* five derivation sites. Do not read it — the honest answer is `mfa`'s.
|
|
84
|
+
*/
|
|
85
|
+
twoFactorConfirmedAt;
|
|
86
|
+
lastLoginAt;
|
|
87
|
+
createdAt = new Date();
|
|
88
|
+
updatedAt = new Date();
|
|
89
|
+
// Feature 055 — Custom Fields Layer value bag (inherits host tenant scope).
|
|
90
|
+
customFieldValues = {};
|
|
91
|
+
deletedAt;
|
|
92
|
+
// ── Feature 040 (Customers) lifecycle extensions ────────────────────────
|
|
93
|
+
/**
|
|
94
|
+
* Direct customer→customer-group membership (FR-022). Independent of the
|
|
95
|
+
* Organization's group: the effective pricing group is
|
|
96
|
+
* `customerGroupId ?? organization.customerGroupId`. FK to `customer_groups`
|
|
97
|
+
* (owned by price_lists), ON DELETE SET NULL.
|
|
98
|
+
*/
|
|
99
|
+
customerGroupId;
|
|
100
|
+
/**
|
|
101
|
+
* Feature 056 (T032) — customer-side roll-up capability. When `true`, this
|
|
102
|
+
* login sees/acts across its organization's **subtree** (the tenant scope is
|
|
103
|
+
* widened from single-org to `allowed-set(subtreeIds(theirOrg))` server-side,
|
|
104
|
+
* Principle XI). Default `false` ⇒ node-only (flat behavior). Set only by a
|
|
105
|
+
* platform admin on the org member surface; mirrors the admin/sales-rep
|
|
106
|
+
* `organizations:rollup` capability for a buyer account.
|
|
107
|
+
*/
|
|
108
|
+
subtreeRollupEnabled = false;
|
|
109
|
+
/** Non-null ⇒ the account is blocked and login is denied (FR-012/FR-016). */
|
|
110
|
+
blockedAt;
|
|
111
|
+
blockReason;
|
|
112
|
+
/** Who applied the block — drives unblock authority (FR-013/FR-015). */
|
|
113
|
+
blockSource;
|
|
114
|
+
blockedByAdminUserId;
|
|
115
|
+
blockedByCustomerAccountId;
|
|
116
|
+
/** Admin who soft-deleted the account (paired with `deletedAt`, FR-039). */
|
|
117
|
+
deletionRequestedByAdminUserId;
|
|
118
|
+
/**
|
|
119
|
+
* Non-null ⇒ PII has been irreversibly scrubbed by the anonymization sweep
|
|
120
|
+
* after the retention window; restore is no longer possible (FR-040).
|
|
121
|
+
*/
|
|
122
|
+
anonymizedAt;
|
|
123
|
+
};
|
|
124
|
+
__decorate([
|
|
125
|
+
PrimaryKey({ type: 'uuid' }),
|
|
126
|
+
__metadata("design:type", String)
|
|
127
|
+
], CustomerAccount.prototype, "id", void 0);
|
|
128
|
+
__decorate([
|
|
129
|
+
Property({ type: 'uuid' }),
|
|
130
|
+
Index(),
|
|
131
|
+
__metadata("design:type", String)
|
|
132
|
+
], CustomerAccount.prototype, "organizationId", void 0);
|
|
133
|
+
__decorate([
|
|
134
|
+
Property({ type: 'string', length: 320 }),
|
|
135
|
+
Unique(),
|
|
136
|
+
__metadata("design:type", String)
|
|
137
|
+
], CustomerAccount.prototype, "email", void 0);
|
|
138
|
+
__decorate([
|
|
139
|
+
Property({ type: 'string', length: 512 }),
|
|
140
|
+
__metadata("design:type", String)
|
|
141
|
+
], CustomerAccount.prototype, "passwordHash", void 0);
|
|
142
|
+
__decorate([
|
|
143
|
+
Property({ type: 'datetime', nullable: true }),
|
|
144
|
+
__metadata("design:type", Object)
|
|
145
|
+
], CustomerAccount.prototype, "passwordSetAt", void 0);
|
|
146
|
+
__decorate([
|
|
147
|
+
Property({ type: 'string', length: 120 }),
|
|
148
|
+
__metadata("design:type", String)
|
|
149
|
+
], CustomerAccount.prototype, "firstName", void 0);
|
|
150
|
+
__decorate([
|
|
151
|
+
Property({ type: 'string', length: 120 }),
|
|
152
|
+
__metadata("design:type", String)
|
|
153
|
+
], CustomerAccount.prototype, "lastName", void 0);
|
|
154
|
+
__decorate([
|
|
155
|
+
Property({ type: 'string', length: 32 }),
|
|
156
|
+
Index(),
|
|
157
|
+
__metadata("design:type", String)
|
|
158
|
+
], CustomerAccount.prototype, "role", void 0);
|
|
159
|
+
__decorate([
|
|
160
|
+
Property({ type: 'datetime', nullable: true }),
|
|
161
|
+
__metadata("design:type", Object)
|
|
162
|
+
], CustomerAccount.prototype, "emailVerifiedAt", void 0);
|
|
163
|
+
__decorate([
|
|
164
|
+
Property({ type: 'datetime', nullable: true }),
|
|
165
|
+
__metadata("design:type", Object)
|
|
166
|
+
], CustomerAccount.prototype, "twoFactorConfirmedAt", void 0);
|
|
167
|
+
__decorate([
|
|
168
|
+
Property({ type: 'datetime', nullable: true }),
|
|
169
|
+
__metadata("design:type", Object)
|
|
170
|
+
], CustomerAccount.prototype, "lastLoginAt", void 0);
|
|
171
|
+
__decorate([
|
|
172
|
+
Property({ type: 'datetime', onCreate: () => new Date() }),
|
|
173
|
+
__metadata("design:type", Date)
|
|
174
|
+
], CustomerAccount.prototype, "createdAt", void 0);
|
|
175
|
+
__decorate([
|
|
176
|
+
Property({ type: 'datetime', onUpdate: () => new Date() }),
|
|
177
|
+
__metadata("design:type", Date)
|
|
178
|
+
], CustomerAccount.prototype, "updatedAt", void 0);
|
|
179
|
+
__decorate([
|
|
180
|
+
Property({ type: 'json' }),
|
|
181
|
+
__metadata("design:type", Object)
|
|
182
|
+
], CustomerAccount.prototype, "customFieldValues", void 0);
|
|
183
|
+
__decorate([
|
|
184
|
+
Property({ type: 'datetime', nullable: true }),
|
|
185
|
+
__metadata("design:type", Object)
|
|
186
|
+
], CustomerAccount.prototype, "deletedAt", void 0);
|
|
187
|
+
__decorate([
|
|
188
|
+
Property({ type: 'uuid', nullable: true }),
|
|
189
|
+
Index(),
|
|
190
|
+
__metadata("design:type", Object)
|
|
191
|
+
], CustomerAccount.prototype, "customerGroupId", void 0);
|
|
192
|
+
__decorate([
|
|
193
|
+
Property({ type: 'boolean' }),
|
|
194
|
+
__metadata("design:type", Boolean)
|
|
195
|
+
], CustomerAccount.prototype, "subtreeRollupEnabled", void 0);
|
|
196
|
+
__decorate([
|
|
197
|
+
Property({ type: 'datetime', nullable: true }),
|
|
198
|
+
Index(),
|
|
199
|
+
__metadata("design:type", Object)
|
|
200
|
+
], CustomerAccount.prototype, "blockedAt", void 0);
|
|
201
|
+
__decorate([
|
|
202
|
+
Property({ type: 'text', nullable: true }),
|
|
203
|
+
__metadata("design:type", Object)
|
|
204
|
+
], CustomerAccount.prototype, "blockReason", void 0);
|
|
205
|
+
__decorate([
|
|
206
|
+
Property({ type: 'string', length: 16, nullable: true }),
|
|
207
|
+
__metadata("design:type", Object)
|
|
208
|
+
], CustomerAccount.prototype, "blockSource", void 0);
|
|
209
|
+
__decorate([
|
|
210
|
+
Property({ type: 'uuid', nullable: true }),
|
|
211
|
+
__metadata("design:type", Object)
|
|
212
|
+
], CustomerAccount.prototype, "blockedByAdminUserId", void 0);
|
|
213
|
+
__decorate([
|
|
214
|
+
Property({ type: 'uuid', nullable: true }),
|
|
215
|
+
__metadata("design:type", Object)
|
|
216
|
+
], CustomerAccount.prototype, "blockedByCustomerAccountId", void 0);
|
|
217
|
+
__decorate([
|
|
218
|
+
Property({ type: 'uuid', nullable: true }),
|
|
219
|
+
__metadata("design:type", Object)
|
|
220
|
+
], CustomerAccount.prototype, "deletionRequestedByAdminUserId", void 0);
|
|
221
|
+
__decorate([
|
|
222
|
+
Property({ type: 'datetime', nullable: true }),
|
|
223
|
+
__metadata("design:type", Object)
|
|
224
|
+
], CustomerAccount.prototype, "anonymizedAt", void 0);
|
|
225
|
+
CustomerAccount = __decorate([
|
|
226
|
+
OrgScoped(),
|
|
227
|
+
Entity({ tableName: 'customer_accounts' })
|
|
228
|
+
], CustomerAccount);
|
|
229
|
+
export { CustomerAccount };
|
|
230
|
+
//# sourceMappingURL=customer-account.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customer-account.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/customer-account.entity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { OptionalProps } from '@mikro-orm/core';
|
|
2
|
+
/**
|
|
3
|
+
* CustomerGroup — the segmentation bucket a customer belongs to.
|
|
4
|
+
*
|
|
5
|
+
* A customer account carries one directly (`CustomerAccount.customerGroupId`,
|
|
6
|
+
* a real foreign key into this table with `on delete set null`) and inherits
|
|
7
|
+
* its Organization's (`Organization.customerGroupId`, an indexed column with no
|
|
8
|
+
* constraint) when it has none of its own. Groups have no behavioural state of
|
|
9
|
+
* their own; they exist as an addressable target — for the feature 011
|
|
10
|
+
* Application Rule's `customerGroup` criterion, for a promotion's audience and
|
|
11
|
+
* for a push audience rule.
|
|
12
|
+
*
|
|
13
|
+
* Feature 076 (D-79) moved this class here from `price_lists`. Table ownership
|
|
14
|
+
* resolves from the module directory the decorated class lives in — its
|
|
15
|
+
* `tableName` read out of the entity decorator below — so the move *is* the
|
|
16
|
+
* ownership change; no SQL was written, the creating migration stayed in
|
|
17
|
+
* `price_lists/migrations/`, and the foreign key from `customer_accounts`
|
|
18
|
+
* became intra-module.
|
|
19
|
+
*/
|
|
20
|
+
export declare class CustomerGroup {
|
|
21
|
+
[OptionalProps]?: 'id' | 'createdAt' | 'updatedAt' | 'description';
|
|
22
|
+
id: string;
|
|
23
|
+
code: string;
|
|
24
|
+
name: string;
|
|
25
|
+
description?: string | null;
|
|
26
|
+
createdAt: Date;
|
|
27
|
+
updatedAt: Date;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=customer-group.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customer-group.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/customer-group.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,aAAa,EAAgC,MAAM,iBAAiB,CAAC;AAItF;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAEa,aAAa;IACxB,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,GAAG,aAAa,CAAC;IAGnE,EAAE,EAAE,MAAM,CAAgB;IAI1B,IAAI,EAAG,MAAM,CAAC;IAGd,IAAI,EAAG,MAAM,CAAC;IAGd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Entity, OptionalProps, PrimaryKey, Property, Unique } from '@mikro-orm/core';
|
|
11
|
+
import { GlobalEntity } from '@endora-commerce/platform/tenancy';
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
13
|
+
/**
|
|
14
|
+
* CustomerGroup — the segmentation bucket a customer belongs to.
|
|
15
|
+
*
|
|
16
|
+
* A customer account carries one directly (`CustomerAccount.customerGroupId`,
|
|
17
|
+
* a real foreign key into this table with `on delete set null`) and inherits
|
|
18
|
+
* its Organization's (`Organization.customerGroupId`, an indexed column with no
|
|
19
|
+
* constraint) when it has none of its own. Groups have no behavioural state of
|
|
20
|
+
* their own; they exist as an addressable target — for the feature 011
|
|
21
|
+
* Application Rule's `customerGroup` criterion, for a promotion's audience and
|
|
22
|
+
* for a push audience rule.
|
|
23
|
+
*
|
|
24
|
+
* Feature 076 (D-79) moved this class here from `price_lists`. Table ownership
|
|
25
|
+
* resolves from the module directory the decorated class lives in — its
|
|
26
|
+
* `tableName` read out of the entity decorator below — so the move *is* the
|
|
27
|
+
* ownership change; no SQL was written, the creating migration stayed in
|
|
28
|
+
* `price_lists/migrations/`, and the foreign key from `customer_accounts`
|
|
29
|
+
* became intra-module.
|
|
30
|
+
*/
|
|
31
|
+
let CustomerGroup = class CustomerGroup {
|
|
32
|
+
[OptionalProps];
|
|
33
|
+
id = randomUUID();
|
|
34
|
+
code;
|
|
35
|
+
name;
|
|
36
|
+
description;
|
|
37
|
+
createdAt = new Date();
|
|
38
|
+
updatedAt = new Date();
|
|
39
|
+
};
|
|
40
|
+
__decorate([
|
|
41
|
+
PrimaryKey({ type: 'uuid' }),
|
|
42
|
+
__metadata("design:type", String)
|
|
43
|
+
], CustomerGroup.prototype, "id", void 0);
|
|
44
|
+
__decorate([
|
|
45
|
+
Property({ type: 'string', length: 64 }),
|
|
46
|
+
Unique(),
|
|
47
|
+
__metadata("design:type", String)
|
|
48
|
+
], CustomerGroup.prototype, "code", void 0);
|
|
49
|
+
__decorate([
|
|
50
|
+
Property({ type: 'string', length: 160 }),
|
|
51
|
+
__metadata("design:type", String)
|
|
52
|
+
], CustomerGroup.prototype, "name", void 0);
|
|
53
|
+
__decorate([
|
|
54
|
+
Property({ type: 'string', length: 1000, nullable: true }),
|
|
55
|
+
__metadata("design:type", Object)
|
|
56
|
+
], CustomerGroup.prototype, "description", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
Property({ type: 'datetime', onCreate: () => new Date() }),
|
|
59
|
+
__metadata("design:type", Date)
|
|
60
|
+
], CustomerGroup.prototype, "createdAt", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
Property({ type: 'datetime', onUpdate: () => new Date() }),
|
|
63
|
+
__metadata("design:type", Date)
|
|
64
|
+
], CustomerGroup.prototype, "updatedAt", void 0);
|
|
65
|
+
CustomerGroup = __decorate([
|
|
66
|
+
GlobalEntity(),
|
|
67
|
+
Entity({ tableName: 'customer_groups' })
|
|
68
|
+
], CustomerGroup);
|
|
69
|
+
export { CustomerGroup };
|
|
70
|
+
//# sourceMappingURL=customer-group.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customer-group.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/customer-group.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;;;;;;;;;;;;;;GAiBG;AAGI,IAAM,aAAa,GAAnB,MAAM,aAAa;IACxB,CAAC,aAAa,CAAC,CAAoD;IAGnE,EAAE,GAAW,UAAU,EAAE,CAAC;IAI1B,IAAI,CAAU;IAGd,IAAI,CAAU;IAGd,WAAW,CAAiB;IAG5B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AAjBC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;yCACH;AAI1B;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxC,MAAM,EAAE;;2CACK;AAGd;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;2CAC5B;AAGd;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;kDAC/B;AAG5B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;gDAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;gDAAc;AApBlB,aAAa;IAFzB,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC;GAC5B,aAAa,CAqBzB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { OptionalProps } from '@mikro-orm/core';
|
|
2
|
+
/**
|
|
3
|
+
* One-shot password-reset token. Same shape as EmailVerificationToken — sha256
|
|
4
|
+
* hash stored, expires_at + consumed_at one-shot. Issued by the public
|
|
5
|
+
* /auth/password-reset/request endpoint.
|
|
6
|
+
*/
|
|
7
|
+
export declare class PasswordResetToken {
|
|
8
|
+
[OptionalProps]?: 'id' | 'createdAt' | 'consumedAt';
|
|
9
|
+
id: string;
|
|
10
|
+
customerAccountId: string;
|
|
11
|
+
tokenHash: string;
|
|
12
|
+
expiresAt: Date;
|
|
13
|
+
consumedAt?: Date | null;
|
|
14
|
+
createdAt: Date;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=password-reset-token.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-reset-token.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/password-reset-token.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAgC,MAAM,iBAAiB,CAAC;AAI7F;;;;GAIG;AACH,qBAEa,kBAAkB;IAC7B,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,YAAY,CAAC;IAGpD,EAAE,EAAE,MAAM,CAAgB;IAI1B,iBAAiB,EAAG,MAAM,CAAC;IAI3B,SAAS,EAAG,MAAM,CAAC;IAInB,SAAS,EAAG,IAAI,CAAC;IAGjB,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAGzB,SAAS,EAAE,IAAI,CAAc;CAC9B"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Entity, Index, OptionalProps, PrimaryKey, Property, Unique } from '@mikro-orm/core';
|
|
11
|
+
import { CustomerScoped } from '@endora-commerce/platform/tenancy';
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
13
|
+
/**
|
|
14
|
+
* One-shot password-reset token. Same shape as EmailVerificationToken — sha256
|
|
15
|
+
* hash stored, expires_at + consumed_at one-shot. Issued by the public
|
|
16
|
+
* /auth/password-reset/request endpoint.
|
|
17
|
+
*/
|
|
18
|
+
let PasswordResetToken = class PasswordResetToken {
|
|
19
|
+
[OptionalProps];
|
|
20
|
+
id = randomUUID();
|
|
21
|
+
customerAccountId;
|
|
22
|
+
tokenHash;
|
|
23
|
+
expiresAt;
|
|
24
|
+
consumedAt;
|
|
25
|
+
createdAt = new Date();
|
|
26
|
+
};
|
|
27
|
+
__decorate([
|
|
28
|
+
PrimaryKey({ type: 'uuid' }),
|
|
29
|
+
__metadata("design:type", String)
|
|
30
|
+
], PasswordResetToken.prototype, "id", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
Property({ type: 'uuid' }),
|
|
33
|
+
Index(),
|
|
34
|
+
__metadata("design:type", String)
|
|
35
|
+
], PasswordResetToken.prototype, "customerAccountId", void 0);
|
|
36
|
+
__decorate([
|
|
37
|
+
Property({ type: 'string', length: 128 }),
|
|
38
|
+
Unique(),
|
|
39
|
+
__metadata("design:type", String)
|
|
40
|
+
], PasswordResetToken.prototype, "tokenHash", void 0);
|
|
41
|
+
__decorate([
|
|
42
|
+
Property({ type: 'datetime' }),
|
|
43
|
+
Index(),
|
|
44
|
+
__metadata("design:type", Date)
|
|
45
|
+
], PasswordResetToken.prototype, "expiresAt", void 0);
|
|
46
|
+
__decorate([
|
|
47
|
+
Property({ type: 'datetime', nullable: true }),
|
|
48
|
+
__metadata("design:type", Object)
|
|
49
|
+
], PasswordResetToken.prototype, "consumedAt", void 0);
|
|
50
|
+
__decorate([
|
|
51
|
+
Property({ type: 'datetime', onCreate: () => new Date() }),
|
|
52
|
+
__metadata("design:type", Date)
|
|
53
|
+
], PasswordResetToken.prototype, "createdAt", void 0);
|
|
54
|
+
PasswordResetToken = __decorate([
|
|
55
|
+
CustomerScoped(),
|
|
56
|
+
Entity({ tableName: 'password_reset_tokens' })
|
|
57
|
+
], PasswordResetToken);
|
|
58
|
+
export { PasswordResetToken };
|
|
59
|
+
//# sourceMappingURL=password-reset-token.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-reset-token.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/password-reset-token.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;GAIG;AAGI,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC7B,CAAC,aAAa,CAAC,CAAqC;IAGpD,EAAE,GAAW,UAAU,EAAE,CAAC;IAI1B,iBAAiB,CAAU;IAI3B,SAAS,CAAU;IAInB,SAAS,CAAQ;IAGjB,UAAU,CAAe;IAGzB,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AAnBC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;8CACH;AAI1B;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,EAAE;;6DACmB;AAI3B;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACzC,MAAM,EAAE;;qDACU;AAInB;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAC9B,KAAK,EAAE;8BACI,IAAI;qDAAC;AAGjB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;sDACtB;AAGzB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;qDAAc;AAtBlB,kBAAkB;IAF9B,cAAc,EAAE;IAChB,MAAM,CAAC,EAAE,SAAS,EAAE,uBAAuB,EAAE,CAAC;GAClC,kBAAkB,CAuB9B"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
2
|
+
import type { ChannelMemberEntityType } from '@endora-commerce/contracts';
|
|
3
|
+
import type { AuditPort } from '@endora-commerce/platform/kernel';
|
|
4
|
+
import type { CommandBus } from '@endora-commerce/platform/commands';
|
|
5
|
+
import type { ModuleContext } from '@endora-commerce/platform/kernel';
|
|
6
|
+
import type { RequireAdminFactory } from '@endora-commerce/platform/kernel';
|
|
7
|
+
import type { SettingsReadPort } from '@endora-commerce/platform/kernel';
|
|
8
|
+
import { CustomerAccount } from './entities/customer-account.entity.js';
|
|
9
|
+
import { CustomerGroup } from './entities/customer-group.entity.js';
|
|
10
|
+
import { PasswordResetToken } from './entities/password-reset-token.entity.js';
|
|
11
|
+
import { CustomerAuthService } from './services/customer-auth-service.js';
|
|
12
|
+
import { CustomerGroupService } from './services/customer-group-service.js';
|
|
13
|
+
import { PasswordResetService } from './services/password-reset-service.js';
|
|
14
|
+
import { RoleService } from './services/role-service.js';
|
|
15
|
+
/**
|
|
16
|
+
* `customer_accounts` — one customer auth service, where there were two
|
|
17
|
+
* (feature 072, wave 1, T094).
|
|
18
|
+
*
|
|
19
|
+
* The module owns no routes: `organizations` serves customer login and
|
|
20
|
+
* registration, `customers` serves the self-service surface. Both built their
|
|
21
|
+
* own `CustomerAuthService`, and the third constructor argument differed:
|
|
22
|
+
*
|
|
23
|
+
* organizations: new CustomerAuthService(em, sessions, options.getMfaLoginPort, audit)
|
|
24
|
+
* customers: new CustomerAuthService(em, sessions, undefined, audit)
|
|
25
|
+
* ^ "not wired in the
|
|
26
|
+
* customers composition"
|
|
27
|
+
*
|
|
28
|
+
* That comment was accurate rather than careless, and this is **not** a live
|
|
29
|
+
* MFA bypass today: `getMfaLoginPort` is consulted only inside `login()`, the
|
|
30
|
+
* single login route lives in `organizations`, and the `customers` instance is
|
|
31
|
+
* used only for `changePassword`. What it is, is the `addresses` shape — two
|
|
32
|
+
* instances of one service that are not required to agree, one of which cannot
|
|
33
|
+
* enforce a second factor. The day a customer-side route needs `login()`, the
|
|
34
|
+
* divergence stops being latent, and nothing in the tree would flag it.
|
|
35
|
+
*
|
|
36
|
+
* `PasswordResetService` was doubled the same way, with identical arguments.
|
|
37
|
+
*
|
|
38
|
+
* **The MFA port is resolved here now, behind a presence probe** (D-96). It was
|
|
39
|
+
* a contribution both roots filled from one getter — a root resolving a gated
|
|
40
|
+
* port on this module's behalf, which is composition checklist item 6 — and the
|
|
41
|
+
* harness captured that gate at compose time, so `mfa` switched off was
|
|
42
|
+
* unobservable. The edge is declared `degrades-without` in this module's
|
|
43
|
+
* manifest: `mfa` declares `customer_accounts`, so the ordinary declaration
|
|
44
|
+
* would close a cycle and would make customer login refuse the operator's flip.
|
|
45
|
+
*
|
|
46
|
+
* Everything here is a **port**: `organizations` and `customers` resolve these
|
|
47
|
+
* services across a module boundary, so an operator switching customer accounts
|
|
48
|
+
* off should get an explicit 503 rather than a service that half-answers.
|
|
49
|
+
*
|
|
50
|
+
* `customerOrgResolver` moves here from `HOST_REGISTERED_PORTS`, where a
|
|
51
|
+
* composition root stood in for this module. `auth` reads it in its request
|
|
52
|
+
* hook to attach the organization to a customer session; the lookup is a plain
|
|
53
|
+
* read of this module's own table, so it belongs to this module and the root's
|
|
54
|
+
* entry goes away.
|
|
55
|
+
*
|
|
56
|
+
* **Social-login account creation came home in T143a cluster 6, and the two
|
|
57
|
+
* roots disagreed about what it does.** Both wrote `mfaSocialAccountResolvers`
|
|
58
|
+
* closures that read and created rows in this module's table. Production gated
|
|
59
|
+
* the creation on `customers.allow_registration_without_organization`, which
|
|
60
|
+
* ships **off**; the harness gated it on nothing, so federated sign-in
|
|
61
|
+
* auto-created an account in every test run and the gate itself was covered by
|
|
62
|
+
* no test — a policy the platform has and the suite denied. Production
|
|
63
|
+
* system-scoped the identity read (tenancy comes after identity) and the
|
|
64
|
+
* harness did not, and production minted a random password where the harness
|
|
65
|
+
* hashed one fixed string for every auto-created account. One implementation
|
|
66
|
+
* now, and it is this module's, because the table is.
|
|
67
|
+
*/
|
|
68
|
+
export interface CustomerAccountsCradle {
|
|
69
|
+
/**
|
|
70
|
+
* Feature 120 (FR-015) — the platform's channel-bridge registry, resolved by
|
|
71
|
+
* **container name** rather than imported. The shape is the narrow one this
|
|
72
|
+
* module needs, which is what `ctx.cradle<C>()` asks an author to declare;
|
|
73
|
+
* the registry itself is the kernel's and is published on no barrel.
|
|
74
|
+
*/
|
|
75
|
+
readonly salesChannelBridgeRegistry: {
|
|
76
|
+
register(bridge: {
|
|
77
|
+
entityType: ChannelMemberEntityType;
|
|
78
|
+
table: string;
|
|
79
|
+
entityIdColumn: string;
|
|
80
|
+
}): void;
|
|
81
|
+
};
|
|
82
|
+
readonly emFactory: () => EntityManager;
|
|
83
|
+
readonly auditLogService: AuditPort;
|
|
84
|
+
/** Feature 054 — the customer-group writes audit co-transactionally. */
|
|
85
|
+
readonly commandBus: CommandBus;
|
|
86
|
+
/** `auth`'s admin guard, for the customer-group admin routes. */
|
|
87
|
+
readonly requireAdmin: RequireAdminFactory;
|
|
88
|
+
readonly settingsReadPort: SettingsReadPort;
|
|
89
|
+
/**
|
|
90
|
+
* Which channel a global-scope settings read resolves against — the
|
|
91
|
+
* deployment's system-default channel. A property of the deployment, so a
|
|
92
|
+
* root supplies it; `inventory` reads the same name.
|
|
93
|
+
*/
|
|
94
|
+
readonly settingsChannelResolver: () => Promise<string | null>;
|
|
95
|
+
/**
|
|
96
|
+
* The two customer-side halves of `mfa`'s `SocialIdentityDeps` (T143a): match
|
|
97
|
+
* a verified provider e-mail to an account, and create one when nothing
|
|
98
|
+
* matches and the platform allows an org-less registration.
|
|
99
|
+
*/
|
|
100
|
+
readonly customerSocialLoginPort: {
|
|
101
|
+
resolveByEmail(email: string): Promise<{
|
|
102
|
+
id: string;
|
|
103
|
+
} | null>;
|
|
104
|
+
autoCreate(email: string): Promise<{
|
|
105
|
+
id: string;
|
|
106
|
+
} | null>;
|
|
107
|
+
};
|
|
108
|
+
readonly customerAuthService: CustomerAuthService;
|
|
109
|
+
readonly passwordResetService: PasswordResetService;
|
|
110
|
+
readonly customerRoleService: RoleService;
|
|
111
|
+
readonly customerGroupService: CustomerGroupService;
|
|
112
|
+
}
|
|
113
|
+
export declare function registerModule(ctx: ModuleContext): void;
|
|
114
|
+
/**
|
|
115
|
+
* The module's persisted entity classes, on the `./backend` subpath, as one
|
|
116
|
+
* array and **no named class export** (D-168).
|
|
117
|
+
*
|
|
118
|
+
* This is the shape the platform reads when the package is *installed*: the
|
|
119
|
+
* boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
|
|
120
|
+
* and the static declaration reader (`scripts/lib/package-declarations.ts`),
|
|
121
|
+
* which is the third source of `check:module-boundary`'s `table->owner` map and
|
|
122
|
+
* the package pass of `check-entity-tenant-classification`. A missing array is
|
|
123
|
+
* answered with `[]` — zero entities registered, no error anywhere.
|
|
124
|
+
*
|
|
125
|
+
* The order is the one `db/entities-registry.generated.ts` declared before this
|
|
126
|
+
* module became a package, so the registered set is the same list in the same
|
|
127
|
+
* sequence.
|
|
128
|
+
*/
|
|
129
|
+
export declare const entities: (typeof CustomerAccount | typeof CustomerGroup | typeof PasswordResetToken)[];
|
|
130
|
+
/**
|
|
131
|
+
* The sales-channel membership bridge this module owns (feature 120, FR-015).
|
|
132
|
+
*
|
|
133
|
+
* Exported as well as registered because the owning module is the only honest
|
|
134
|
+
* source for it: a caller that composes no platform — the bare-database test
|
|
135
|
+
* harness, which constructs the kernel's membership service directly — declares
|
|
136
|
+
* these from here rather than from a list of nine it keeps itself, which is
|
|
137
|
+
* exactly the total map this feature deleted.
|
|
138
|
+
*/
|
|
139
|
+
export declare const salesChannelBridges: ReadonlyArray<{
|
|
140
|
+
readonly entityType: ChannelMemberEntityType;
|
|
141
|
+
readonly table: string;
|
|
142
|
+
readonly entityIdColumn: string;
|
|
143
|
+
}>;
|
|
144
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAmB1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAGrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAItE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAIzE,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAc/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAE1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAE5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,0BAA0B,EAAE;QACnC,QAAQ,CAAC,MAAM,EAAE;YACf,UAAU,EAAE,uBAAuB,CAAC;YACpC,KAAK,EAAE,MAAM,CAAC;YACd,cAAc,EAAE,MAAM,CAAC;SACxB,GAAG,IAAI,CAAC;KACV,CAAC;IACF,QAAQ,CAAC,SAAS,EAAE,MAAM,aAAa,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC;IACpC,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/D;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,EAAE;QAChC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC,CAAC;QAC9D,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC,CAAC;KAC3D,CAAC;IACF,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IAClD,QAAQ,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;IACpD,QAAQ,CAAC,mBAAmB,EAAE,WAAW,CAAC;IAC1C,QAAQ,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;CACrD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CA0evD;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,QAAQ,+EAAuD,CAAC;AAE7E;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,aAAa,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,uBAAuB,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC,CAEA,CAAC"}
|