smartcomply-web-sdk 1.0.89 → 1.0.91

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 (49) hide show
  1. package/dist/camera/ActionDetector.d.ts +2 -1
  2. package/dist/camera/ActionDetector.d.ts.map +1 -1
  3. package/dist/camera/ActionDetector.js +21 -5
  4. package/dist/camera/ActionDetector.js.map +1 -1
  5. package/dist/client/Smartcomply.d.ts +14 -2
  6. package/dist/client/Smartcomply.d.ts.map +1 -1
  7. package/dist/client/Smartcomply.js +15 -2
  8. package/dist/client/Smartcomply.js.map +1 -1
  9. package/dist/esm/camera/ActionDetector.d.ts +2 -1
  10. package/dist/esm/camera/ActionDetector.d.ts.map +1 -1
  11. package/dist/esm/camera/ActionDetector.js +21 -5
  12. package/dist/esm/camera/ActionDetector.js.map +1 -1
  13. package/dist/esm/client/Smartcomply.d.ts +14 -2
  14. package/dist/esm/client/Smartcomply.d.ts.map +1 -1
  15. package/dist/esm/client/Smartcomply.js +15 -2
  16. package/dist/esm/client/Smartcomply.js.map +1 -1
  17. package/dist/esm/flow/SmartComplyFlow.d.ts +24 -9
  18. package/dist/esm/flow/SmartComplyFlow.d.ts.map +1 -1
  19. package/dist/esm/flow/SmartComplyFlow.js +151 -25
  20. package/dist/esm/flow/SmartComplyFlow.js.map +1 -1
  21. package/dist/esm/flow/spinner.js +14 -14
  22. package/dist/esm/index.d.ts +1 -1
  23. package/dist/esm/index.d.ts.map +1 -1
  24. package/dist/esm/index.js.map +1 -1
  25. package/dist/esm/modules/liveness/LivenessUI.js +83 -83
  26. package/dist/esm/types/liveness.d.ts +15 -0
  27. package/dist/esm/types/liveness.d.ts.map +1 -1
  28. package/dist/flow/SmartComplyFlow.d.ts +24 -9
  29. package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
  30. package/dist/flow/SmartComplyFlow.js +152 -25
  31. package/dist/flow/SmartComplyFlow.js.map +1 -1
  32. package/dist/flow/spinner.js +14 -14
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/modules/liveness/LivenessUI.js +83 -83
  37. package/dist/smartcomply.browser.js +108 -11
  38. package/dist/smartcomply.browser.js.map +3 -3
  39. package/dist/types/liveness.d.ts +15 -0
  40. package/dist/types/liveness.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/dist/esm/components/CameraView.d.ts +0 -59
  43. package/dist/esm/components/CameraView.d.ts.map +0 -1
  44. package/dist/esm/components/CameraView.js +0 -238
  45. package/dist/esm/components/CameraView.js.map +0 -1
  46. package/dist/esm/components/DocumentUpload.d.ts +0 -21
  47. package/dist/esm/components/DocumentUpload.d.ts.map +0 -1
  48. package/dist/esm/components/DocumentUpload.js +0 -216
  49. package/dist/esm/components/DocumentUpload.js.map +0 -1
@@ -3,30 +3,30 @@ function injectLivenessKeyframes() {
3
3
  return;
4
4
  const s = document.createElement("style");
5
5
  s.id = "sc-liveness-kf";
6
- s.textContent = `
7
- @keyframes sc-pop-in {
8
- 0% { transform:scale(0.7); opacity:0; }
9
- 60% { transform:scale(1.05); }
10
- 100% { transform:scale(1); opacity:1; }
11
- }
12
- @keyframes sc-scan-dot {
13
- 0%,100% { opacity:0.3; transform:scale(0.85); }
14
- 50% { opacity:1; transform:scale(1); }
15
- }
16
- @keyframes sc-scanline-sweep {
17
- 0% { transform:translateY(-4%); opacity:0; }
18
- 8% { opacity:0.9; }
19
- 92% { opacity:0.9; }
20
- 100% { transform:translateY(104%); opacity:0; }
21
- }
22
- @keyframes sc-corner-pulse {
23
- 0%,100% { opacity:0.55; }
24
- 50% { opacity:1; }
25
- }
26
- @keyframes sc-oval-breathe {
27
- 0%,100% { opacity:0.5; }
28
- 50% { opacity:0.85; }
29
- }
6
+ s.textContent = `
7
+ @keyframes sc-pop-in {
8
+ 0% { transform:scale(0.7); opacity:0; }
9
+ 60% { transform:scale(1.05); }
10
+ 100% { transform:scale(1); opacity:1; }
11
+ }
12
+ @keyframes sc-scan-dot {
13
+ 0%,100% { opacity:0.3; transform:scale(0.85); }
14
+ 50% { opacity:1; transform:scale(1); }
15
+ }
16
+ @keyframes sc-scanline-sweep {
17
+ 0% { transform:translateY(-4%); opacity:0; }
18
+ 8% { opacity:0.9; }
19
+ 92% { opacity:0.9; }
20
+ 100% { transform:translateY(104%); opacity:0; }
21
+ }
22
+ @keyframes sc-corner-pulse {
23
+ 0%,100% { opacity:0.55; }
24
+ 50% { opacity:1; }
25
+ }
26
+ @keyframes sc-oval-breathe {
27
+ 0%,100% { opacity:0.5; }
28
+ 50% { opacity:0.85; }
29
+ }
30
30
  `;
31
31
  document.head.appendChild(s);
32
32
  }
@@ -56,38 +56,38 @@ export class LivenessUI {
56
56
  mount(container, challenge) {
57
57
  injectLivenessKeyframes();
58
58
  this.root = document.createElement("div");
59
- this.root.style.cssText = `
60
- position:relative;width:100%;max-width:420px;margin:0 auto;
61
- background:#0a0a0a;border-radius:16px;overflow:hidden;
62
- font-family:system-ui,-apple-system,sans-serif;
63
- box-shadow:0 8px 32px rgba(0,0,0,0.4);
64
- aspect-ratio:3/4;
59
+ this.root.style.cssText = `
60
+ position:relative;width:100%;max-width:420px;margin:0 auto;
61
+ background:#0a0a0a;border-radius:16px;overflow:hidden;
62
+ font-family:system-ui,-apple-system,sans-serif;
63
+ box-shadow:0 8px 32px rgba(0,0,0,0.4);
64
+ aspect-ratio:3/4;
65
65
  `;
66
66
  this.videoEl = document.createElement("video");
67
67
  this.videoEl.autoplay = true;
68
68
  this.videoEl.playsInline = true;
69
69
  this.videoEl.muted = true;
70
70
  this.videoEl.setAttribute("aria-label", "Live camera preview for face verification");
71
- this.videoEl.style.cssText = `
72
- width:100%;height:100%;display:block;
73
- filter:brightness(1.03) contrast(1.03);
74
- transform:scaleX(-1);object-fit:cover;
71
+ this.videoEl.style.cssText = `
72
+ width:100%;height:100%;display:block;
73
+ filter:brightness(1.03) contrast(1.03);
74
+ transform:scaleX(-1);object-fit:cover;
75
75
  `;
76
76
  // Dim everything outside the oval so the guide reads as a scan aperture
77
77
  // rather than a shape floating over the raw feed.
78
78
  const vignette = document.createElement("div");
79
- vignette.style.cssText = `
80
- position:absolute;inset:0;pointer-events:none;
81
- background:radial-gradient(ellipse 34% 44% at 50% 47%, transparent 55%, rgba(0,0,0,0.55) 100%);
79
+ vignette.style.cssText = `
80
+ position:absolute;inset:0;pointer-events:none;
81
+ background:radial-gradient(ellipse 34% 44% at 50% 47%, transparent 55%, rgba(0,0,0,0.55) 100%);
82
82
  `;
83
83
  // Oval guide — centred
84
84
  const guideWrap = document.createElement("div");
85
- guideWrap.style.cssText = `
86
- position:absolute;top:50%;left:50%;
87
- transform:translate(-50%,-52%);
88
- width:64%;aspect-ratio:140/180;pointer-events:none;
89
- filter:drop-shadow(0 0 18px rgba(59,130,246,0.35));
90
- transition:filter 0.3s ease;
85
+ guideWrap.style.cssText = `
86
+ position:absolute;top:50%;left:50%;
87
+ transform:translate(-50%,-52%);
88
+ width:64%;aspect-ratio:140/180;pointer-events:none;
89
+ filter:drop-shadow(0 0 18px rgba(59,130,246,0.35));
90
+ transition:filter 0.3s ease;
91
91
  `;
92
92
  this.guideWrapEl = guideWrap;
93
93
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
@@ -176,49 +176,49 @@ export class LivenessUI {
176
176
  // Scan-line sweep — clipped to the oval, gives a visible "actively
177
177
  // scanning" motion cue instead of a static outline.
178
178
  const scanlineClipWrap = document.createElement("div");
179
- scanlineClipWrap.style.cssText = `
180
- position:absolute;inset:0;
181
- clip-path:ellipse(45.7% 47.8% at 50% 50%);
182
- overflow:hidden;
179
+ scanlineClipWrap.style.cssText = `
180
+ position:absolute;inset:0;
181
+ clip-path:ellipse(45.7% 47.8% at 50% 50%);
182
+ overflow:hidden;
183
183
  `;
184
184
  const scanline = document.createElement("div");
185
- scanline.style.cssText = `
186
- position:absolute;left:0;right:0;height:26%;top:0;
187
- background:linear-gradient(180deg,transparent 0%,rgba(59,130,246,0.32) 45%,rgba(147,197,253,0.55) 50%,rgba(59,130,246,0.32) 55%,transparent 100%);
188
- animation:sc-scanline-sweep 2.6s ease-in-out infinite;
185
+ scanline.style.cssText = `
186
+ position:absolute;left:0;right:0;height:26%;top:0;
187
+ background:linear-gradient(180deg,transparent 0%,rgba(59,130,246,0.32) 45%,rgba(147,197,253,0.55) 50%,rgba(59,130,246,0.32) 55%,transparent 100%);
188
+ animation:sc-scanline-sweep 2.6s ease-in-out infinite;
189
189
  `;
190
190
  this.scanlineEl = scanline;
191
191
  scanlineClipWrap.appendChild(scanline);
192
192
  guideWrap.appendChild(scanlineClipWrap);
193
193
  // Instruction — top, gradient scrim
194
194
  const camTop = document.createElement("div");
195
- camTop.style.cssText = `
196
- position:absolute;top:0;left:0;right:0;
197
- background:linear-gradient(180deg,rgba(0,0,0,0.8) 0%,transparent 100%);
198
- padding:14px 16px 32px;
195
+ camTop.style.cssText = `
196
+ position:absolute;top:0;left:0;right:0;
197
+ background:linear-gradient(180deg,rgba(0,0,0,0.8) 0%,transparent 100%);
198
+ padding:14px 16px 32px;
199
199
  `;
200
200
  this.instructionEl = document.createElement("div");
201
201
  this.instructionEl.setAttribute("aria-live", "polite");
202
202
  this.instructionEl.setAttribute("role", "status");
203
- this.instructionEl.style.cssText = `
204
- color:#fff;font-size:14px;font-weight:600;text-align:center;line-height:1.4;
203
+ this.instructionEl.style.cssText = `
204
+ color:#fff;font-size:14px;font-weight:600;text-align:center;line-height:1.4;
205
205
  `;
206
206
  this.instructionEl.textContent = challenge.instruction;
207
207
  camTop.appendChild(this.instructionEl);
208
208
  // Scan progress dots — bottom
209
209
  const camBottom = document.createElement("div");
210
- camBottom.style.cssText = `
211
- position:absolute;bottom:0;left:0;right:0;
212
- background:linear-gradient(0deg,rgba(0,0,0,0.7) 0%,transparent 100%);
213
- padding:28px 10px 18px;display:flex;justify-content:center;
210
+ camBottom.style.cssText = `
211
+ position:absolute;bottom:0;left:0;right:0;
212
+ background:linear-gradient(0deg,rgba(0,0,0,0.7) 0%,transparent 100%);
213
+ padding:28px 10px 18px;display:flex;justify-content:center;
214
214
  `;
215
215
  this.dotsEl = document.createElement("div");
216
216
  this.dotsEl.style.cssText = "display:flex;gap:6px;";
217
217
  for (let i = 0; i < 3; i++) {
218
218
  const dot = document.createElement("div");
219
- dot.style.cssText = `
220
- width:6px;height:6px;border-radius:50%;background:${this.colors.primary};
221
- animation:sc-scan-dot 1.1s ease-in-out ${i * 0.18}s infinite;
219
+ dot.style.cssText = `
220
+ width:6px;height:6px;border-radius:50%;background:${this.colors.primary};
221
+ animation:sc-scan-dot 1.1s ease-in-out ${i * 0.18}s infinite;
222
222
  `;
223
223
  this.dotsEl.appendChild(dot);
224
224
  }
@@ -230,10 +230,10 @@ export class LivenessUI {
230
230
  this.root.appendChild(camBottom);
231
231
  // Result overlay
232
232
  this.overlayEl = document.createElement("div");
233
- this.overlayEl.style.cssText = `
234
- position:absolute;inset:0;display:none;align-items:center;
235
- justify-content:center;z-index:10;
236
- background:rgba(0,0,0,0.88);backdrop-filter:blur(8px);
233
+ this.overlayEl.style.cssText = `
234
+ position:absolute;inset:0;display:none;align-items:center;
235
+ justify-content:center;z-index:10;
236
+ background:rgba(0,0,0,0.88);backdrop-filter:blur(8px);
237
237
  `;
238
238
  this.root.appendChild(this.overlayEl);
239
239
  container.appendChild(this.root);
@@ -294,15 +294,15 @@ export class LivenessUI {
294
294
  }
295
295
  const ok = status === "processing";
296
296
  this.overlayEl.style.display = "flex";
297
- this.overlayEl.innerHTML = `
298
- <div style="text-align:center;color:#fff;animation:sc-pop-in 0.35s ease;padding:24px;">
299
- <div style="width:72px;height:72px;border-radius:50%;margin:0 auto 16px;display:flex;align-items:center;justify-content:center;font-size:32px;
300
- background:${ok ? "rgba(34,197,94,0.2)" : "rgba(239,68,68,0.2)"};
301
- border:3px solid ${ok ? this.colors.success : this.colors.error};">
302
- ${ok ? "✓" : "✕"}
303
- </div>
304
- <div style="font-size:17px;font-weight:700;margin-bottom:8px;">${ok ? "Verification submitted" : "Submission failed"}</div>
305
- <div style="font-size:12px;opacity:0.6;line-height:1.6;">${ok ? "Hold on while we wrap up…" : "Something went wrong. Please try again."}</div>
297
+ this.overlayEl.innerHTML = `
298
+ <div style="text-align:center;color:#fff;animation:sc-pop-in 0.35s ease;padding:24px;">
299
+ <div style="width:72px;height:72px;border-radius:50%;margin:0 auto 16px;display:flex;align-items:center;justify-content:center;font-size:32px;
300
+ background:${ok ? "rgba(34,197,94,0.2)" : "rgba(239,68,68,0.2)"};
301
+ border:3px solid ${ok ? this.colors.success : this.colors.error};">
302
+ ${ok ? "✓" : "✕"}
303
+ </div>
304
+ <div style="font-size:17px;font-weight:700;margin-bottom:8px;">${ok ? "Verification submitted" : "Submission failed"}</div>
305
+ <div style="font-size:12px;opacity:0.6;line-height:1.6;">${ok ? "Hold on while we wrap up…" : "Something went wrong. Please try again."}</div>
306
306
  </div>`;
307
307
  setTimeout(resolve, 1800);
308
308
  });
@@ -314,12 +314,12 @@ export class LivenessUI {
314
314
  return;
315
315
  }
316
316
  this.overlayEl.style.display = "flex";
317
- this.overlayEl.innerHTML = `
318
- <div style="text-align:center;color:#fff;animation:sc-pop-in 0.35s ease;padding:24px;">
319
- <div style="width:72px;height:72px;border-radius:50%;margin:0 auto 14px;display:flex;align-items:center;justify-content:center;font-size:32px;background:rgba(251,191,36,0.15);border:3px solid ${this.colors.warning};">⏱</div>
320
- <div style="font-size:17px;font-weight:700;margin-bottom:8px;">Time's Up</div>
321
- <div style="font-size:12px;opacity:0.6;margin-bottom:18px;">We couldn't confirm liveness in time. Please try again.</div>
322
- <button id="sc-retry-btn" style="padding:11px 28px;border-radius:10px;background:${this.colors.primary};color:#fff;border:none;cursor:pointer;font-size:14px;font-weight:600;width:100%;max-width:180px;">Try Again</button>
317
+ this.overlayEl.innerHTML = `
318
+ <div style="text-align:center;color:#fff;animation:sc-pop-in 0.35s ease;padding:24px;">
319
+ <div style="width:72px;height:72px;border-radius:50%;margin:0 auto 14px;display:flex;align-items:center;justify-content:center;font-size:32px;background:rgba(251,191,36,0.15);border:3px solid ${this.colors.warning};">⏱</div>
320
+ <div style="font-size:17px;font-weight:700;margin-bottom:8px;">Time's Up</div>
321
+ <div style="font-size:12px;opacity:0.6;margin-bottom:18px;">We couldn't confirm liveness in time. Please try again.</div>
322
+ <button id="sc-retry-btn" style="padding:11px 28px;border-radius:10px;background:${this.colors.primary};color:#fff;border:none;cursor:pointer;font-size:14px;font-weight:600;width:100%;max-width:180px;">Try Again</button>
323
323
  </div>`;
324
324
  const btn = this.overlayEl.querySelector("#sc-retry-btn");
325
325
  if (btn) {
@@ -31,6 +31,21 @@ export type LivenessEntryStatus = "pending" | "processing" | "passed" | "failed"
31
31
  * Mirrors DocumentVerification.STATUS_CHOICES on the backend (sdk/models.py).
32
32
  */
33
33
  export type DocumentVerificationStatus = "pending" | "ocr_complete" | "verified" | "failed" | "expired_document";
34
+ /**
35
+ * Response from GET /v1/sdk/liveness/resume-info/ (unwrapped).
36
+ * Read-only lookup for a client-initiated resubmit's resume_token — tells
37
+ * the widget which entry/step it's resuming before create/ is ever called.
38
+ * identifier_type/country mirror the entry's original submission so the
39
+ * widget can pre-select the same channel instead of guessing.
40
+ */
41
+ export interface LivenessResumeInfoResponse {
42
+ id: number;
43
+ status: string;
44
+ failure_stage: "document" | "liveness" | "data_match" | null;
45
+ verification_type: "document_verification" | "data_verification" | "liveness_only";
46
+ country: string | null;
47
+ identifier_type: string | null;
48
+ }
34
49
  /**
35
50
  * Response from POST /v1/sdk/liveness/create/ (unwrapped).
36
51
  */
@@ -1 +1 @@
1
- {"version":3,"file":"liveness.d.ts","sourceRoot":"","sources":["../../../src/types/liveness.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"liveness.d.ts","sourceRoot":"","sources":["../../../src/types/liveness.ts"],"names":[],"mappings":"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"}
@@ -14,15 +14,19 @@ export interface FlowOptions {
14
14
  * deep-link payload, etc.) and pass it straight through here; the SDK
15
15
  * does not parse the host page's URL itself.
16
16
  *
17
- * This authenticates the widget as the resumed session instead of
18
- * creating a new one, so the backend's own resume-match (LivenessCreateAPIView)
19
- * applies on the customer's next create/submit call. It does NOT yet
20
- * skip the widget's own UI screens (country/ID-type/welcome still show
21
- * as normal) — the backend-side "only ask for what's missing" behavior
22
- * (e.g. reusing an already-passed liveness capture on a document-only
23
- * retry) still applies once create/ is called, but the widget doesn't
24
- * yet inspect failure_stage to pre-select a step. That's tracked as
25
- * separate follow-up UI work, not part of this flag.
17
+ * Authenticates the widget as the resumed session (instead of creating a
18
+ * new one) and looks up which step failed, so the customer lands
19
+ * directly on document_capture or liveness instead of the welcome
20
+ * screen — skipping country/ID-type selection, which is pre-filled from
21
+ * the original attempt. Falls back to the normal welcome screen if that
22
+ * lookup doesn't resolve cleanly (an already-used/expired token, or the
23
+ * original channel no longer exists in this config); the resume itself
24
+ * still works correctly via the backend's own resume-match once
25
+ * create/submit is called either way — this only affects which screen
26
+ * is shown first.
27
+ *
28
+ * A data-verification/liveness-only failure has no document channel to
29
+ * re-select, so it goes straight to the liveness step.
26
30
  */
27
31
  resumeToken?: string;
28
32
  onComplete?: (result: FlowResult) => void;
@@ -36,6 +40,16 @@ export interface FlowResult {
36
40
  submittedAt: string | null;
37
41
  verificationResult?: VerifyIdentityResponse;
38
42
  }
43
+ /**
44
+ * Whether a showErrorStep() message is about an expired/invalid resume or
45
+ * resubmit link (RESUME_TARGET_UNAVAILABLE / NOT_A_RESUME_TOKEN — see
46
+ * SmartComplyFlow._resolveResumeStep), rather than a plain session timeout.
47
+ * Extracted to a standalone function so this specific classification is
48
+ * independently testable, same as resolveIdTypeInfo below — showErrorStep's
49
+ * own regex-based classification block is otherwise tightly coupled to DOM
50
+ * rendering it doesn't make sense to extract wholesale for this fix.
51
+ */
52
+ export declare function isResumeLinkErrorMessage(message: string): boolean;
39
53
  export declare function resolveIdTypeInfo(typeName: string, isDocumentFlow: boolean): {
40
54
  icon: string;
41
55
  desc: string;
@@ -117,6 +131,7 @@ export declare class SmartComplyFlow {
117
131
  close(): void;
118
132
  private mount;
119
133
  private initialize;
134
+ private _resolveResumeStep;
120
135
  private _showExpiryWarningWhenSafe;
121
136
  private static readonly MAX_EXPIRY_DEFERRALS;
122
137
  private _expiryDeferrals;
@@ -1 +1 @@
1
- {"version":3,"file":"SmartComplyFlow.d.ts","sourceRoot":"","sources":["../../src/flow/SmartComplyFlow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SmartComplyFlow.d.ts","sourceRoot":"","sources":["../../src/flow/SmartComplyFlow.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SmartComplyFlow = void 0;
4
+ exports.isResumeLinkErrorMessage = isResumeLinkErrorMessage;
4
5
  exports.resolveIdTypeInfo = resolveIdTypeInfo;
5
6
  const Smartcomply_1 = require("../client/Smartcomply");
6
7
  const theme_1 = require("./theme");
@@ -10,6 +11,7 @@ const documentRules_1 = require("../utils/documentRules");
10
11
  const constants_1 = require("../utils/constants");
11
12
  const icons_1 = require("./icons");
12
13
  const spinner_1 = require("./spinner");
14
+ const SDKError_1 = require("../errors/SDKError");
13
15
  // A dropped camera/network/upload error is not the user's fault and must not
14
16
  // cost them a retry attempt — only a genuine verification outcome should.
15
17
  // Classified by message rather than a typed error class since the errors
@@ -70,6 +72,18 @@ const COUNTRY_LABELS = {
70
72
  function isUploadFieldType(type) {
71
73
  return type === "upload" || type === "image" || type === "file";
72
74
  }
75
+ /**
76
+ * Whether a showErrorStep() message is about an expired/invalid resume or
77
+ * resubmit link (RESUME_TARGET_UNAVAILABLE / NOT_A_RESUME_TOKEN — see
78
+ * SmartComplyFlow._resolveResumeStep), rather than a plain session timeout.
79
+ * Extracted to a standalone function so this specific classification is
80
+ * independently testable, same as resolveIdTypeInfo below — showErrorStep's
81
+ * own regex-based classification block is otherwise tightly coupled to DOM
82
+ * rendering it doesn't make sense to extract wholesale for this fix.
83
+ */
84
+ function isResumeLinkErrorMessage(message) {
85
+ return /resume link|resubmit link/i.test(message);
86
+ }
73
87
  function resolveIdTypeInfo(typeName, isDocumentFlow) {
74
88
  const u = typeName.toUpperCase();
75
89
  const advanced = u.includes("ADVANCED");
@@ -658,12 +672,114 @@ class SmartComplyFlow {
658
672
  }
659
673
  if (this.isDestroyed)
660
674
  return;
661
- this.showStep("welcome");
675
+ if (this.options.resumeToken) {
676
+ // null means _resolveResumeStep already rendered an error itself
677
+ // (a provably expired/invalid resume link — see that method) and
678
+ // there is no step left to show; calling showStep() in that case
679
+ // would wipe the error message straight back out.
680
+ const resumeStep = await this._resolveResumeStep();
681
+ if (resumeStep !== null)
682
+ this.showStep(resumeStep);
683
+ }
684
+ else {
685
+ this.showStep("welcome");
686
+ }
662
687
  }
663
688
  catch (err) {
664
689
  this.showErrorStep(err.message || "Failed to initialize. Please try again.");
665
690
  }
666
691
  }
692
+ // Resolves a resume_token to the step the customer should land on,
693
+ // pre-selecting the same country/ID type the original attempt used (the
694
+ // same state renderCountrySelect/renderIdTypeSelect's own click handlers
695
+ // set) so document_capture/liveness render correctly instead of assuming
696
+ // state that was never set. Falls back to "welcome" on anything that
697
+ // doesn't resolve cleanly for an UNCERTAIN reason (network error, timeout)
698
+ // — this is a UX improvement, not a requirement: the backend's own
699
+ // resume-match at create/ time still works correctly even if the widget
700
+ // can't figure out which screen to pre-select.
701
+ //
702
+ // Returns null instead when the lookup fails for a CERTAIN, known reason
703
+ // — the resume link itself is provably expired or already used
704
+ // (RESUME_TARGET_UNAVAILABLE) or was never a resume link at all
705
+ // (NOT_A_RESUME_TOKEN). Unlike a transient failure, there is no "try the
706
+ // real request and it'll still work" fallback for these: create/'s own
707
+ // resume-match reads the exact same resume_target_entry binding this
708
+ // lookup just found missing/invalid, so falling through to a generic
709
+ // welcome screen would silently walk the customer into a brand-new,
710
+ // unrelated verification attempt with no explanation — worse than telling
711
+ // them plainly that their link no longer works. The caller shows this
712
+ // error itself (via showErrorStep, called here directly) rather than
713
+ // rendering a step.
714
+ async _resolveResumeStep() {
715
+ try {
716
+ const info = await this.sdk.getResumeInfo();
717
+ if (info.verification_type === "liveness_only" ||
718
+ info.failure_stage === "liveness" ||
719
+ // data_match is always a selfie-vs-identity-photo mismatch (see the
720
+ // backend's own comment in _process_identity_face_match) — fixed by
721
+ // redoing the selfie/video, same as a "liveness" failure. There is
722
+ // no document step in data verification at all, so this can never
723
+ // legitimately need document_capture.
724
+ info.failure_stage === "data_match") {
725
+ // Nothing to re-select — there's no document channel to pick, just
726
+ // liveness itself to redo. selectedCountry still needs a non-blank
727
+ // value (renderLiveness sends it as a required field) the same way
728
+ // the liveness-only welcome-screen path already handles this.
729
+ this.selectedCountry = info.country || this.selectedCountry || "global";
730
+ return "liveness";
731
+ }
732
+ if (info.failure_stage === "document" && info.country && info.identifier_type) {
733
+ const channels = this.sdkConfig?.channels || {};
734
+ const idTypes = channels[info.country] || [];
735
+ const match = idTypes.find((idType) => {
736
+ const code = typeof idType === "string" ? idType : (idType.code || idType.name);
737
+ return code === info.identifier_type;
738
+ });
739
+ if (match) {
740
+ const typeName = typeof match === "string" ? match : match.name;
741
+ const typeCode = typeof match === "string" ? match : (match.code || match.name);
742
+ const channelFields = typeof match !== "string" ? (match.fields || []) : [];
743
+ const isDocFlow = channelFields.some((f) => isUploadFieldType(f.type)) || this.isDocumentFlow();
744
+ const info2 = resolveIdTypeInfo(typeName, isDocFlow);
745
+ const requiresBackFromBackend = typeof match !== "string" ? match.requires_back_side : undefined;
746
+ this.selectedCountry = info.country;
747
+ this.selectedIdType = typeCode;
748
+ this.selectedIdTypeName = typeName;
749
+ this.selectedRequiresBack = requiresBackFromBackend ?? info2.requiresBack;
750
+ if (typeof match !== "string") {
751
+ this.selectedChannelId = match.id;
752
+ this.selectedChannelFields = match.fields || [];
753
+ }
754
+ return "document_capture";
755
+ }
756
+ // Channel from the original submission no longer exists in this
757
+ // config (e.g. it was disabled since) — fall through to welcome
758
+ // rather than render document_capture with no title/back-side info.
759
+ }
760
+ // Nothing above matched cleanly (e.g. a document channel that no
761
+ // longer exists in this config) — the entry is still correctly bound
762
+ // server-side regardless of which screen the widget shows first.
763
+ return "welcome";
764
+ }
765
+ catch (err) {
766
+ const code = err instanceof SDKError_1.SDKError ? err.errorCode : undefined;
767
+ if (code === "RESUME_TARGET_UNAVAILABLE" || code === "NOT_A_RESUME_TOKEN") {
768
+ // A certain, known failure — this specific link is provably no
769
+ // longer usable (already used, expired, or was never a resume link
770
+ // at all). Tell the customer plainly rather than silently starting
771
+ // a new, unrelated verification on a welcome screen with no
772
+ // explanation — see this method's own docstring above.
773
+ this.showErrorStep("This resume link has expired or is no longer valid.");
774
+ return null;
775
+ }
776
+ // Anything else (network error, timeout, an SDKError with a
777
+ // different/absent code) — never block the flow on this lookup.
778
+ // create/'s own resume-match still runs correctly once the customer
779
+ // gets there, so falling through to a generic welcome screen is safe.
780
+ return "welcome";
781
+ }
782
+ }
667
783
  // Defers the expiry warning while the user is on a camera-active step
668
784
  // (document_capture/liveness) — showing it there would blow away a live
669
785
  // video element and in-progress MediaRecorder mid-scan.
@@ -2268,7 +2384,14 @@ class SmartComplyFlow {
2268
2384
  // Classify the error into a user-friendly category
2269
2385
  const isCameraErr = /camera|permission|notallowed|notfound/i.test(message);
2270
2386
  const isNetworkErr = /network|timeout|connection|fetch/i.test(message);
2271
- const isAuthErr = /session.*expired|token.*expired|authentication/i.test(message);
2387
+ // Checked before the generic isAuthErr below — a resume/resubmit link
2388
+ // (RESUME_TARGET_UNAVAILABLE / NOT_A_RESUME_TOKEN from the backend, see
2389
+ // _resolveResumeStep) also matches "token...expired"/"link" wording, but
2390
+ // the corrective action is different from a plain session timeout: the
2391
+ // customer can't just "start again" themselves, they need a fresh link
2392
+ // from whoever sent them this one.
2393
+ const isResumeLinkErr = isResumeLinkErrorMessage(message);
2394
+ const isAuthErr = !isResumeLinkErr && /session.*expired|token.*expired|authentication/i.test(message);
2272
2395
  const isDocQuality = /blurry|blur|quality|glare|dark|bright|lighting/i.test(message);
2273
2396
  const isExpiredDoc = /document.*expired|expired.*document/i.test(message);
2274
2397
  const isFaceMatch = /face.*match|selfie.*match|does not match/i.test(message);
@@ -2278,36 +2401,40 @@ class SmartComplyFlow {
2278
2401
  const isBillingErr = /wallet|balance|insufficient.*fund|payment.*required/i.test(message);
2279
2402
  const errorIconName = isCameraErr ? "camera"
2280
2403
  : isNetworkErr ? "network"
2281
- : isAuthErr ? "clock"
2282
- : isDocQuality ? "search"
2283
- : isExpiredDoc ? "calendar"
2284
- : isFaceMatch ? "face"
2285
- : isBillingErr ? "warning"
2286
- : "close";
2404
+ : isResumeLinkErr ? "clock"
2405
+ : isAuthErr ? "clock"
2406
+ : isDocQuality ? "search"
2407
+ : isExpiredDoc ? "calendar"
2408
+ : isFaceMatch ? "face"
2409
+ : isBillingErr ? "warning"
2410
+ : "close";
2287
2411
  const errorTitle = isCameraErr ? "Camera Access Required"
2288
2412
  : isNetworkErr ? "Connection Problem"
2289
- : isAuthErr ? "Session Expired"
2290
- : isDocQuality ? "Document Photo Unclear"
2291
- : isExpiredDoc ? "Document Expired"
2292
- : isFaceMatch ? "Face Match Failed"
2293
- : isBillingErr ? "Verification Unavailable"
2294
- : "Verification Unsuccessful";
2413
+ : isResumeLinkErr ? "Link No Longer Valid"
2414
+ : isAuthErr ? "Session Expired"
2415
+ : isDocQuality ? "Document Photo Unclear"
2416
+ : isExpiredDoc ? "Document Expired"
2417
+ : isFaceMatch ? "Face Match Failed"
2418
+ : isBillingErr ? "Verification Unavailable"
2419
+ : "Verification Unsuccessful";
2295
2420
  // Map to user-facing guidance — never show raw internal message
2296
2421
  const userMessage = isCameraErr
2297
2422
  ? "Please allow camera access in your browser settings and try again."
2298
2423
  : isNetworkErr
2299
2424
  ? "Check your internet connection and try again."
2300
- : isAuthErr
2301
- ? "Your session has expired. Please start again."
2302
- : isDocQuality
2303
- ? _sanitizeUserMessage(message) || "Please retake your document photo in good lighting with no glare."
2304
- : isExpiredDoc
2305
- ? "The document you submitted has expired. Please use a valid, current ID."
2306
- : isFaceMatch
2307
- ? "Your selfie did not match the photo on your ID. Please ensure you are using your own valid document and face the camera directly."
2308
- : isBillingErr
2309
- ? "Verification is temporarily unavailable. Please contact support."
2310
- : _sanitizeUserMessage(message) || "We were unable to complete your verification. Please try again.";
2425
+ : isResumeLinkErr
2426
+ ? "This link has expired or has already been used. Please contact us to request a new one."
2427
+ : isAuthErr
2428
+ ? "Your session has expired. Please start again."
2429
+ : isDocQuality
2430
+ ? _sanitizeUserMessage(message) || "Please retake your document photo in good lighting with no glare."
2431
+ : isExpiredDoc
2432
+ ? "The document you submitted has expired. Please use a valid, current ID."
2433
+ : isFaceMatch
2434
+ ? "Your selfie did not match the photo on your ID. Please ensure you are using your own valid document and face the camera directly."
2435
+ : isBillingErr
2436
+ ? "Verification is temporarily unavailable. Please contact support."
2437
+ : _sanitizeUserMessage(message) || "We were unable to complete your verification. Please try again.";
2311
2438
  const iconWrap = document.createElement("div");
2312
2439
  iconWrap.style.cssText = `
2313
2440
  width:72px;height:72px;border-radius:50%;