@metamask-previews/kyc-controller 0.0.0-preview-abca9bcea → 0.0.0-preview-ec24abb79

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 (76) hide show
  1. package/CHANGELOG.md +0 -12
  2. package/dist/KycController-method-action-types.cjs.map +1 -1
  3. package/dist/KycController-method-action-types.d.cts +4 -6
  4. package/dist/KycController-method-action-types.d.cts.map +1 -1
  5. package/dist/KycController-method-action-types.d.mts +4 -6
  6. package/dist/KycController-method-action-types.d.mts.map +1 -1
  7. package/dist/KycController-method-action-types.mjs.map +1 -1
  8. package/dist/KycController.cjs +300 -191
  9. package/dist/KycController.cjs.map +1 -1
  10. package/dist/KycController.d.cts +40 -46
  11. package/dist/KycController.d.cts.map +1 -1
  12. package/dist/KycController.d.mts +40 -46
  13. package/dist/KycController.d.mts.map +1 -1
  14. package/dist/KycController.mjs +299 -188
  15. package/dist/KycController.mjs.map +1 -1
  16. package/dist/KycService-method-action-types.cjs.map +1 -1
  17. package/dist/KycService-method-action-types.d.cts +6 -23
  18. package/dist/KycService-method-action-types.d.cts.map +1 -1
  19. package/dist/KycService-method-action-types.d.mts +6 -23
  20. package/dist/KycService-method-action-types.d.mts.map +1 -1
  21. package/dist/KycService-method-action-types.mjs.map +1 -1
  22. package/dist/KycService.cjs +119 -100
  23. package/dist/KycService.cjs.map +1 -1
  24. package/dist/KycService.d.cts +12 -38
  25. package/dist/KycService.d.cts.map +1 -1
  26. package/dist/KycService.d.mts +12 -38
  27. package/dist/KycService.d.mts.map +1 -1
  28. package/dist/KycService.mjs +119 -100
  29. package/dist/KycService.mjs.map +1 -1
  30. package/dist/index.cjs +1 -3
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +4 -4
  33. package/dist/index.d.cts.map +1 -1
  34. package/dist/index.d.mts +4 -4
  35. package/dist/index.d.mts.map +1 -1
  36. package/dist/index.mjs +1 -1
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/types.cjs.map +1 -1
  39. package/dist/types.d.cts +5 -53
  40. package/dist/types.d.cts.map +1 -1
  41. package/dist/types.d.mts +5 -53
  42. package/dist/types.d.mts.map +1 -1
  43. package/dist/types.mjs.map +1 -1
  44. package/dist/ukyc/wrapEncryptionKey.cjs +9 -4
  45. package/dist/ukyc/wrapEncryptionKey.cjs.map +1 -1
  46. package/dist/ukyc/wrapEncryptionKey.d.cts +10 -8
  47. package/dist/ukyc/wrapEncryptionKey.d.cts.map +1 -1
  48. package/dist/ukyc/wrapEncryptionKey.d.mts +10 -8
  49. package/dist/ukyc/wrapEncryptionKey.d.mts.map +1 -1
  50. package/dist/ukyc/wrapEncryptionKey.mjs +9 -4
  51. package/dist/ukyc/wrapEncryptionKey.mjs.map +1 -1
  52. package/package.json +2 -2
  53. package/dist/logger.cjs +0 -9
  54. package/dist/logger.cjs.map +0 -1
  55. package/dist/logger.d.cts +0 -6
  56. package/dist/logger.d.cts.map +0 -1
  57. package/dist/logger.d.mts +0 -6
  58. package/dist/logger.d.mts.map +0 -1
  59. package/dist/logger.mjs +0 -6
  60. package/dist/logger.mjs.map +0 -1
  61. package/dist/vendorDisclaimerAcceptance.cjs +0 -74
  62. package/dist/vendorDisclaimerAcceptance.cjs.map +0 -1
  63. package/dist/vendorDisclaimerAcceptance.d.cts +0 -39
  64. package/dist/vendorDisclaimerAcceptance.d.cts.map +0 -1
  65. package/dist/vendorDisclaimerAcceptance.d.mts +0 -39
  66. package/dist/vendorDisclaimerAcceptance.d.mts.map +0 -1
  67. package/dist/vendorDisclaimerAcceptance.mjs +0 -67
  68. package/dist/vendorDisclaimerAcceptance.mjs.map +0 -1
  69. package/dist/vendors/MoonPayFrameHandler.cjs +0 -235
  70. package/dist/vendors/MoonPayFrameHandler.cjs.map +0 -1
  71. package/dist/vendors/MoonPayFrameHandler.d.cts +0 -74
  72. package/dist/vendors/MoonPayFrameHandler.d.cts.map +0 -1
  73. package/dist/vendors/MoonPayFrameHandler.d.mts +0 -74
  74. package/dist/vendors/MoonPayFrameHandler.d.mts.map +0 -1
  75. package/dist/vendors/MoonPayFrameHandler.mjs +0 -230
  76. package/dist/vendors/MoonPayFrameHandler.mjs.map +0 -1
@@ -10,23 +10,25 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _KycController_instances, _KycController_sumsubLauncher, _KycController_moonPayFrames, _KycController_generation, _KycController_sessionStatusPollIntervalMs, _KycController_pollTimer, _KycController_pollToken, _KycController_userStatusPollIntervalMs, _KycController_userStatusPollTimer, _KycController_userStatusPolling, _KycController_userStatusPollToken, _KycController_localUserSecretStore, _KycController_startConsentsSession, _KycController_recordSessionDisclaimers, _KycController_createSession, _KycController_clearAcceptedTerms, _KycController_continueAfterAuthentication, _KycController_requireTermsReacceptance, _KycController_buildUkycSessionVendorFields, _KycController_createUkycSession, _KycController_fetchAndApplyUserStatus, _KycController_applyUserStatus, _KycController_ensureUserStatusPolling, _KycController_stopUserStatusPolling, _KycController_startSessionStatusPolling, _KycController_pollSessionStatusOnce, _KycController_stopPolling, _KycController_cancelPendingSession, _KycController_updateIfCurrent, _KycController_applyUpdate, _KycController_assertAttestedServerPublicKey, _KycController_fail;
13
+ var _KycController_instances, _KycController_sumsubLauncher, _KycController_keypair, _KycController_authClientToken, _KycController_generation, _KycController_sessionStatusPollIntervalMs, _KycController_pollTimer, _KycController_pollToken, _KycController_userStatusPollIntervalMs, _KycController_userStatusPollTimer, _KycController_userStatusPolling, _KycController_userStatusPollToken, _KycController_localUserSecretStore, _KycController_startConsentsSession, _KycController_recordSessionDisclaimers, _KycController_createSession, _KycController_clearAcceptedTerms, _KycController_clearMoonPaySession, _KycController_dropTermsUnlessForVendor, _KycController_hasTermsForVendor, _KycController_handleCheckOutcome, _KycController_handleAuthOutcome, _KycController_continueAfterAuthentication, _KycController_requireTermsReacceptance, _KycController_buildUkycSessionVendorFields, _KycController_createUkycSession, _KycController_fetchAndApplyUserStatus, _KycController_applyUserStatus, _KycController_ensureUserStatusPolling, _KycController_stopUserStatusPolling, _KycController_startSessionStatusPolling, _KycController_pollSessionStatusOnce, _KycController_stopPolling, _KycController_cancelPendingSession, _KycController_updateIfCurrent, _KycController_applyUpdate, _KycController_assertAttestedServerPublicKey, _KycController_fail;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.KycController = exports.getDefaultKycControllerState = exports.getDefaultKycProviderDisclaimersAccepted = exports.getDefaultKycVendorDisclaimersAccepted = exports.controllerName = void 0;
15
+ exports.KycController = exports.getDefaultKycControllerState = exports.controllerName = void 0;
16
16
  const base_controller_1 = require("@metamask/base-controller");
17
17
  const utils_1 = require("@metamask/utils");
18
18
  const ed25519_1 = require("@noble/curves/ed25519");
19
+ const crypto_js_1 = require("./crypto.cjs");
19
20
  const encoding_js_1 = require("./encoding.cjs");
20
- const logger_js_1 = require("./logger.cjs");
21
21
  const deriveClientMaterial_js_1 = require("./ukyc/deriveClientMaterial.cjs");
22
22
  const jwtChain_js_1 = require("./ukyc/jwtChain.cjs");
23
23
  const localUserSecret_js_1 = require("./ukyc/localUserSecret.cjs");
24
24
  const storageAccessToken_js_1 = require("./ukyc/storageAccessToken.cjs");
25
25
  const wrapEncryptionKey_js_1 = require("./ukyc/wrapEncryptionKey.cjs");
26
- const vendorDisclaimerAcceptance_js_1 = require("./vendorDisclaimerAcceptance.cjs");
27
- const MoonPayFrameHandler_js_1 = require("./vendors/MoonPayFrameHandler.cjs");
28
26
  // === GENERAL ===
29
27
  exports.controllerName = 'KycController';
28
+ const FRAMES_BASE_URL = 'https://blocks.moonpay.com/platform/v1';
29
+ const CHANNEL_CHECK = 'ch_1';
30
+ const CHANNEL_AUTH = 'ch_2';
31
+ const CHANNEL_RESET = 'ch_reset';
30
32
  // Placeholder credentials for the SumSub sub-flow. These are demo values that
31
33
  // must be replaced with real UKYC-issued material before production use.
32
34
  const MOCK_JWT_TOKEN = 'mock-jwt-token';
@@ -117,19 +119,31 @@ const kycControllerMetadata = {
117
119
  persist: false,
118
120
  usedInUi: false,
119
121
  },
120
- vendorDisclaimersAccepted: {
122
+ termsAcceptedAt: {
121
123
  includeInDebugSnapshot: true,
122
124
  includeInStateLogs: true,
123
125
  persist: true,
124
126
  usedInUi: false,
125
127
  },
126
- providerDisclaimersAccepted: {
128
+ acceptedDisclaimerIds: {
127
129
  includeInDebugSnapshot: true,
128
130
  includeInStateLogs: true,
129
131
  persist: true,
130
132
  usedInUi: false,
131
133
  },
132
- idosDisclaimersAccepted: {
134
+ termsAcceptedVendor: {
135
+ includeInDebugSnapshot: true,
136
+ includeInStateLogs: true,
137
+ persist: true,
138
+ usedInUi: false,
139
+ },
140
+ sumsubTncAccepted: {
141
+ includeInDebugSnapshot: true,
142
+ includeInStateLogs: true,
143
+ persist: true,
144
+ usedInUi: false,
145
+ },
146
+ idosTncAccepted: {
133
147
  includeInDebugSnapshot: true,
134
148
  includeInStateLogs: true,
135
149
  persist: true,
@@ -141,13 +155,13 @@ const kycControllerMetadata = {
141
155
  persist: false,
142
156
  usedInUi: false,
143
157
  },
144
- vendorDisclaimers: {
158
+ disclaimers: {
145
159
  includeInDebugSnapshot: false,
146
160
  includeInStateLogs: false,
147
161
  persist: false,
148
162
  usedInUi: true,
149
163
  },
150
- vendorError: {
164
+ disclaimersError: {
151
165
  includeInDebugSnapshot: true,
152
166
  includeInStateLogs: true,
153
167
  persist: false,
@@ -165,13 +179,13 @@ const kycControllerMetadata = {
165
179
  persist: false,
166
180
  usedInUi: true,
167
181
  },
168
- moonpaySessionToken: {
182
+ sessionToken: {
169
183
  includeInDebugSnapshot: false,
170
184
  includeInStateLogs: false,
171
185
  persist: false,
172
186
  usedInUi: false,
173
187
  },
174
- moonpayAccessToken: {
188
+ accessToken: {
175
189
  includeInDebugSnapshot: false,
176
190
  includeInStateLogs: false,
177
191
  persist: false,
@@ -232,19 +246,6 @@ const kycControllerMetadata = {
232
246
  usedInUi: true,
233
247
  },
234
248
  };
235
- /**
236
- * Constructs the default {@link KycVendorDisclaimersAccepted} value.
237
- *
238
- * @returns The default vendor-disclaimer acceptance map.
239
- */
240
- function getDefaultKycVendorDisclaimersAccepted() {
241
- return { moonpay: null, iron: null };
242
- }
243
- exports.getDefaultKycVendorDisclaimersAccepted = getDefaultKycVendorDisclaimersAccepted;
244
- function getDefaultKycProviderDisclaimersAccepted() {
245
- return { sumsub: null };
246
- }
247
- exports.getDefaultKycProviderDisclaimersAccepted = getDefaultKycProviderDisclaimersAccepted;
248
249
  /**
249
250
  * Constructs the default {@link KycController} state.
250
251
  *
@@ -256,16 +257,18 @@ function getDefaultKycControllerState() {
256
257
  statusMessage: '',
257
258
  error: null,
258
259
  email: null,
259
- vendorDisclaimersAccepted: getDefaultKycVendorDisclaimersAccepted(),
260
- providerDisclaimersAccepted: getDefaultKycProviderDisclaimersAccepted(),
261
- idosDisclaimersAccepted: null,
260
+ termsAcceptedAt: null,
261
+ acceptedDisclaimerIds: [],
262
+ termsAcceptedVendor: null,
263
+ sumsubTncAccepted: null,
264
+ idosTncAccepted: null,
262
265
  credentialReusabilityConsentGiven: null,
263
- vendorDisclaimers: [],
264
- vendorError: null,
266
+ disclaimers: [],
267
+ disclaimersError: null,
265
268
  sessionDisclaimers: null,
266
269
  geoCountry: null,
267
- moonpaySessionToken: null,
268
- moonpayAccessToken: null,
270
+ sessionToken: null,
271
+ accessToken: null,
269
272
  moonpayCustomerId: null,
270
273
  activeVendor: 'moonpay',
271
274
  activeProduct: null,
@@ -310,62 +313,45 @@ function isConsentConflictError(error) {
310
313
  error.httpStatus === 409);
311
314
  }
312
315
  /**
313
- *
314
- * @param value - The value to validate.
315
- * @returns `true` when `value` is a valid consent record list.
316
- */
317
- function isValidConsentRecordList(value) {
318
- return (Array.isArray(value) &&
319
- value.every((item) => typeof item === 'object' &&
320
- item !== null &&
321
- typeof item.key === 'string' &&
322
- typeof item.version === 'string'));
323
- }
324
- /**
325
- * Maps accepted disclaimer records onto unconsented catalog documents.
316
+ * Maps a session-disclaimer catalog into the `{ key, version }` records the
317
+ * record-consents API expects, or an empty list when the user declined that
318
+ * category.
326
319
  *
327
320
  * @param documents - Catalog documents for one consent category.
328
- * @param accepted - Accepted `{ key, version }` records from the caller.
329
- * @returns Consent records to POST, omitting already-consented documents.
321
+ * @param accepted - Whether the user accepted that category.
322
+ * @returns Consent records, or `[]` when not accepted.
330
323
  */
331
- function consentRecordsFromAcceptedList(documents, accepted) {
332
- if (accepted.length === 0) {
324
+ function consentRecordsFromCatalog(documents, accepted) {
325
+ if (!accepted) {
333
326
  return [];
334
327
  }
335
- const acceptedKeys = new Set(accepted.map((record) => `${record.key}:${record.version}`));
336
328
  return documents
337
- .filter((document) => !document.consented &&
338
- acceptedKeys.has(`${document.key}:${document.version}`))
329
+ .filter((document) => !document.consented)
339
330
  .map(({ key, version }) => ({ key, version }));
340
331
  }
341
332
  /**
342
- * Whether accepted disclaimers reference a missing catalog category.
333
+ * Whether an accepted T&C2 category has no catalog documents. An empty list
334
+ * would otherwise skip the POST and count as success.
343
335
  *
344
336
  * @param documents - Catalog documents for one consent category.
345
- * @param accepted - Accepted `{ key, version }` records from the caller.
346
- * @returns `true` when the caller accepted docs but the catalog is empty.
337
+ * @param accepted - Whether the user accepted that category.
338
+ * @returns `true` when the user accepted and the catalog is empty.
347
339
  */
348
340
  function isAcceptedCategoryEmpty(documents, accepted) {
349
- return accepted.length > 0 && documents.length === 0;
341
+ return accepted && documents.length === 0;
350
342
  }
351
343
  /**
352
- * Whether accepted disclaimers are still missing consent after a 409 re-GET:
353
- * empty catalog or any accepted document still unconsented.
344
+ * Whether an accepted category is still missing consent after a 409 re-GET:
345
+ * empty catalog or any document still unconsented.
354
346
  *
355
347
  * @param documents - Latest catalog documents for one consent category.
356
- * @param accepted - Accepted `{ key, version }` records from the caller.
348
+ * @param accepted - Whether the user accepted that category.
357
349
  * @returns `true` when accepted documents are not fully consented.
358
350
  */
359
351
  function acceptedCategoryStillMissing(documents, accepted) {
360
- if (accepted.length === 0) {
361
- return false;
362
- }
363
- if (documents.length === 0) {
364
- return true;
365
- }
366
- const acceptedKeys = new Set(accepted.map((record) => `${record.key}:${record.version}`));
367
- const relevant = documents.filter((document) => acceptedKeys.has(`${document.key}:${document.version}`));
368
- return (relevant.length === 0 || relevant.some((document) => !document.consented));
352
+ return (accepted &&
353
+ (documents.length === 0 ||
354
+ documents.some((document) => !document.consented)));
369
355
  }
370
356
  /**
371
357
  * Vendors other than MoonPay skip Check/Auth frames and use the empty-shell
@@ -401,9 +387,9 @@ const MESSENGER_EXPOSED_METHODS = [
401
387
  /**
402
388
  * `KycController` orchestrates the vendor-backed KYC / identity-verification
403
389
  * flow (MoonPay identity + SumSub documents) behind a vendor-neutral, per
404
- * product surface used by ramps and card. It owns all state and HTTP
405
- * orchestration (via `KycService`), while vendor protocol handling and
406
- * platform-specific presentation (WebView/iframe, SumSub SDK) are delegated.
390
+ * product surface used by ramps and card. It owns all state, HTTP
391
+ * orchestration (via `KycService`), crypto, and the frame message protocol;
392
+ * platform-specific presentation (WebView/iframe, SumSub SDK) is injected.
407
393
  */
408
394
  class KycController extends base_controller_1.BaseController {
409
395
  /**
@@ -427,8 +413,10 @@ class KycController extends base_controller_1.BaseController {
427
413
  });
428
414
  _KycController_instances.add(this);
429
415
  _KycController_sumsubLauncher.set(this, void 0);
430
- /** MoonPay-specific frame protocol and non-persisted credentials. */
431
- _KycController_moonPayFrames.set(this, void 0);
416
+ /** Ephemeral X25519 keypair for the frame key exchange (never persisted). */
417
+ _KycController_keypair.set(this, void 0);
418
+ /** Auth-frame client token, kept out of state. */
419
+ _KycController_authClientToken.set(this, null);
432
420
  /**
433
421
  * Monotonic flow generation. Incremented by {@link reset} and
434
422
  * {@link clearState} so in-flight async work (e.g. the KYC-required check)
@@ -465,13 +453,7 @@ class KycController extends base_controller_1.BaseController {
465
453
  __classPrivateFieldSet(this, _KycController_sumsubLauncher, sumsubLauncher, "f");
466
454
  __classPrivateFieldSet(this, _KycController_sessionStatusPollIntervalMs, sessionStatusPollIntervalMs, "f");
467
455
  __classPrivateFieldSet(this, _KycController_userStatusPollIntervalMs, userStatusPollIntervalMs, "f");
468
- __classPrivateFieldSet(this, _KycController_moonPayFrames, new MoonPayFrameHandler_js_1.MoonPayFrameHandler({
469
- getState: () => this.state,
470
- update: (updater) => __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, updater),
471
- fail: (message) => __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, message),
472
- onAuthenticated: async () => __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_continueAfterAuthentication).call(this),
473
- requireTermsReacceptance: () => __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_requireTermsReacceptance).call(this),
474
- }), "f");
456
+ __classPrivateFieldSet(this, _KycController_keypair, (0, crypto_js_1.generateKeyPair)(), "f");
475
457
  this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
476
458
  }
477
459
  /**
@@ -494,19 +476,10 @@ class KycController extends base_controller_1.BaseController {
494
476
  // forces `phase` back through `session`/`check`, breaking an in-flight
495
477
  // Check/Auth frame flow. Leave the active flow untouched and let the
496
478
  // consumer drive it (or call `reset` first to start over).
497
- const vendor = params?.vendor ?? 'moonpay';
498
479
  if (IN_PROGRESS_PHASES.includes(this.state.phase)) {
499
- if (vendor === 'moonpay') {
500
- __classPrivateFieldGet(this, _KycController_moonPayFrames, "f").ensureKeypair();
501
- }
502
480
  return;
503
481
  }
504
- if (vendor === 'moonpay') {
505
- __classPrivateFieldGet(this, _KycController_moonPayFrames, "f").startFlow();
506
- }
507
- else {
508
- __classPrivateFieldGet(this, _KycController_moonPayFrames, "f").clear();
509
- }
482
+ const vendor = params?.vendor ?? 'moonpay';
510
483
  // `initialize` starts a fresh flow, so `activeProduct` is always reset to
511
484
  // this call's product (or `null`). Otherwise a prior run's product could
512
485
  // linger and cause `#continueAfterAuthentication` to auto-run the check /
@@ -516,9 +489,14 @@ class KycController extends base_controller_1.BaseController {
516
489
  state.email = params.email;
517
490
  }
518
491
  state.activeVendor = vendor;
519
- // MoonPay Check/Auth artifacts must not survive a switch to another vendor
492
+ // MoonPay Check/Auth artifacts must not survive a switch to another
493
+ // vendor: leftover `sessionToken` would keep `buildCheckFrameUrl` alive,
494
+ // leftover `accessToken` / `#authClientToken` would keep Auth / KYC
495
+ // calls bound to MoonPay, and leftover `moonpayCustomerId` would make
496
+ // `getCustomerIdentity` report a MoonPay id under the wrong vendor.
520
497
  if (vendor !== 'moonpay') {
521
- (0, MoonPayFrameHandler_js_1.clearMoonPaySession)(state);
498
+ __classPrivateFieldSet(this, _KycController_authClientToken, null, "f");
499
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearMoonPaySession).call(this, state);
522
500
  }
523
501
  state.activeProduct = params?.product ?? null;
524
502
  });
@@ -566,14 +544,16 @@ class KycController extends base_controller_1.BaseController {
566
544
  if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
567
545
  return;
568
546
  }
569
- const hasTerms = (0, vendorDisclaimerAcceptance_js_1.hasVendorDisclaimerAcceptance)(this.state.vendorDisclaimersAccepted, vendor);
547
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_dropTermsUnlessForVendor).call(this, vendor);
548
+ const hasTerms = Boolean(this.state.termsAcceptedAt) &&
549
+ this.state.acceptedDisclaimerIds.length > 0;
570
550
  if (hasTerms && this.state.email) {
571
551
  if (usesConsentsFlow(vendor)) {
572
552
  // Consents-path vendors require T&C2 flags; if they weren't persisted
573
553
  // (i.e. null from pre-migration state), require reacceptance.
574
- const { providerDisclaimersAccepted, idosDisclaimersAccepted } = this.state;
575
- if (providerDisclaimersAccepted.sumsub === null ||
576
- idosDisclaimersAccepted === null) {
554
+ const sumsubTncSigned = this.state.sumsubTncAccepted;
555
+ const idosTncSigned = this.state.idosTncAccepted;
556
+ if (sumsubTncSigned === null || idosTncSigned === null) {
577
557
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
578
558
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearAcceptedTerms).call(this, state);
579
559
  state.phase = 'terms';
@@ -582,19 +562,12 @@ class KycController extends base_controller_1.BaseController {
582
562
  return;
583
563
  }
584
564
  await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_startConsentsSession).call(this, {
585
- providerDisclaimersAccepted: providerDisclaimersAccepted.sumsub,
586
- idosDisclaimersAccepted,
565
+ sumsubTncSigned,
566
+ idosTncSigned,
587
567
  credentialReusabilityConsentGiven: this.state.credentialReusabilityConsentGiven ?? false,
588
568
  });
589
569
  }
590
570
  else {
591
- // TODO: should this be here? or should it exist at all?
592
- if (vendor === 'moonpay' && this.state.vendorDisclaimers.length === 0) {
593
- await this.loadDisclaimers();
594
- if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
595
- return;
596
- }
597
- }
598
571
  await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_createSession).call(this);
599
572
  }
600
573
  return;
@@ -628,8 +601,8 @@ class KycController extends base_controller_1.BaseController {
628
601
  // after this request succeeds.
629
602
  state.activeVendor = params.vendor;
630
603
  if (params.vendor !== 'moonpay') {
631
- __classPrivateFieldGet(this, _KycController_moonPayFrames, "f").clear();
632
- (0, MoonPayFrameHandler_js_1.clearMoonPaySession)(state);
604
+ __classPrivateFieldSet(this, _KycController_authClientToken, null, "f");
605
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearMoonPaySession).call(this, state);
633
606
  }
634
607
  });
635
608
  const generation = __classPrivateFieldGet(this, _KycController_generation, "f");
@@ -638,6 +611,10 @@ class KycController extends base_controller_1.BaseController {
638
611
  vendor: params.vendor,
639
612
  email: params.email,
640
613
  });
614
+ if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
615
+ return;
616
+ }
617
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_dropTermsUnlessForVendor).call(this, params.vendor);
641
618
  }
642
619
  catch (error) {
643
620
  if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
@@ -666,18 +643,18 @@ class KycController extends base_controller_1.BaseController {
666
643
  state.geoCountry = country;
667
644
  });
668
645
  }
669
- const disclaimers = await this.messenger.call('KycService:fetchVendorDisclaimers', {
646
+ const disclaimers = await this.messenger.call('KycService:fetchDisclaimers', {
670
647
  vendor: this.state.activeVendor,
671
648
  country,
672
649
  });
673
650
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
674
- state.vendorDisclaimers = disclaimers;
675
- state.vendorError = null;
651
+ state.disclaimers = disclaimers;
652
+ state.disclaimersError = null;
676
653
  });
677
654
  }
678
655
  catch (error) {
679
656
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
680
- state.vendorError = `Failed to load disclaimers: ${String(error)}`;
657
+ state.disclaimersError = `Failed to load disclaimers: ${String(error)}`;
681
658
  });
682
659
  }
683
660
  }
@@ -690,47 +667,44 @@ class KycController extends base_controller_1.BaseController {
690
667
  * @param params.product - The consuming feature the flow runs for. See
691
668
  * {@link initialize} for how the product drives the automatic post
692
669
  * authentication continuation.
693
- * @param params.providerDisclaimersAccepted - Sumsub disclaimer documents the
694
- * customer accepted (`{ key, version }` records). Required for every vendor
695
- * so callers explicitly declare acceptance.
696
- * @param params.idosDisclaimersAccepted - idOS disclaimer documents the
697
- * customer accepted (`{ key, version }` records). Required for every vendor
698
- * so callers explicitly declare acceptance.
670
+ * @param params.sumsubTncSigned - Whether Sumsub T&C were accepted (T&C2).
671
+ * Required for every vendor so callers explicitly declare acceptance.
672
+ * @param params.idosTncSigned - Whether idOS T&C were accepted (T&C2).
673
+ * Required for every vendor so callers explicitly declare acceptance.
699
674
  * @param params.credentialReusabilityConsentGiven - Whether the customer
700
675
  * consented to reuse existing idOS credentials. Used when recording
701
676
  * session-scoped disclaimers on the consents path. Defaults to `false`.
702
677
  */
703
678
  async acceptTermsAndStartSession(params) {
704
- const providerDisclaimersAccepted = params?.providerDisclaimersAccepted;
705
- const idosDisclaimersAccepted = params?.idosDisclaimersAccepted;
706
- if (!isValidConsentRecordList(providerDisclaimersAccepted) ||
707
- !isValidConsentRecordList(idosDisclaimersAccepted)) {
679
+ const sumsubTncSigned = params?.sumsubTncSigned;
680
+ const idosTncSigned = params?.idosTncSigned;
681
+ if (typeof sumsubTncSigned !== 'boolean' ||
682
+ typeof idosTncSigned !== 'boolean') {
708
683
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, 'Missing T&C2 acceptance flags.');
709
684
  return;
710
685
  }
711
- const credentialReusabilityConsentGiven = params?.credentialReusabilityConsentGiven ?? false;
686
+ const credentialReusabilityConsentGiven = params.credentialReusabilityConsentGiven ?? false;
712
687
  const termsAcceptedAt = new Date().toISOString();
713
- const disclaimerIds = this.state.vendorDisclaimers.map((disclaimer) => disclaimer.id);
688
+ const disclaimerIds = this.state.disclaimers.map((disclaimer) => disclaimer.id);
714
689
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
715
- if (params?.email) {
690
+ if (params.email) {
716
691
  state.email = params.email;
717
692
  }
718
- if (params?.product) {
693
+ if (params.product) {
719
694
  state.activeProduct = params.product;
720
695
  }
721
- state.vendorDisclaimersAccepted = (0, vendorDisclaimerAcceptance_js_1.recordVendorDisclaimerAcceptance)(state.vendorDisclaimersAccepted, state.activeVendor, { termsAcceptedAt, disclaimerIds });
722
- state.providerDisclaimersAccepted = {
723
- ...state.providerDisclaimersAccepted,
724
- sumsub: providerDisclaimersAccepted,
725
- };
726
- state.idosDisclaimersAccepted = idosDisclaimersAccepted;
696
+ state.termsAcceptedAt = termsAcceptedAt;
697
+ state.acceptedDisclaimerIds = disclaimerIds;
698
+ state.termsAcceptedVendor = state.activeVendor;
699
+ state.sumsubTncAccepted = sumsubTncSigned;
700
+ state.idosTncAccepted = idosTncSigned;
727
701
  state.credentialReusabilityConsentGiven =
728
702
  credentialReusabilityConsentGiven;
729
703
  });
730
704
  if (usesConsentsFlow(this.state.activeVendor)) {
731
705
  await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_startConsentsSession).call(this, {
732
- providerDisclaimersAccepted,
733
- idosDisclaimersAccepted,
706
+ sumsubTncSigned,
707
+ idosTncSigned,
734
708
  credentialReusabilityConsentGiven,
735
709
  });
736
710
  return;
@@ -742,12 +716,7 @@ class KycController extends base_controller_1.BaseController {
742
716
  */
743
717
  clearSavedTerms() {
744
718
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
745
- state.vendorDisclaimersAccepted =
746
- getDefaultKycVendorDisclaimersAccepted();
747
- state.providerDisclaimersAccepted =
748
- getDefaultKycProviderDisclaimersAccepted();
749
- state.idosDisclaimersAccepted = null;
750
- state.credentialReusabilityConsentGiven = null;
719
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearAcceptedTerms).call(this, state);
751
720
  });
752
721
  }
753
722
  /**
@@ -761,7 +730,68 @@ class KycController extends base_controller_1.BaseController {
761
730
  * @returns An object whose optional `reply` should be posted back.
762
731
  */
763
732
  async handleFrameMessage(params) {
764
- return await __classPrivateFieldGet(this, _KycController_moonPayFrames, "f").handleMessage(params.message);
733
+ const payload = params.message;
734
+ if (!payload) {
735
+ return {};
736
+ }
737
+ if (payload.kind === 'handshake') {
738
+ const channelId = payload.meta?.channelId;
739
+ return { reply: { version: 2, meta: { channelId }, kind: 'ack' } };
740
+ }
741
+ if (payload.kind !== 'complete') {
742
+ return {};
743
+ }
744
+ const channelId = payload.meta?.channelId;
745
+ // Only honor a Check/Auth `complete` for the MoonPay frame the flow is
746
+ // currently waiting on. This drops stale or duplicate messages — e.g. a
747
+ // late post after `reset()` (phase `idle`), after the flow already
748
+ // advanced past this frame, or after a vendor switch — so they cannot
749
+ // resurrect tokens, rewind `phase`, or recapture `moonpayCustomerId` on a
750
+ // controller that has moved on. Frame messages are external input and,
751
+ // unlike the async steps, are not covered by the `#generation` guard.
752
+ let expectedPhase = null;
753
+ if (channelId === CHANNEL_CHECK) {
754
+ expectedPhase = 'check';
755
+ }
756
+ else if (channelId === CHANNEL_AUTH) {
757
+ expectedPhase = 'auth';
758
+ }
759
+ if (!expectedPhase ||
760
+ this.state.phase !== expectedPhase ||
761
+ this.state.activeVendor !== 'moonpay') {
762
+ return {};
763
+ }
764
+ const status = payload.payload?.status;
765
+ const credsEnvelope = payload.payload?.credentials;
766
+ const customerId = payload.payload?.customer?.id ?? null;
767
+ if (customerId) {
768
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
769
+ state.moonpayCustomerId = customerId;
770
+ });
771
+ }
772
+ if (!status) {
773
+ return {};
774
+ }
775
+ let accessToken;
776
+ let clientToken;
777
+ if (credsEnvelope) {
778
+ try {
779
+ const { credentials } = (0, crypto_js_1.decryptCredentials)(credsEnvelope, __classPrivateFieldGet(this, _KycController_keypair, "f").privateKey);
780
+ accessToken = credentials.accessToken;
781
+ clientToken = credentials.clientToken;
782
+ }
783
+ catch (error) {
784
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, `Failed to decrypt frame credentials: ${String(error)}`);
785
+ return {};
786
+ }
787
+ }
788
+ if (channelId === CHANNEL_CHECK) {
789
+ await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_handleCheckOutcome).call(this, status, accessToken, clientToken);
790
+ return {};
791
+ }
792
+ // channelId === CHANNEL_AUTH, guaranteed by the expectedPhase guard above.
793
+ await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_handleAuthOutcome).call(this, status, accessToken);
794
+ return {};
765
795
  }
766
796
  /**
767
797
  * Builds the Check-frame URL, or `null` when no session exists yet.
@@ -769,7 +799,15 @@ class KycController extends base_controller_1.BaseController {
769
799
  * @returns The Check-frame URL or `null`.
770
800
  */
771
801
  buildCheckFrameUrl() {
772
- return __classPrivateFieldGet(this, _KycController_moonPayFrames, "f").buildCheckFrameUrl();
802
+ if (this.state.activeVendor !== 'moonpay' || !this.state.sessionToken) {
803
+ return null;
804
+ }
805
+ const url = new URL(`${FRAMES_BASE_URL}/check-connection`);
806
+ url.searchParams.set('sessionToken', this.state.sessionToken);
807
+ url.searchParams.set('publicKey', __classPrivateFieldGet(this, _KycController_keypair, "f").publicKeyHex);
808
+ url.searchParams.set('channelId', CHANNEL_CHECK);
809
+ url.searchParams.set('skipKyc', 'true');
810
+ return url.toString();
773
811
  }
774
812
  /**
775
813
  * Builds the Auth-frame URL, or `null` when no client token is available.
@@ -777,7 +815,14 @@ class KycController extends base_controller_1.BaseController {
777
815
  * @returns The Auth-frame URL or `null`.
778
816
  */
779
817
  buildAuthFrameUrl() {
780
- return __classPrivateFieldGet(this, _KycController_moonPayFrames, "f").buildAuthFrameUrl();
818
+ if (this.state.activeVendor !== 'moonpay' || !__classPrivateFieldGet(this, _KycController_authClientToken, "f")) {
819
+ return null;
820
+ }
821
+ const url = new URL(`${FRAMES_BASE_URL}/auth`);
822
+ url.searchParams.set('clientToken', __classPrivateFieldGet(this, _KycController_authClientToken, "f"));
823
+ url.searchParams.set('publicKey', __classPrivateFieldGet(this, _KycController_keypair, "f").publicKeyHex);
824
+ url.searchParams.set('channelId', CHANNEL_AUTH);
825
+ return url.toString();
781
826
  }
782
827
  /**
783
828
  * Builds the Reset-frame URL.
@@ -785,7 +830,9 @@ class KycController extends base_controller_1.BaseController {
785
830
  * @returns The Reset-frame URL.
786
831
  */
787
832
  buildResetFrameUrl() {
788
- return __classPrivateFieldGet(this, _KycController_moonPayFrames, "f").buildResetFrameUrl();
833
+ const url = new URL(`${FRAMES_BASE_URL}/reset`);
834
+ url.searchParams.set('channelId', CHANNEL_RESET);
835
+ return url.toString();
789
836
  }
790
837
  /**
791
838
  * Checks whether KYC is required for a product and caches the result.
@@ -796,9 +843,9 @@ class KycController extends base_controller_1.BaseController {
796
843
  * @returns Whether KYC is required.
797
844
  */
798
845
  async checkKycRequired(params) {
799
- const { moonpayAccessToken } = this.state;
800
- if (!moonpayAccessToken) {
801
- __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, 'Missing moonpayAccessToken — repeat the authentication step.');
846
+ const { accessToken } = this.state;
847
+ if (!accessToken) {
848
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, 'Missing accessToken — repeat the authentication step.');
802
849
  return false;
803
850
  }
804
851
  const country = params.country ?? this.state.geoCountry;
@@ -814,11 +861,7 @@ class KycController extends base_controller_1.BaseController {
814
861
  state.statusMessage = 'Checking KYC status...';
815
862
  });
816
863
  try {
817
- const { kycRequired } = await this.messenger.call('KycService:checkKycRequired', {
818
- accessToken: moonpayAccessToken,
819
- country,
820
- capabilities: [{ product: params.product }],
821
- });
864
+ const { kycRequired } = await this.messenger.call('KycService:checkKycRequired', { accessToken, country, capabilities: [{ product: params.product }] });
822
865
  // The flow was reset while the check was in flight; discard the result
823
866
  // rather than resurrecting a done/cached state on an idle controller.
824
867
  const applied = __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
@@ -1103,11 +1146,13 @@ class KycController extends base_controller_1.BaseController {
1103
1146
  state.phase = 'idle';
1104
1147
  state.statusMessage = '';
1105
1148
  state.error = null;
1106
- state.vendorDisclaimers = [];
1107
- state.vendorError = null;
1149
+ state.disclaimers = [];
1150
+ state.disclaimersError = null;
1108
1151
  state.sessionDisclaimers = null;
1109
1152
  state.credentialReusabilityConsentGiven = null;
1110
- (0, MoonPayFrameHandler_js_1.clearMoonPaySession)(state);
1153
+ state.sessionToken = null;
1154
+ state.accessToken = null;
1155
+ state.moonpayCustomerId = null;
1111
1156
  state.activeVendor = 'moonpay';
1112
1157
  state.activeProduct = null;
1113
1158
  state.sumsub = {
@@ -1135,7 +1180,7 @@ class KycController extends base_controller_1.BaseController {
1135
1180
  }
1136
1181
  }
1137
1182
  exports.KycController = KycController;
1138
- _KycController_sumsubLauncher = new WeakMap(), _KycController_moonPayFrames = new WeakMap(), _KycController_generation = new WeakMap(), _KycController_sessionStatusPollIntervalMs = new WeakMap(), _KycController_pollTimer = new WeakMap(), _KycController_pollToken = new WeakMap(), _KycController_userStatusPollIntervalMs = new WeakMap(), _KycController_userStatusPollTimer = new WeakMap(), _KycController_userStatusPolling = new WeakMap(), _KycController_userStatusPollToken = new WeakMap(), _KycController_instances = new WeakSet(), _KycController_localUserSecretStore = function _KycController_localUserSecretStore() {
1183
+ _KycController_sumsubLauncher = new WeakMap(), _KycController_keypair = new WeakMap(), _KycController_authClientToken = new WeakMap(), _KycController_generation = new WeakMap(), _KycController_sessionStatusPollIntervalMs = new WeakMap(), _KycController_pollTimer = new WeakMap(), _KycController_pollToken = new WeakMap(), _KycController_userStatusPollIntervalMs = new WeakMap(), _KycController_userStatusPollTimer = new WeakMap(), _KycController_userStatusPolling = new WeakMap(), _KycController_userStatusPollToken = new WeakMap(), _KycController_instances = new WeakSet(), _KycController_localUserSecretStore = function _KycController_localUserSecretStore() {
1139
1184
  return {
1140
1185
  get: async (path, entropySourceId) => this.messenger.call('UserStorageController:performGetStorage', path, entropySourceId),
1141
1186
  set: async (path, value, entropySourceId) => this.messenger.call('UserStorageController:performSetStorage', path, value, entropySourceId),
@@ -1147,14 +1192,13 @@ _KycController_sumsubLauncher = new WeakMap(), _KycController_moonPayFrames = ne
1147
1192
  * SumSub — skipping MoonPay Check/Auth frames.
1148
1193
  *
1149
1194
  * @param consents - T&C2 flags mapped onto the session disclaimer catalog.
1150
- * @param consents.providerDisclaimersAccepted - Accepted Sumsub disclaimer records.
1151
- * @param consents.idosDisclaimersAccepted - Accepted idOS disclaimer records.
1195
+ * @param consents.sumsubTncSigned - Whether Sumsub T&C were accepted.
1196
+ * @param consents.idosTncSigned - Whether idOS T&C were accepted.
1152
1197
  * @param consents.credentialReusabilityConsentGiven - Whether credential
1153
1198
  * reuse was accepted.
1154
1199
  */
1155
1200
  async function _KycController_startConsentsSession(consents) {
1156
- const { email } = this.state;
1157
- const acceptedDisclaimerIds = (0, vendorDisclaimerAcceptance_js_1.ironDisclaimerIds)(this.state.vendorDisclaimersAccepted);
1201
+ const { email, acceptedDisclaimerIds } = this.state;
1158
1202
  if (!email) {
1159
1203
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, 'Missing email for consents session.');
1160
1204
  return;
@@ -1172,7 +1216,7 @@ async function _KycController_startConsentsSession(consents) {
1172
1216
  state.sumsub.result = null;
1173
1217
  state.sumsub.sessionStatus = null;
1174
1218
  // Consents-path vendors have no MoonPay session/access tokens.
1175
- (0, MoonPayFrameHandler_js_1.clearMoonPaySession)(state);
1219
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearMoonPaySession).call(this, state);
1176
1220
  });
1177
1221
  try {
1178
1222
  await this.messenger.call('KycService:submitVendorDisclaimers', {
@@ -1198,7 +1242,7 @@ async function _KycController_startConsentsSession(consents) {
1198
1242
  await this.refreshKycStatus();
1199
1243
  }
1200
1244
  catch (statusError) {
1201
- (0, logger_js_1.controllerLog)('KYC status refresh failed:', statusError);
1245
+ console.error('KYC status refresh failed:', statusError);
1202
1246
  }
1203
1247
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
1204
1248
  state.phase = 'done';
@@ -1234,7 +1278,7 @@ async function _KycController_startConsentsSession(consents) {
1234
1278
  await this.refreshKycStatus();
1235
1279
  }
1236
1280
  catch (statusError) {
1237
- (0, logger_js_1.controllerLog)('KYC status refresh failed:', statusError);
1281
+ console.error('KYC status refresh failed:', statusError);
1238
1282
  }
1239
1283
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
1240
1284
  if (state.phase !== 'error' && state.phase !== 'done') {
@@ -1262,7 +1306,7 @@ async function _KycController_startConsentsSession(consents) {
1262
1306
  });
1263
1307
  return;
1264
1308
  }
1265
- (0, logger_js_1.controllerLog)('Consents session failed:', error);
1309
+ console.error('Consents session failed:', error);
1266
1310
  if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
1267
1311
  return;
1268
1312
  }
@@ -1289,8 +1333,8 @@ async function _KycController_startConsentsSession(consents) {
1289
1333
  *
1290
1334
  * @param sessionId - The UKYC session id.
1291
1335
  * @param consents - T&C2 flags mapped onto catalog documents.
1292
- * @param consents.providerDisclaimersAccepted - Accepted Sumsub disclaimer records.
1293
- * @param consents.idosDisclaimersAccepted - Accepted idOS disclaimer records.
1336
+ * @param consents.sumsubTncSigned - Whether Sumsub T&C were accepted.
1337
+ * @param consents.idosTncSigned - Whether idOS T&C were accepted.
1294
1338
  * @param consents.credentialReusabilityConsentGiven - Whether credential
1295
1339
  * reuse was accepted.
1296
1340
  * @param generation - Flow generation captured by the caller.
@@ -1304,12 +1348,12 @@ async function _KycController_recordSessionDisclaimers(sessionId, consents, gene
1304
1348
  state.sessionDisclaimers = catalog;
1305
1349
  state.statusMessage = 'Submitting consents...';
1306
1350
  });
1307
- if (isAcceptedCategoryEmpty(catalog.idOS, consents.idosDisclaimersAccepted) ||
1308
- isAcceptedCategoryEmpty(catalog.kycProvider, consents.providerDisclaimersAccepted)) {
1351
+ if (isAcceptedCategoryEmpty(catalog.idOS, consents.idosTncSigned) ||
1352
+ isAcceptedCategoryEmpty(catalog.kycProvider, consents.sumsubTncSigned)) {
1309
1353
  throw new Error('Session disclaimer catalog is missing documents for an accepted category.');
1310
1354
  }
1311
- const idOS = consentRecordsFromAcceptedList(catalog.idOS, consents.idosDisclaimersAccepted);
1312
- const kycProvider = consentRecordsFromAcceptedList(catalog.kycProvider, consents.providerDisclaimersAccepted);
1355
+ const idOS = consentRecordsFromCatalog(catalog.idOS, consents.idosTncSigned);
1356
+ const kycProvider = consentRecordsFromCatalog(catalog.kycProvider, consents.sumsubTncSigned);
1313
1357
  const reuseUnchanged = catalog.credentialReusabilityConsentGiven ===
1314
1358
  consents.credentialReusabilityConsentGiven;
1315
1359
  if (idOS.length === 0 && kycProvider.length === 0 && reuseUnchanged) {
@@ -1340,9 +1384,8 @@ async function _KycController_recordSessionDisclaimers(sessionId, consents, gene
1340
1384
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
1341
1385
  state.sessionDisclaimers = latest;
1342
1386
  });
1343
- // TODO: Should we really be doing client side validation of these?
1344
- const stillMissingIdos = acceptedCategoryStillMissing(latest.idOS, consents.idosDisclaimersAccepted);
1345
- const stillMissingProvider = acceptedCategoryStillMissing(latest.kycProvider, consents.providerDisclaimersAccepted);
1387
+ const stillMissingIdos = acceptedCategoryStillMissing(latest.idOS, consents.idosTncSigned);
1388
+ const stillMissingProvider = acceptedCategoryStillMissing(latest.kycProvider, consents.sumsubTncSigned);
1346
1389
  const stillMissingReuse = consents.credentialReusabilityConsentGiven &&
1347
1390
  !latest.credentialReusabilityConsentGiven;
1348
1391
  if (stillMissingIdos || stillMissingProvider || stillMissingReuse) {
@@ -1354,9 +1397,7 @@ async function _KycController_recordSessionDisclaimers(sessionId, consents, gene
1354
1397
  * Creates a vendor session from the currently stored terms + email.
1355
1398
  */
1356
1399
  async function _KycController_createSession() {
1357
- const { email } = this.state;
1358
- const termsAcceptedAt = this.state.vendorDisclaimersAccepted.moonpay?.termsAcceptedAt;
1359
- const acceptedDisclaimerIds = this.state.vendorDisclaimers.map((disclaimer) => disclaimer.id);
1400
+ const { email, termsAcceptedAt, acceptedDisclaimerIds } = this.state;
1360
1401
  if (!email) {
1361
1402
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, 'Missing email for session creation.');
1362
1403
  return;
@@ -1371,7 +1412,7 @@ async function _KycController_createSession() {
1371
1412
  // (or, on failure, invalid) session token, `buildAuthFrameUrl` cannot
1372
1413
  // return a URL tied to an old client token, and `checkKycRequired` cannot
1373
1414
  // run with an access token from an earlier authentication. The Check/Auth
1374
- // frames re-populate these for the new session. Because `moonpaySessionToken` is
1415
+ // frames re-populate these for the new session. Because `sessionToken` is
1375
1416
  // cleared here and only re-set on success, a failed creation leaves it
1376
1417
  // `null` rather than resurrecting the previous session.
1377
1418
  // Capture the flow generation so a `reset()` landing while the create
@@ -1379,24 +1420,24 @@ async function _KycController_createSession() {
1379
1420
  // the now-idle controller (failure). The synchronous update below runs
1380
1421
  // before any `await`, so it needs no guard.
1381
1422
  const generation = __classPrivateFieldGet(this, _KycController_generation, "f");
1382
- __classPrivateFieldGet(this, _KycController_moonPayFrames, "f").clearAuthentication();
1423
+ __classPrivateFieldSet(this, _KycController_authClientToken, null, "f");
1383
1424
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
1384
1425
  state.error = null;
1385
1426
  state.phase = 'session';
1386
1427
  state.statusMessage = 'Creating session...';
1387
- state.moonpaySessionToken = null;
1388
- state.moonpayAccessToken = null;
1428
+ state.sessionToken = null;
1429
+ state.accessToken = null;
1389
1430
  });
1390
1431
  try {
1391
1432
  const { sessionToken } = await this.messenger.call('KycService:createSession', { email, termsAcceptedAt, disclaimerIds: acceptedDisclaimerIds });
1392
1433
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
1393
- state.moonpaySessionToken = sessionToken;
1434
+ state.sessionToken = sessionToken;
1394
1435
  state.phase = 'check';
1395
1436
  state.statusMessage = 'Authenticating via Check frame...';
1396
1437
  });
1397
1438
  }
1398
1439
  catch (error) {
1399
- (0, logger_js_1.controllerLog)('Session creation failed:', error);
1440
+ console.error('Session creation failed:', error);
1400
1441
  // A reset() superseded this flow while the request was in flight; leave
1401
1442
  // the idle controller alone rather than forcing it back to `terms`.
1402
1443
  if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
@@ -1416,13 +1457,82 @@ async function _KycController_createSession() {
1416
1457
  });
1417
1458
  await this.loadDisclaimers();
1418
1459
  }
1419
- }, _KycController_clearAcceptedTerms = function _KycController_clearAcceptedTerms(state, vendor) {
1420
- const targetVendor = vendor ?? state.activeVendor;
1421
- state.vendorDisclaimersAccepted = (0, vendorDisclaimerAcceptance_js_1.clearVendorDisclaimerAcceptance)(state.vendorDisclaimersAccepted, targetVendor);
1422
- state.providerDisclaimersAccepted =
1423
- getDefaultKycProviderDisclaimersAccepted();
1424
- state.idosDisclaimersAccepted = null;
1460
+ }, _KycController_clearAcceptedTerms = function _KycController_clearAcceptedTerms(state) {
1461
+ state.termsAcceptedAt = null;
1462
+ state.acceptedDisclaimerIds = [];
1463
+ state.termsAcceptedVendor = null;
1464
+ state.sumsubTncAccepted = null;
1465
+ state.idosTncAccepted = null;
1425
1466
  state.credentialReusabilityConsentGiven = null;
1467
+ }, _KycController_clearMoonPaySession = function _KycController_clearMoonPaySession(state) {
1468
+ state.moonpayCustomerId = null;
1469
+ state.sessionToken = null;
1470
+ state.accessToken = null;
1471
+ }, _KycController_dropTermsUnlessForVendor = function _KycController_dropTermsUnlessForVendor(vendor) {
1472
+ if (__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_hasTermsForVendor).call(this, vendor)) {
1473
+ return;
1474
+ }
1475
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
1476
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearAcceptedTerms).call(this, state);
1477
+ });
1478
+ }, _KycController_hasTermsForVendor = function _KycController_hasTermsForVendor(vendor) {
1479
+ if (this.state.termsAcceptedVendor === null) {
1480
+ return false;
1481
+ }
1482
+ return this.state.termsAcceptedVendor === vendor;
1483
+ }, _KycController_handleCheckOutcome =
1484
+ /**
1485
+ * Applies a Check-frame outcome.
1486
+ *
1487
+ * @param status - The frame status.
1488
+ * @param accessToken - The decrypted access token, if any.
1489
+ * @param clientToken - The decrypted client token, if any.
1490
+ */
1491
+ async function _KycController_handleCheckOutcome(status, accessToken, clientToken) {
1492
+ if (status === 'active' && accessToken) {
1493
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
1494
+ state.accessToken = accessToken;
1495
+ state.phase = 'form';
1496
+ state.statusMessage = 'Already authenticated. Review to submit.';
1497
+ });
1498
+ await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_continueAfterAuthentication).call(this);
1499
+ return;
1500
+ }
1501
+ if (status === 'connectionRequired' && clientToken) {
1502
+ __classPrivateFieldSet(this, _KycController_authClientToken, clientToken, "f");
1503
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
1504
+ state.phase = 'auth';
1505
+ state.statusMessage = 'Verify your email via OTP in the Auth frame.';
1506
+ });
1507
+ return;
1508
+ }
1509
+ if (status === 'termsAcceptanceRequired') {
1510
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_requireTermsReacceptance).call(this);
1511
+ return;
1512
+ }
1513
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, `Check frame returned status: ${status}`);
1514
+ }, _KycController_handleAuthOutcome =
1515
+ /**
1516
+ * Applies an Auth-frame outcome.
1517
+ *
1518
+ * @param status - The frame status.
1519
+ * @param accessToken - The decrypted access token, if any.
1520
+ */
1521
+ async function _KycController_handleAuthOutcome(status, accessToken) {
1522
+ if (status === 'active' && accessToken) {
1523
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
1524
+ state.accessToken = accessToken;
1525
+ state.phase = 'form';
1526
+ state.statusMessage = 'Authenticated. Review to submit.';
1527
+ });
1528
+ await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_continueAfterAuthentication).call(this);
1529
+ return;
1530
+ }
1531
+ if (status === 'termsAcceptanceRequired') {
1532
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_requireTermsReacceptance).call(this);
1533
+ return;
1534
+ }
1535
+ __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, `Auth frame returned status: ${status}`);
1426
1536
  }, _KycController_continueAfterAuthentication =
1427
1537
  /**
1428
1538
  * Continues the flow once authentication has completed (phase `form`).
@@ -1474,7 +1584,7 @@ async function _KycController_continueAfterAuthentication() {
1474
1584
  return {
1475
1585
  vendor: 'moonpay',
1476
1586
  vendorMetadata: {
1477
- moonPayAccessToken: this.state.moonpayAccessToken,
1587
+ moonPayAccessToken: this.state.accessToken,
1478
1588
  moonPayUserId: this.state.moonpayCustomerId,
1479
1589
  },
1480
1590
  };
@@ -1542,8 +1652,7 @@ async function _KycController_createUkycSession(generation) {
1542
1652
  // authorizes later storage reads without granting write or delete access.
1543
1653
  const ukycCapabilityToken = (0, storageAccessToken_js_1.signStorageAccessToken)({
1544
1654
  material: clientMaterial,
1545
- // TODO: Confirm with idOS when this can be switched back to read and a separate token is sent for write
1546
- operations: ['read', 'write'],
1655
+ operations: ['read'],
1547
1656
  expiresAt: new Date(Date.now() + UKYC_CAPABILITY_TOKEN_TTL_MS),
1548
1657
  });
1549
1658
  const wrappedUkycCapabilityToken = (0, wrapEncryptionKey_js_1.wrapEncryptionKey)(sessionClientPrivateKey, capabilityTokenSchema.serverPublicKey.x, (0, utils_1.stringToBytes)((0, storageAccessToken_js_1.encodeStorageAccessTokenForHeader)(ukycCapabilityToken)));
@@ -1730,7 +1839,7 @@ async function _KycController_pollSessionStatusOnce(sessionId, token) {
1730
1839
  __classPrivateFieldSet(this, _KycController_pollTimer, null, "f");
1731
1840
  }
1732
1841
  }, _KycController_cancelPendingSession = function _KycController_cancelPendingSession() {
1733
- __classPrivateFieldGet(this, _KycController_moonPayFrames, "f").clear();
1842
+ __classPrivateFieldSet(this, _KycController_authClientToken, null, "f");
1734
1843
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_stopPolling).call(this);
1735
1844
  __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_stopUserStatusPolling).call(this);
1736
1845
  __classPrivateFieldSet(this, _KycController_generation, __classPrivateFieldGet(this, _KycController_generation, "f") + 1, "f");