@checktiv/sdk-web 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +81 -0
  2. package/dist/agents/AGENTS.md +2 -1
  3. package/dist/agents/manifest.json +1 -1
  4. package/dist/{api-gE16d66n.d.ts → api-DWWQGjxL.d.ts} +22 -3
  5. package/dist/capture-ui.css +1 -1
  6. package/dist/capture-ui.d.ts +5 -4
  7. package/dist/capture-ui.js +3 -3
  8. package/dist/capture.d.ts +3 -3
  9. package/dist/capture.js +2 -2
  10. package/dist/challenge.js +2 -4
  11. package/dist/chunk-7F7ZMYB7.js +7 -0
  12. package/dist/{chunk-ZXE45FN5.js → chunk-CGSNIVQF.js} +2 -2
  13. package/dist/chunk-D23CFGJB.js +13 -0
  14. package/dist/chunk-EYSE7JJ4.js +5 -0
  15. package/dist/chunk-JRJRXR7Q.js +7 -0
  16. package/dist/{chunk-ACQKQLL2.js → chunk-KK66RKPI.js} +2 -2
  17. package/dist/{chunk-6U53T32A.js → chunk-NHNGQ5BB.js} +3 -4
  18. package/dist/chunk-OC5N6W7T.js +3 -0
  19. package/dist/chunk-S2OOEDJS.js +3 -0
  20. package/dist/chunk-TORKYG3K.js +6 -0
  21. package/dist/chunk-YPYFPHOH.js +9 -0
  22. package/dist/collect-user-info.d.ts +64 -0
  23. package/dist/collect-user-info.js +9 -0
  24. package/dist/{controller-CFL3mA5e.d.ts → controller-e63nkNGE.d.ts} +1 -1
  25. package/dist/{copy-Dfmk11S_.d.ts → copy-CC_mrlVV.d.ts} +1 -1
  26. package/dist/custom-form.d.ts +3 -3
  27. package/dist/custom-form.js +5 -3
  28. package/dist/fraud.d.ts +3 -3
  29. package/dist/fraud.js +5 -3
  30. package/dist/idv/cross-device.d.ts +6 -4
  31. package/dist/idv/cross-device.js +5 -5
  32. package/dist/idv.css +1 -1
  33. package/dist/idv.d.ts +3 -3
  34. package/dist/idv.js +9 -7
  35. package/dist/{index-CLPKNcV9.d.ts → index-B9Gc_xWl.d.ts} +6 -4
  36. package/dist/index.d.ts +7 -6
  37. package/dist/index.js +6 -3
  38. package/dist/{machine-CuZalPFX.d.ts → machine-DZPN-A44.d.ts} +5 -1
  39. package/dist/react.d.ts +5 -4
  40. package/dist/react.js +9 -5
  41. package/dist/workspace.d.ts +3 -3
  42. package/dist/workspace.js +1 -1
  43. package/package.json +7 -3
  44. package/dist/chunk-3CSUYGFY.js +0 -7
  45. package/dist/chunk-5AQCMTZV.js +0 -6
  46. package/dist/chunk-7NIKMJFJ.js +0 -6
  47. package/dist/chunk-PZFDDSXB.js +0 -10
package/README.md CHANGED
@@ -184,6 +184,7 @@ actionable error telling you which subpath to add, instead of failing silently.
184
184
  | `./fraud` | Consent-gated fraud-signal collection. Import for its self-registration side effect. |
185
185
  | `./custom-form` | Custom intake-form module (server-authored field definitions). Import for its self-registration side effect. |
186
186
  | `./custom-form/style.css` | Stylesheet for the custom-form module. `<link>` or `import` this into the host page. |
187
+ | `./collect-user-info` | `collectUserInfo({ session })` - satisfy a `collect_user_info` step from your own form. No UI, no registration import. Zero-lifecycle. |
187
188
  | `./capture-ui/style.css` | Stylesheet for the managed IDV capture surface. Import it (the managed module renders through it) or the capture screen is unstyled. |
188
189
  | `./react` | React wrappers: `ChecktivJourney` (zero-lifecycle `mount`), plus `ChecktivProvider` / `useChecktiv()` / `ChecktivIdv` (the `init()` path). |
189
190
  | `./capture` | Advanced: headless host-side capture controller (`createCaptureController`). No default UI. |
@@ -237,6 +238,86 @@ The module always renders a continue control (even for a content-only screen) so
237
238
  journey can advance, and emits `checktiv.custom_form.submitted` when the applicant
238
239
  completes it. Pass `customFormConfig` and `customFormCopy` alongside `target`.
239
240
 
241
+ ## Collect user info (`./collect-user-info`)
242
+
243
+ Some workflows begin with a `collect_user_info` step that gathers the applicant's
244
+ identity details (a legal name, and optionally email, phone, date of birth, or
245
+ address) before identity verification. The embedded capture modules do not render
246
+ this step. Collect these fields in your own form and satisfy the step with
247
+ `collectUserInfo`, then mount the journey so it opens on the verification step.
248
+
249
+ `collectUserInfo` is a small standalone function, not a mounted module: no UI, no
250
+ container, no stylesheet, no registration import. It takes the same zero-lifecycle
251
+ `fetchToken` as `mount()` (return your durable client token, the SAME one you pass
252
+ to `Checktiv.mount()`); the SDK exchanges it for a short-lived working token
253
+ internally.
254
+
255
+ ```js
256
+ import { collectUserInfo } from '@checktiv/sdk-web/collect-user-info';
257
+
258
+ const collector = collectUserInfo({
259
+ session: {
260
+ publishableKey: 'ah_pk_us_test_...',
261
+ fetchToken: () =>
262
+ fetch('/kyc/session', { method: 'POST' })
263
+ .then((res) => res.json())
264
+ .then((data) => data.clientToken),
265
+ },
266
+ });
267
+ ```
268
+
269
+ **Render your form from the template with `describe()`.** `legalName` is always
270
+ required; every other field is optional and gated by the operator's template.
271
+ `describe()` tells you which optional fields the template collects, so you render
272
+ required-ness template-driven instead of guessing:
273
+
274
+ ```js
275
+ const config = await collector.describe();
276
+ if (config.ok) {
277
+ // config.fields is a subset of 'email' | 'phone' | 'dob' | 'address'.
278
+ // config.captureStructuredName is true when a structured first/middle/last
279
+ // name is wanted (otherwise collect a single legal name).
280
+ renderForm(config.fields, config.captureStructuredName);
281
+ }
282
+ ```
283
+
284
+ **Submit before you mount the journey.** `submit()` never throws for a server or
285
+ network error; it resolves a discriminated result you branch on. Satisfy the collect
286
+ step first, then mount, so the journey opens on the verification step rather than a
287
+ step the embedded modules cannot render.
288
+
289
+ ```js
290
+ const result = await collector.submit({
291
+ legalName: 'Ada Lovelace',
292
+ name: { first: 'Ada', last: 'Lovelace' }, // when captureStructuredName is true
293
+ email: 'ada@example.com',
294
+ // phone, dateOfBirth ('YYYY-MM-DD'), and address are also optional.
295
+ });
296
+
297
+ if (result.ok) {
298
+ // The step is satisfied. Mount the journey now.
299
+ } else {
300
+ // result.code is a stable, machine-readable reason ('not_collect_step',
301
+ // 'validation_failed', 'token_expired', 'origin_not_allowed', 'rate_limited',
302
+ // 'service_unavailable', 'session_expired', 'wrong_token_type', 'network_error');
303
+ // result.message is an actionable, user-visible string.
304
+ showError(result.message);
305
+ }
306
+ ```
307
+
308
+ In React, the `./react` subpath exposes the same collector through the
309
+ `useCollectUserInfo` hook:
310
+
311
+ ```jsx
312
+ import { useCollectUserInfo } from '@checktiv/sdk-web/react';
313
+
314
+ const collector = useCollectUserInfo({ publishableKey: 'ah_pk_us_test_...', fetchToken });
315
+ // collector.describe() and collector.submit(...) work exactly as above.
316
+ ```
317
+
318
+ See the developer docs for the full contract and the meaning of each `submit()`
319
+ error code.
320
+
240
321
  ## React integration (`./react`)
241
322
 
242
323
  `react` / `react-dom` are supplied by your app as optional peers, so there is a single
@@ -35,10 +35,11 @@ Who mints the one-time handoff link depends on the token plane:
35
35
 
36
36
  For a FULLY CUSTOM IDV renderer built on `@checktiv/sdk-web/capture` (NOT the managed module), the STANDALONE exports drive the overlay yourself and you always supply the mint hook: `@checktiv/sdk-web/idv/cross-device` (`openCrossDeviceOverlay(opts)` opens the overlay, `preloadCrossDeviceChunk()` warms the lazy chunk) and `@checktiv/sdk-web/cross-device` (`mountCrossDevice(target, props)` renders the bare panel on a screen you fully control). `openCrossDeviceOverlay` takes `{ target, onOpenCrossDevice, copy, isMobile, emit, onClose }` plus an optional `poll` config, and returns a handle with `setCompleting()` (keep the QR mounted with a waiting label while your page reloads) and `destroy()` (idempotent). Set `isMobile: true` to suppress the QR on a phone (a same-device scan is circular). The SDK NEVER writes `window.location`; navigation is always the host's, off the emitted event.
37
37
 
38
- Three token-free overlay events (NONE carries the url / OTL / short-code / expiry hint):
38
+ Four token-free overlay events (NONE carries the url / OTL / short-code / expiry hint):
39
39
  • `checktiv.idv.cross_device_opened`: the mint returned `ok` and the overlay is shown.
40
40
  • `checktiv.idv.cross_device_unavailable`: the mint returned `unavailable` or URL validation failed.
41
41
  • `checktiv.idv.cross_device_capped`: the completion poll hit its total time cap without the phone finishing. NOT an error and NOT a verdict: the QR panel stays mounted so the applicant can still finish on their phone.
42
+ • `checktiv.idv.cross_device_closed`: the applicant dismissed the overlay (back on desktop, try-again on mobile). Fires only on an applicant-initiated dismissal, never on a `destroy()` you call for an unrelated reason such as tearing the overlay down after the phone already completed.
42
43
 
43
44
  ## Runnable recipes
44
45
 
@@ -74,7 +74,7 @@
74
74
  {
75
75
  "id": "cross-device-handoff-hook",
76
76
  "title": "Cross-device QR handoff is built into the managed IDV module",
77
- "body": "Cross-device handoff (a desktop applicant finishes on their phone via a QR + copy-link overlay) is OWNED BY THE MANAGED IDV MODULE. Render it with `client.mount('idv', { crossDeviceCopy, onEvent })` and the returned handle exposes `openCrossDevice()`: calling it opens the overlay OVER the still-live capture frame, runs the completion poll, and emits `checktiv.idv.submitted` when the phone finishes so your host reloads. You MUST `import '@checktiv/sdk-web/idv/cross-device';` to enable the overlay (the CDN script-tag bundle already includes it); without that import `openCrossDevice()` is a graceful, actionable no-op, as it also is before the applicant verification resolves or when no `crossDeviceCopy` was supplied. `IdvMountOptions` carries `crossDeviceCopy` (host-injected strings; the `unavailableMessage` key is required so no arm renders blank) and the OPTIONAL `onOpenCrossDevice` mint override; `IdvHandle` exposes `openCrossDevice?()`, so call it as `handle.openCrossDevice?.()`. The zero-lifecycle `Checktiv.mount(...)` and its React wrapper `<ChecktivJourney>` ALSO expose `openCrossDevice()` on their handle (reach the React handle via a `ref`), carrying the same `crossDeviceCopy` / optional `onOpenCrossDevice` options; on that path the SDK self-mints the handoff on the working-token plane by default (see below), and the CDN script-tag bundle registers the opener too. The trigger is a DESKTOP affordance: `openCrossDevice()` is a graceful warn-no-op on a coarse-pointer (touch) device, because immersive phone capture and the desktop cross-device overlay are mutually exclusive per device, so gate your trigger to desktop.\n\nWho mints the one-time handoff link depends on the token plane:\n • Working-token plane: the module mints the link ITSELF (it calls its own handoff endpoint `POST /sdk/v1/sessions/me/handoff`, authenticated by the applicant's short-lived working token, and caps the per-overlay \"refresh link\" re-mints). Supply `onOpenCrossDevice` ONLY to point the mint at your own backend instead.\n • Browser-token (`bt_*`) plane: the SDK CANNOT self-mint (the handoff route rejects a `bt_*` bearer), so you MUST supply `onOpenCrossDevice` backed by a server-held credential.\n\n`onOpenCrossDevice: CrossDeviceHandoffHook` is `() => Promise<{ kind: 'ok'; url: string } | { kind: 'unavailable' }>`. Return `{ kind: 'ok', url }` with the journey URL (which MUST be `https:`: the SDK collapses `javascript:`, `http:`, and `data:` schemes to `'unavailable'`) or `{ kind: 'unavailable' }` when the mint fails. The hook is re-callable for the overlay's \"refresh link\" affordance; the SDK caps re-mints per overlay.\n\nFor a FULLY CUSTOM IDV renderer built on `@checktiv/sdk-web/capture` (NOT the managed module), the STANDALONE exports drive the overlay yourself and you always supply the mint hook: `@checktiv/sdk-web/idv/cross-device` (`openCrossDeviceOverlay(opts)` opens the overlay, `preloadCrossDeviceChunk()` warms the lazy chunk) and `@checktiv/sdk-web/cross-device` (`mountCrossDevice(target, props)` renders the bare panel on a screen you fully control). `openCrossDeviceOverlay` takes `{ target, onOpenCrossDevice, copy, isMobile, emit, onClose }` plus an optional `poll` config, and returns a handle with `setCompleting()` (keep the QR mounted with a waiting label while your page reloads) and `destroy()` (idempotent). Set `isMobile: true` to suppress the QR on a phone (a same-device scan is circular). The SDK NEVER writes `window.location`; navigation is always the host's, off the emitted event.\n\nThree token-free overlay events (NONE carries the url / OTL / short-code / expiry hint):\n • `checktiv.idv.cross_device_opened`: the mint returned `ok` and the overlay is shown.\n • `checktiv.idv.cross_device_unavailable`: the mint returned `unavailable` or URL validation failed.\n • `checktiv.idv.cross_device_capped`: the completion poll hit its total time cap without the phone finishing. NOT an error and NOT a verdict: the QR panel stays mounted so the applicant can still finish on their phone."
77
+ "body": "Cross-device handoff (a desktop applicant finishes on their phone via a QR + copy-link overlay) is OWNED BY THE MANAGED IDV MODULE. Render it with `client.mount('idv', { crossDeviceCopy, onEvent })` and the returned handle exposes `openCrossDevice()`: calling it opens the overlay OVER the still-live capture frame, runs the completion poll, and emits `checktiv.idv.submitted` when the phone finishes so your host reloads. You MUST `import '@checktiv/sdk-web/idv/cross-device';` to enable the overlay (the CDN script-tag bundle already includes it); without that import `openCrossDevice()` is a graceful, actionable no-op, as it also is before the applicant verification resolves or when no `crossDeviceCopy` was supplied. `IdvMountOptions` carries `crossDeviceCopy` (host-injected strings; the `unavailableMessage` key is required so no arm renders blank) and the OPTIONAL `onOpenCrossDevice` mint override; `IdvHandle` exposes `openCrossDevice?()`, so call it as `handle.openCrossDevice?.()`. The zero-lifecycle `Checktiv.mount(...)` and its React wrapper `<ChecktivJourney>` ALSO expose `openCrossDevice()` on their handle (reach the React handle via a `ref`), carrying the same `crossDeviceCopy` / optional `onOpenCrossDevice` options; on that path the SDK self-mints the handoff on the working-token plane by default (see below), and the CDN script-tag bundle registers the opener too. The trigger is a DESKTOP affordance: `openCrossDevice()` is a graceful warn-no-op on a coarse-pointer (touch) device, because immersive phone capture and the desktop cross-device overlay are mutually exclusive per device, so gate your trigger to desktop.\n\nWho mints the one-time handoff link depends on the token plane:\n • Working-token plane: the module mints the link ITSELF (it calls its own handoff endpoint `POST /sdk/v1/sessions/me/handoff`, authenticated by the applicant's short-lived working token, and caps the per-overlay \"refresh link\" re-mints). Supply `onOpenCrossDevice` ONLY to point the mint at your own backend instead.\n • Browser-token (`bt_*`) plane: the SDK CANNOT self-mint (the handoff route rejects a `bt_*` bearer), so you MUST supply `onOpenCrossDevice` backed by a server-held credential.\n\n`onOpenCrossDevice: CrossDeviceHandoffHook` is `() => Promise<{ kind: 'ok'; url: string } | { kind: 'unavailable' }>`. Return `{ kind: 'ok', url }` with the journey URL (which MUST be `https:`: the SDK collapses `javascript:`, `http:`, and `data:` schemes to `'unavailable'`) or `{ kind: 'unavailable' }` when the mint fails. The hook is re-callable for the overlay's \"refresh link\" affordance; the SDK caps re-mints per overlay.\n\nFor a FULLY CUSTOM IDV renderer built on `@checktiv/sdk-web/capture` (NOT the managed module), the STANDALONE exports drive the overlay yourself and you always supply the mint hook: `@checktiv/sdk-web/idv/cross-device` (`openCrossDeviceOverlay(opts)` opens the overlay, `preloadCrossDeviceChunk()` warms the lazy chunk) and `@checktiv/sdk-web/cross-device` (`mountCrossDevice(target, props)` renders the bare panel on a screen you fully control). `openCrossDeviceOverlay` takes `{ target, onOpenCrossDevice, copy, isMobile, emit, onClose }` plus an optional `poll` config, and returns a handle with `setCompleting()` (keep the QR mounted with a waiting label while your page reloads) and `destroy()` (idempotent). Set `isMobile: true` to suppress the QR on a phone (a same-device scan is circular). The SDK NEVER writes `window.location`; navigation is always the host's, off the emitted event.\n\nFour token-free overlay events (NONE carries the url / OTL / short-code / expiry hint):\n • `checktiv.idv.cross_device_opened`: the mint returned `ok` and the overlay is shown.\n • `checktiv.idv.cross_device_unavailable`: the mint returned `unavailable` or URL validation failed.\n • `checktiv.idv.cross_device_capped`: the completion poll hit its total time cap without the phone finishing. NOT an error and NOT a verdict: the QR panel stays mounted so the applicant can still finish on their phone.\n • `checktiv.idv.cross_device_closed`: the applicant dismissed the overlay (back on desktop, try-again on mobile). Fires only on an applicant-initiated dismissal, never on a `destroy()` you call for an unrelated reason such as tearing the overlay down after the phone already completed."
78
78
  }
79
79
  ],
80
80
  "recipes": [
@@ -1,5 +1,5 @@
1
- import { C as CaptureLayout, a as CaptureBehaviorMessage, S as SelfiePromptMap, h as SelfieChromeCopy, b as CoachingKind } from './machine-CuZalPFX.js';
2
- import { M as MountCopy } from './copy-Dfmk11S_.js';
1
+ import { C as CaptureLayout, a as CaptureBehaviorMessage, h as SelfiePromptMap, j as SelfieChromeCopy, b as CoachingKind } from './machine-DZPN-A44.js';
2
+ import { M as MountCopy } from './copy-CC_mrlVV.js';
3
3
  import { C as CrossDeviceCopy } from './copy-DCeQ4JKx.js';
4
4
 
5
5
  declare const SystemModes: readonly ["live", "test"];
@@ -36,6 +36,7 @@ interface IdvMountOptions {
36
36
  onEvent?: (e: ChecktivIdvEvent) => void;
37
37
  copy?: MountCopy;
38
38
  layout?: CaptureLayout;
39
+ maxWidth?: string;
39
40
  onBeforeSubmit?: () => Promise<void>;
40
41
  onBehaviorSegment?: (segment: Pick<CaptureBehaviorMessage, 'steps' | 'traits'>) => void;
41
42
  fetchImpl?: typeof fetch;
@@ -141,6 +142,7 @@ interface MountProvisionedOptions {
141
142
  onConsent?: () => boolean | Promise<boolean>;
142
143
  copy?: MountCopy;
143
144
  layout?: CaptureLayout;
145
+ maxWidth?: string;
144
146
  onBeforeSubmit?: () => Promise<void>;
145
147
  onBehaviorSegment?: (segment: Pick<CaptureBehaviorMessage, 'steps' | 'traits'>) => void;
146
148
  fetchImpl?: typeof fetch;
@@ -230,6 +232,7 @@ type ChecktivIdvEvent = {
230
232
  sessionId: string;
231
233
  } | {
232
234
  type: 'checktiv.idv.processing';
235
+ reason?: 'signal_pending' | 'no_renderable_step';
233
236
  } | {
234
237
  type: 'checktiv.idv.capture_superseded';
235
238
  } | {
@@ -241,6 +244,8 @@ type ChecktivIdvEvent = {
241
244
  type: 'checktiv.idv.cross_device_unavailable';
242
245
  } | {
243
246
  type: 'checktiv.idv.cross_device_capped';
247
+ } | {
248
+ type: 'checktiv.idv.cross_device_closed';
244
249
  };
245
250
  type ChecktivEvent = ChecktivIdvEvent | ChecktivFraudEvent | {
246
251
  type: `checktiv.${string}`;
@@ -274,6 +279,7 @@ type MountOptions = MountScope & {
274
279
  readonly resumeKey?: string;
275
280
  readonly shortCode?: string;
276
281
  readonly layout?: CaptureLayout;
282
+ readonly maxWidth?: string;
277
283
  readonly theme?: {
278
284
  readonly primaryColor?: string;
279
285
  };
@@ -281,13 +287,26 @@ type MountOptions = MountScope & {
281
287
  readonly crossDeviceCopy?: CrossDeviceCopy;
282
288
  readonly onOpenCrossDevice?: CrossDeviceHandoffHook;
283
289
  };
290
+ interface SessionsCreateApplicantAddress {
291
+ readonly line1: string;
292
+ readonly line2?: string;
293
+ readonly city: string;
294
+ readonly region?: string;
295
+ readonly postalCode?: string;
296
+ readonly country: string;
297
+ readonly placeId?: string;
298
+ readonly formatted?: string;
299
+ }
284
300
  interface SessionsCreateApplicant {
285
301
  readonly externalId?: string;
286
302
  readonly email?: string;
287
303
  readonly phone?: string;
288
304
  readonly firstName?: string;
305
+ readonly middleName?: string;
289
306
  readonly lastName?: string;
307
+ readonly legalName?: string;
290
308
  readonly dateOfBirth?: string;
309
+ readonly address?: SessionsCreateApplicantAddress;
291
310
  readonly referenceName?: string;
292
311
  }
293
312
  interface SessionsCreateInput {
@@ -315,4 +334,4 @@ declare class InvalidPublishableKeyError extends Error {
315
334
  }
316
335
  declare function parsePublishableKey(key: string): ParsedPublishableKey;
317
336
 
318
- export { type SubstrateContext as A, REMINT_READY_TIMEOUT_MS as B, type ChecktivInitOptions as C, createIdv as D, type ChecktivCustomFormEvent as E, type FraudHandle as F, type GetSessionToken as G, type CustomFormCopy as H, type InitOptions as I, type CustomFormFieldCopy as J, type CustomFormHandle as K, type CustomFormMountOptions as L, type MountOptions as M, createCustomForm as N, createFraud as O, type ProvisionedHandle as P, type ResolvedIdvConfig as R, type SdkMode as S, type TokenManager as T, type ChecktivClient as a, type ChecktivSessions as b, type ChecktivError as c, type ChecktivErrorCode as d, type ChecktivEvent as e, type ChecktivFraudEvent as f, type ChecktivIdvEvent as g, type CrossDeviceHandoffHook as h, type FraudMountOptions as i, type GetSessionTokenContext as j, type IdvCoachingHint as k, type IdvHandle as l, type IdvMountOptions as m, InvalidPublishableKeyError as n, type MountCompleteResult as o, type MountProvisionedOptions as p, type MountScope as q, type ParsedPublishableKey as r, type SdkRegion as s, type SessionsCreateApplicant as t, type SessionsCreateInput as u, type SessionsCreateOptions as v, type SessionsCreateResult as w, type SyntheticIdvScript as x, parsePublishableKey as y, type ChecktivInitScope as z };
337
+ export { type ChecktivInitScope as A, type SubstrateContext as B, type ChecktivInitOptions as C, REMINT_READY_TIMEOUT_MS as D, createIdv as E, type FraudHandle as F, type GetSessionToken as G, type ChecktivCustomFormEvent as H, type InitOptions as I, type CustomFormCopy as J, type CustomFormFieldCopy as K, type CustomFormHandle as L, type MountOptions as M, type CustomFormMountOptions as N, createCustomForm as O, type ProvisionedHandle as P, createFraud as Q, type ResolvedIdvConfig as R, type SdkMode as S, type TokenManager as T, type ChecktivClient as a, type ChecktivSessions as b, type ChecktivError as c, type ChecktivErrorCode as d, type ChecktivEvent as e, type ChecktivFraudEvent as f, type ChecktivIdvEvent as g, type CrossDeviceHandoffHook as h, type FraudMountOptions as i, type GetSessionTokenContext as j, type IdvCoachingHint as k, type IdvHandle as l, type IdvMountOptions as m, InvalidPublishableKeyError as n, type MountCompleteResult as o, type MountProvisionedOptions as p, type MountScope as q, type ParsedPublishableKey as r, type SdkRegion as s, type SessionsCreateApplicant as t, type SessionsCreateApplicantAddress as u, type SessionsCreateInput as v, type SessionsCreateOptions as w, type SessionsCreateResult as x, type SyntheticIdvScript as y, parsePublishableKey as z };
@@ -1 +1 @@
1
- .idv-capture-frame{display:block;width:100%;max-width:28rem;aspect-ratio:3 / 4;margin:0 auto;border:0;border-radius:0.5rem;background:transparent}.idv-capture-frame--biometric{aspect-ratio:auto;height:min(70dvh,var(--idv-capture-max-height, 520px))}@media(orientation:landscape)and (pointer:coarse){.idv-capture-frame,.idv-capture-frame--biometric{aspect-ratio:auto;height:min(55dvh,var(--idv-capture-landscape-max-height, 380px));width:auto}}@media(pointer:fine)and (min-width:768px){.idv-capture-frame,.idv-capture-frame--biometric{max-width:34rem}}@media(pointer:fine)and (orientation:landscape){.idv-capture-frame{max-height:min(70dvh,560px)}.idv-capture-frame--biometric{height:min(70dvh,560px)}}.idv-capture-active{position:relative}.idv-capture-skeleton{position:absolute;top:0;left:50%;transform:translateX(-50%);z-index:1;width:100%;max-width:28rem;height:min(70dvh,var(--idv-capture-max-height, 520px));border-radius:0.5rem;overflow:hidden;background:#e5e7eb}.idv-capture-skeleton[data-color-mode=dark]{background:#1f2937}.idv-capture-skeleton::before{content:"";position:absolute;inset:0;background:linear-gradient(100deg,transparent 30%,rgba(255,255,255,0.22) 50%,transparent 70%);background-size:200% 100%;animation:idv-capture-skeleton-sweep 1.4s ease-in-out infinite}@keyframes idv-capture-skeleton-sweep{from{background-position:200% 0}to{background-position:-200% 0}}@media(prefers-reduced-motion:reduce){.idv-capture-skeleton::before{animation:none}}.idv-capture-skeleton--document{aspect-ratio:3 / 4;height:auto}.idv-capture-skeleton--standalone{position:static;transform:none;margin:0 auto}@media(orientation:landscape)and (pointer:coarse){.idv-capture-skeleton{height:min(55dvh,var(--idv-capture-landscape-max-height, 380px))}}@media(pointer:fine)and (min-width:768px){.idv-capture-skeleton{max-width:34rem;height:min(70dvh,560px)}}:root{--idv-capture-max-height: 520px;--idv-capture-landscape-max-height: 380px}.idv-capture-root{display:contents}.idv-capture-status{margin:0.75rem 0 0;text-align:center;color:#6b7280;font-size:0.875rem;line-height:1.4}.idv-capture-error{margin:0.75rem auto 1.25rem;max-width:22rem;text-align:center}.idv-capture-error p{margin:0 0 0.75rem;color:#374151;font-size:0.9375rem;line-height:1.5}.idv-capture-retry{display:inline-block;padding:0.5rem 1rem;font:inherit;font-size:0.875rem;font-weight:500;color:#374151;background:transparent;border:1px solid #d1d5db;border-radius:0.375rem;cursor:pointer}.idv-capture-retry:hover{background:#f3f4f6;border-color:#9ca3af}.idv-capture-retry:focus-visible{outline:2px solid #6b7280;outline-offset:2px}.idv-capture-cv-reject{text-align:center;color:#6b7280;font-size:0.8125rem;line-height:1.4;padding:0.5rem 0.75rem;background:#f9fafb;border:1px solid #e5e7eb;border-radius:0.375rem}[data-color-mode=dark] .idv-capture-status{color:#9ca3af}[data-color-mode=dark] .idv-capture-error p{color:#d1d5db}[data-color-mode=dark] .idv-capture-retry{color:#e5e7eb;background:transparent;border-color:#4b5563}[data-color-mode=dark] .idv-capture-retry:hover{background:#1f2937;border-color:#6b7280}[data-color-mode=dark] .idv-capture-cv-reject{color:#d1d5db;background:#1f2937;border-color:#374151}@media(pointer:coarse)and (max-width:640px),(pointer:coarse)and (max-height:640px){.idv-capture-immersive{position:fixed;inset:0;z-index:2147483000;display:flex;flex-direction:column;height:100dvh;overflow:hidden;box-sizing:border-box;background:#111827}.idv-capture-immersive .idv-capture-frame,.idv-capture-immersive .idv-capture-frame--biometric{flex:1 1 auto;min-height:0;width:100%;height:auto;max-width:none;aspect-ratio:auto;border-radius:0}.idv-capture-immersive .idv-capture-cv-reject,.idv-capture-immersive .idv-capture-status{flex:0 0 auto}.idv-capture-immersive .idv-capture-cv-reject{background:transparent;border:0;border-radius:0;color:#f3f4f6;padding:0.5rem 1rem;font-size:0.8125rem}.idv-capture-immersive .idv-capture-status{margin:0;text-align:center;color:#f3f4f6;line-height:1.4;font-size:0.875rem;padding:0.75rem 1rem calc(0.75rem + env(safe-area-inset-bottom))}.idv-capture-immersive .idv-capture-skeleton{position:absolute;inset:0;transform:none;width:100%;max-width:none;height:auto;background:#1f2937}.idv-capture-immersive .idv-capture-sentinel{position:absolute;width:0;height:0;overflow:hidden}}
1
+ .idv-capture-frame{display:block;width:100%;max-width:var(--idv-capture-max-width, 28rem);aspect-ratio:3 / 4;margin:0 auto;border:0;border-radius:0.5rem;background:transparent}.idv-capture-frame--biometric{aspect-ratio:auto;height:min(70dvh,var(--idv-capture-max-height, 520px))}@media(orientation:landscape)and (pointer:coarse){.idv-capture-frame,.idv-capture-frame--biometric{aspect-ratio:auto;height:min(55dvh,var(--idv-capture-landscape-max-height, 380px));width:auto}}@media(pointer:fine)and (min-width:768px){.idv-capture-frame,.idv-capture-frame--biometric{max-width:var(--idv-capture-max-width, 34rem)}}@media(pointer:fine)and (orientation:landscape){.idv-capture-frame{max-height:min(70dvh,560px)}.idv-capture-frame--biometric{height:min(70dvh,560px)}}.idv-capture-active{position:relative}.idv-capture-skeleton{position:absolute;top:0;left:50%;transform:translateX(-50%);z-index:1;width:100%;max-width:var(--idv-capture-max-width, 28rem);height:min(70dvh,var(--idv-capture-max-height, 520px));border-radius:0.5rem;overflow:hidden;background:#e5e7eb}.idv-capture-skeleton[data-color-mode=dark]{background:#1f2937}.idv-capture-skeleton::before{content:"";position:absolute;inset:0;background:linear-gradient(100deg,transparent 30%,rgba(255,255,255,0.22) 50%,transparent 70%);background-size:200% 100%;animation:idv-capture-skeleton-sweep 1.4s ease-in-out infinite}@keyframes idv-capture-skeleton-sweep{from{background-position:200% 0}to{background-position:-200% 0}}@media(prefers-reduced-motion:reduce){.idv-capture-skeleton::before{animation:none}}.idv-capture-skeleton--document{aspect-ratio:3 / 4;height:auto}.idv-capture-skeleton--standalone{position:static;transform:none;margin:0 auto}@media(orientation:landscape)and (pointer:coarse){.idv-capture-skeleton{height:min(55dvh,var(--idv-capture-landscape-max-height, 380px))}}@media(pointer:fine)and (min-width:768px){.idv-capture-skeleton{max-width:var(--idv-capture-max-width, 34rem);height:min(70dvh,560px)}}:root{--idv-capture-max-height: 520px;--idv-capture-landscape-max-height: 380px}.idv-capture-root{display:contents}.idv-capture-status{margin:0.75rem 0 0;text-align:center;color:#6b7280;font-size:0.875rem;line-height:1.4}.idv-capture-error{margin:0.75rem auto 1.25rem;max-width:22rem;text-align:center}.idv-capture-error p{margin:0 0 0.75rem;color:#374151;font-size:0.9375rem;line-height:1.5}.idv-capture-retry{display:inline-block;padding:0.5rem 1rem;font:inherit;font-size:0.875rem;font-weight:500;color:#374151;background:transparent;border:1px solid #d1d5db;border-radius:0.375rem;cursor:pointer}.idv-capture-retry:hover{background:#f3f4f6;border-color:#9ca3af}.idv-capture-retry:focus-visible{outline:2px solid #6b7280;outline-offset:2px}.idv-capture-cv-reject{text-align:center;color:#6b7280;font-size:0.8125rem;line-height:1.4;padding:0.5rem 0.75rem;background:#f9fafb;border:1px solid #e5e7eb;border-radius:0.375rem}[data-color-mode=dark] .idv-capture-status{color:#9ca3af}[data-color-mode=dark] .idv-capture-error p{color:#d1d5db}[data-color-mode=dark] .idv-capture-retry{color:#e5e7eb;background:transparent;border-color:#4b5563}[data-color-mode=dark] .idv-capture-retry:hover{background:#1f2937;border-color:#6b7280}[data-color-mode=dark] .idv-capture-cv-reject{color:#d1d5db;background:#1f2937;border-color:#374151}@media(pointer:coarse)and (max-width:640px),(pointer:coarse)and (max-height:640px){.idv-capture-immersive{position:fixed;inset:0;z-index:2147483000;display:flex;flex-direction:column;height:100dvh;overflow:hidden;box-sizing:border-box;background:#111827}.idv-capture-immersive .idv-capture-frame,.idv-capture-immersive .idv-capture-frame--biometric{flex:1 1 auto;min-height:0;width:100%;height:auto;max-width:none;aspect-ratio:auto;border-radius:0}.idv-capture-immersive .idv-capture-cv-reject,.idv-capture-immersive .idv-capture-status{flex:0 0 auto}.idv-capture-immersive .idv-capture-cv-reject{background:transparent;border:0;border-radius:0;color:#f3f4f6;padding:0.5rem 1rem;font-size:0.8125rem}.idv-capture-immersive .idv-capture-status{margin:0;text-align:center;color:#f3f4f6;line-height:1.4;font-size:0.875rem;padding:0.75rem 1rem calc(0.75rem + env(safe-area-inset-bottom))}.idv-capture-immersive .idv-capture-skeleton{position:absolute;inset:0;transform:none;width:100%;max-width:none;height:auto;background:#1f2937}.idv-capture-immersive .idv-capture-sentinel{position:absolute;width:0;height:0;overflow:hidden}}
@@ -1,11 +1,12 @@
1
- import { a as CaptureControllerDeps, b as CaptureEvent } from './controller-CFL3mA5e.js';
2
- import { C as CaptureLayout, f as CaptureState } from './machine-CuZalPFX.js';
3
- import { M as MountCopy } from './copy-Dfmk11S_.js';
4
- export { T as TerminalKind, f as fallbackCopy } from './copy-Dfmk11S_.js';
1
+ import { a as CaptureControllerDeps, b as CaptureEvent } from './controller-e63nkNGE.js';
2
+ import { C as CaptureLayout, f as CaptureState } from './machine-DZPN-A44.js';
3
+ import { M as MountCopy } from './copy-CC_mrlVV.js';
4
+ export { T as TerminalKind, f as fallbackCopy } from './copy-CC_mrlVV.js';
5
5
 
6
6
  interface MountCaptureOptions extends Omit<CaptureControllerDeps, 'getIframe'> {
7
7
  copy: MountCopy;
8
8
  layout?: CaptureLayout;
9
+ maxWidth?: string;
9
10
  onState?: (state: CaptureState) => void;
10
11
  onControllerEvent?: (event: CaptureEvent) => void;
11
12
  }
@@ -1,8 +1,8 @@
1
- export { fallbackCopy, mount } from './chunk-3CSUYGFY.js';
1
+ export { fallbackCopy, mount } from './chunk-JRJRXR7Q.js';
2
2
  import './chunk-HV2QKVJX.js';
3
3
  import './chunk-XOGHMNBX.js';
4
- import './chunk-5AQCMTZV.js';
5
- import './chunk-6U53T32A.js';
4
+ import './chunk-TORKYG3K.js';
5
+ import './chunk-NHNGQ5BB.js';
6
6
  import './chunk-IQKHRPJR.js';
7
7
  import './chunk-QFA3K5ZV.js';
8
8
  import './chunk-AIK7CDV6.js';
package/dist/capture.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { C as CaptureController, a as CaptureControllerDeps, b as CaptureEvent, c as CaptureEventType, S as SubmitResult, d as createCaptureController } from './controller-CFL3mA5e.js';
2
- import { b as CoachingKind } from './machine-CuZalPFX.js';
3
- export { c as CaptureAction, d as CaptureErrorKind, e as CapturePhase, f as CaptureState, i as isBiometricPhase, n as nextCapturePhaseAfterDocument, r as reducer } from './machine-CuZalPFX.js';
1
+ export { C as CaptureController, a as CaptureControllerDeps, b as CaptureEvent, c as CaptureEventType, S as SubmitResult, d as createCaptureController } from './controller-e63nkNGE.js';
2
+ import { b as CoachingKind } from './machine-DZPN-A44.js';
3
+ export { c as CaptureAction, d as CaptureErrorKind, e as CapturePhase, f as CaptureState, i as isBiometricPhase, n as nextCapturePhaseAfterDocument, r as reducer } from './machine-DZPN-A44.js';
4
4
 
5
5
  declare function coachingKindForState(state: string): CoachingKind;
6
6
 
package/dist/capture.js CHANGED
@@ -1,5 +1,5 @@
1
- export { coachingKindForState, createCaptureController, isBiometricPhase, nextCapturePhaseAfterDocument, reducer } from './chunk-5AQCMTZV.js';
2
- import './chunk-6U53T32A.js';
1
+ export { coachingKindForState, createCaptureController, isBiometricPhase, nextCapturePhaseAfterDocument, reducer } from './chunk-TORKYG3K.js';
2
+ import './chunk-NHNGQ5BB.js';
3
3
  import './chunk-IQKHRPJR.js';
4
4
  import './chunk-QFA3K5ZV.js';
5
5
  import './chunk-AIK7CDV6.js';
package/dist/challenge.js CHANGED
@@ -1,9 +1,7 @@
1
1
  import { assertNever } from './chunk-UBQTPS5J.js';
2
- import { challengeFromIframeMessageSchema } from './chunk-6U53T32A.js';
3
- import './chunk-IQKHRPJR.js';
4
- import './chunk-QFA3K5ZV.js';
2
+ import { external_exports } from './chunk-NHNGQ5BB.js';
5
3
  import './chunk-AIK7CDV6.js';
6
4
 
7
- function createChallengeController(deps){let started=false;let destroyed=false;let resetInFlight=false;let messageListener=null;function postInit(){const iframe=deps.getIframe();if(iframe===null||iframe.contentWindow===null)return;const init={type:"challenge:init",...deps.theme!==void 0?{theme:deps.theme}:{},...deps.locale!==void 0?{locale:deps.locale}:{}};iframe.contentWindow.postMessage(init,deps.embedOrigin);}function postReset(){const iframe=deps.getIframe();if(iframe===null||iframe.contentWindow===null)return;const reset={type:"challenge:reset"};iframe.contentWindow.postMessage(reset,deps.embedOrigin);}function handleMessage(msg){switch(msg.type){case "challenge:ready":{resetInFlight=false;return}case "challenge:token":{resetInFlight=false;deps.onToken(msg.token);return}case "challenge:error":{resetInFlight=false;deps.onError(msg.code);return}default:{return assertNever(msg)}}}function onWindowMessage(event){if(destroyed)return;if(event.origin!==deps.embedOrigin)return;if(event.source!==null&&event.source!==deps.getIframe()?.contentWindow)return;const parsed=challengeFromIframeMessageSchema.safeParse(event.data);if(!parsed.success)return;handleMessage(parsed.data);}return {start(){if(destroyed||started)return;started=true;messageListener=onWindowMessage;window.addEventListener("message",messageListener);postInit();},reset(){if(destroyed||!started)return;if(resetInFlight)return;resetInFlight=true;postReset();},destroy(){if(destroyed)return;destroyed=true;if(messageListener!==null){window.removeEventListener("message",messageListener);messageListener=null;}}}}
5
+ var canonicalOriginSchema=external_exports.string().min(1).refine(v=>{if(v.includes("*"))return false;try{return new URL(v).origin===v}catch{return false}},"must be a canonical origin (scheme and host[:port], no path / query / fragment / credentials / wildcard)");var challengeErrorCodeEnum=external_exports.enum(["challenge_failed","load_failed","expired","config_error"]);var challengeInitMessageSchema=external_exports.object({type:external_exports.literal("challenge:init"),theme:external_exports.enum(["light","dark"]).optional(),locale:external_exports.string().optional()}).strict();var challengeResetMessageSchema=external_exports.object({type:external_exports.literal("challenge:reset")}).strict();external_exports.discriminatedUnion("type",[challengeInitMessageSchema,challengeResetMessageSchema]);var challengeReadyMessageSchema=external_exports.object({type:external_exports.literal("challenge:ready")}).strict();var challengeTokenMessageSchema=external_exports.object({type:external_exports.literal("challenge:token"),token:external_exports.string().min(1)}).strict();var challengeErrorMessageSchema=external_exports.object({type:external_exports.literal("challenge:error"),code:challengeErrorCodeEnum}).strict();var challengeFromIframeMessageSchema=external_exports.discriminatedUnion("type",[challengeReadyMessageSchema,challengeTokenMessageSchema,challengeErrorMessageSchema]);external_exports.object({challengeContextToken:external_exports.string().min(1),embedOrigin:canonicalOriginSchema}).strict();function createChallengeController(deps){let started=false;let destroyed=false;let resetInFlight=false;let messageListener=null;function postInit(){const iframe=deps.getIframe();if(iframe===null||iframe.contentWindow===null)return;const init={type:"challenge:init",...deps.theme!==void 0?{theme:deps.theme}:{},...deps.locale!==void 0?{locale:deps.locale}:{}};iframe.contentWindow.postMessage(init,deps.embedOrigin);}function postReset(){const iframe=deps.getIframe();if(iframe===null||iframe.contentWindow===null)return;const reset={type:"challenge:reset"};iframe.contentWindow.postMessage(reset,deps.embedOrigin);}function handleMessage(msg){switch(msg.type){case "challenge:ready":{resetInFlight=false;return}case "challenge:token":{resetInFlight=false;deps.onToken(msg.token);return}case "challenge:error":{resetInFlight=false;deps.onError(msg.code);return}default:{return assertNever(msg)}}}function onWindowMessage(event){if(destroyed)return;if(event.origin!==deps.embedOrigin)return;if(event.source!==null&&event.source!==deps.getIframe()?.contentWindow)return;const parsed=challengeFromIframeMessageSchema.safeParse(event.data);if(!parsed.success)return;handleMessage(parsed.data);}return {start(){if(destroyed||started)return;started=true;messageListener=onWindowMessage;window.addEventListener("message",messageListener);postInit();},reset(){if(destroyed||!started)return;if(resetInFlight)return;resetInFlight=true;postReset();},destroy(){if(destroyed)return;destroyed=true;if(messageListener!==null){window.removeEventListener("message",messageListener);messageListener=null;}}}}
8
6
 
9
7
  export { createChallengeController };
@@ -0,0 +1,7 @@
1
+ import { withTokenRetry } from './chunk-S2OOEDJS.js';
2
+ import { sdkPublicSettings, SESSIONS_ME_PATH, dataPlaneHeaders } from './chunk-KK66RKPI.js';
3
+ import { IDV_DOCUMENT_TYPES } from './chunk-IQKHRPJR.js';
4
+
5
+ var SDK_MODULES=["idv","fraud","custom_form"];var BIOMETRIC_MODES=["none","selfie","liveness"];var DOCUMENT_TYPES=IDV_DOCUMENT_TYPES;var SDK_MODES=["live","test"];var DATA_REGIONS=Object.keys(sdkPublicSettings.regions);var COLLECT_USER_INFO_FIELD_VALUES=["email","phone","dob","address"];function isRecord(v){return typeof v==="object"&&v!==null}function isNonEmptyString(v){return typeof v==="string"&&v.length>0}function isSdkModule(v){return typeof v==="string"&&SDK_MODULES.includes(v)}function isBiometricMode(v){return typeof v==="string"&&BIOMETRIC_MODES.includes(v)}function isSdkMode(v){return typeof v==="string"&&SDK_MODES.includes(v)}function isSdkRegion(v){return typeof v==="string"&&DATA_REGIONS.includes(v)}function isDocumentType(v){return typeof v==="string"&&DOCUMENT_TYPES.includes(v)}function isCollectUserInfoField(v){return typeof v==="string"&&COLLECT_USER_INFO_FIELD_VALUES.includes(v)}function parseCollectUserInfoConfig(value){if(!isRecord(value))return null;const fields=value.fields;const captureStructuredName=value.capture_structured_name;if(!Array.isArray(fields))return null;const parsedFields=[];for(const f of fields){if(!isCollectUserInfoField(f))return null;parsedFields.push(f);}if(typeof captureStructuredName!=="boolean")return null;return {fields:parsedFields,captureStructuredName}}function parseIdvConfig(value){if(!isRecord(value))return null;const documentTypes=value.document_types;const biometricMode=value.biometric_mode;const minAge=value.min_age;if(!Array.isArray(documentTypes)||documentTypes.length<1)return null;const types=[];for(const t of documentTypes){if(!isDocumentType(t))return null;types.push(t);}if(!isBiometricMode(biometricMode))return null;if(minAge!==void 0&&typeof minAge!=="number")return null;const config={documentTypes:types,biometricMode};if(typeof minAge==="number")config.minAge=minAge;return config}function parseSessionData(body){if(!isRecord(body)||!isRecord(body.data))return null;const d=body.data;const sessionId=d.session_id;const stepId=d.step_id;const stepType=d.step_type;if(!isNonEmptyString(sessionId)||!isNonEmptyString(stepId)||!isNonEmptyString(stepType)||!isSdkMode(d.mode)||!isSdkRegion(d.region)){return null}if(!Array.isArray(d.modules)||!d.modules.every(isSdkModule))return null;const modules=d.modules;const wantsIdv=stepType==="id_verification";let config=null;if(wantsIdv){config=parseIdvConfig(d.config);if(config===null)return null}const collectUserInfoConfig=stepType==="collect_user_info"?parseCollectUserInfoConfig(d.config)??void 0:void 0;return {sessionId,stepId,stepType,config,mode:d.mode,region:d.region,modules,...collectUserInfoConfig!==void 0?{collectUserInfoConfig}:{}}}function isJourneyPlaneBody(body){if(!isRecord(body)||!isRecord(body.data))return false;const d=body.data;if("session_id"in d)return false;return isRecord(d.session)||isRecord(d.snapshot)}function isNonRenderableMarker(body){if(!isRecord(body)||!isRecord(body.data))return false;return body.data.renderable===false}function warnWrongTokenPlane(){console.warn("[Checktiv] The session token reached the wrong data plane. For the zero-lifecycle APIs (Checktiv.mount() or collectUserInfo), fetchToken must return your durable client token, which the SDK exchanges for a working token. For a customer-embed Checktiv.init(), getSessionToken must return a browser token.");}async function resolveSession(ctx,fetchImpl){const origin=ctx.apiBaseOrigin;let res;try{res=await withTokenRetry(ctx.tokens,token=>fetchImpl(origin+SESSIONS_ME_PATH,{method:"GET",headers:dataPlaneHeaders(ctx,token)}),result=>result?.status===401);}catch{return {kind:"unresolved"}}if(!res.ok)return {kind:"unresolved"};let body;try{body=await res.json();}catch{return {kind:"unresolved"}}if(isNonRenderableMarker(body))return {kind:"nothing_to_render"};const data=parseSessionData(body);if(data!==null){ctx.setSessionId(data.sessionId);return {kind:"ok",session:data}}if(isJourneyPlaneBody(body))return {kind:"wrong_token"};return {kind:"unresolved"}}
6
+
7
+ export { isJourneyPlaneBody, isRecord, resolveSession, warnWrongTokenPlane };
@@ -1,5 +1,5 @@
1
- import { createChecktivError } from './chunk-7NIKMJFJ.js';
1
+ import { createChecktivError } from './chunk-OC5N6W7T.js';
2
2
 
3
- function createChecktivErrorEvent(code){return {type:"checktiv.idv.error",error:createChecktivError(code)}}var CAPTURE_ERROR_CODE={cv_gate_failed:"cv_gate_failed",upload_failed:"upload_failed",sdk_load_failed:"sdk_load_failed",biometric_unsupported:"biometric_unsupported",camera_unsupported:"camera_unsupported",selfie_camera_denied:"camera_denied",liveness_camera_denied:"camera_denied",liveness_runtime_error:"sdk_load_failed",liveness_timeout:"sdk_load_failed",liveness_server_error:"sdk_load_failed",liveness_cancelled:"sdk_load_failed",protocol_mismatch:"protocol_mismatch"};function mapStateToEvent(state,ctx){switch(state.kind){case "minting":case "waiting_for_init":case "submitting":return null;case "ready":return {type:"checktiv.idv.ready",config:ctx.config};case "capturing":if(state.phase==="coaching"&&state.coaching!==null){return {type:"checktiv.idv.coaching",hint:state.coaching}}return {type:"checktiv.idv.phase",phase:state.phase};case "mint_error":return createChecktivErrorEvent("session_expired");case "submit_error":return createChecktivErrorEvent("upload_failed");case "submit_pending":return {type:"checktiv.idv.processing"};case "capture_superseded":return {type:"checktiv.idv.capture_superseded"};case "token_expired":return createChecktivErrorEvent("token_expired");case "capture_error":return createChecktivErrorEvent(CAPTURE_ERROR_CODE[state.errorKind]);default:return null}}var opener=null;function registerCrossDeviceOpener(fn){opener=fn;}function getCrossDeviceOpener(){return opener}
3
+ function createChecktivErrorEvent(code){return {type:"checktiv.idv.error",error:createChecktivError(code)}}var CAPTURE_ERROR_CODE={cv_gate_failed:"cv_gate_failed",upload_failed:"upload_failed",sdk_load_failed:"sdk_load_failed",biometric_unsupported:"biometric_unsupported",camera_unsupported:"camera_unsupported",selfie_camera_denied:"camera_denied",liveness_camera_denied:"camera_denied",liveness_runtime_error:"sdk_load_failed",liveness_timeout:"sdk_load_failed",liveness_server_error:"sdk_load_failed",liveness_cancelled:"sdk_load_failed",protocol_mismatch:"protocol_mismatch"};function mapStateToEvent(state,ctx){switch(state.kind){case "minting":case "waiting_for_init":case "submitting":return null;case "ready":return {type:"checktiv.idv.ready",config:ctx.config};case "capturing":if(state.phase==="coaching"&&state.coaching!==null){return {type:"checktiv.idv.coaching",hint:state.coaching}}return {type:"checktiv.idv.phase",phase:state.phase};case "mint_error":return createChecktivErrorEvent("session_expired");case "submit_error":return createChecktivErrorEvent("upload_failed");case "submit_pending":return {type:"checktiv.idv.processing",reason:"signal_pending"};case "capture_superseded":return {type:"checktiv.idv.capture_superseded"};case "token_expired":return createChecktivErrorEvent("token_expired");case "capture_error":return createChecktivErrorEvent(CAPTURE_ERROR_CODE[state.errorKind]);default:return null}}var opener=null;function registerCrossDeviceOpener(fn){opener=fn;}function getCrossDeviceOpener(){return opener}
4
4
 
5
5
  export { createChecktivErrorEvent, getCrossDeviceOpener, mapStateToEvent, registerCrossDeviceOpener };
@@ -0,0 +1,13 @@
1
+ import { getModule } from './chunk-GFHNOZVO.js';
2
+ import { createChecktivError } from './chunk-OC5N6W7T.js';
3
+ import { parsePublishableKey, createWorkingTokenSource, createWorkingTokenManager } from './chunk-EYSE7JJ4.js';
4
+ import { resolveSession, warnWrongTokenPlane } from './chunk-7F7ZMYB7.js';
5
+ import { assertNever } from './chunk-UBQTPS5J.js';
6
+ import { createTokenManager } from './chunk-S2OOEDJS.js';
7
+ import { resolveApiBaseOrigin, sdkPublicSettings, shortCodeRefreshPath, PUBLISHABLE_KEY_HEADER, SESSIONS_ME_REFRESH_LINK_PATH } from './chunk-KK66RKPI.js';
8
+ import { R, k } from './chunk-XOGHMNBX.js';
9
+ import { getServiceOrigin } from './chunk-QFA3K5ZV.js';
10
+
11
+ var HOST_TAG="checktiv-root";var MOUNTED_FLAG="__checktivMounted";var LEGACY_HOST_ATTR="data-autohost-kyc-host";var HOST_ATTR="data-checktiv-host";var shadowCache=new WeakMap;function mountShadowHost(target){const existing=findExistingHost(target);if(existing){const cached=shadowCache.get(existing);if(cached)return cached}const host=document.createElement("div");host.setAttribute(HOST_ATTR,HOST_TAG);host.setAttribute(LEGACY_HOST_ATTR,HOST_TAG);host[MOUNTED_FLAG]=true;target.appendChild(host);const shadow=host.attachShadow({mode:"closed"});shadowCache.set(host,shadow);return shadow}function findExistingHost(target){for(const child of Array.from(target.children)){if(!(child instanceof HTMLElement))continue;const candidate=child;if(candidate[MOUNTED_FLAG]===true)return candidate}return null}function moduleErrorEvent(name,error){switch(name){case "idv":return {type:"checktiv.idv.error",error};case "fraud":return {type:"checktiv.fraud.error",error};case "custom_form":return {type:"checktiv.custom_form.error",error}}}function missingModuleMessage(name){return `This session requires the '${name}' module. Import '@checktiv/sdk-web/${name}' in your app.`}function missingModuleError(name){const base=createChecktivError("sdk_load_failed");return moduleErrorEvent(name,{...base,message:missingModuleMessage(name)})}function consentGateRequiredError(){const base=createChecktivError("sdk_load_failed");return moduleErrorEvent("fraud",{...base,message:"This session includes the 'fraud' module, which needs a consent gate. Pass onConsent to mountProvisioned() to enable it."})}function customFormConfigRequiredError(){const base=createChecktivError("sdk_load_failed");return moduleErrorEvent("custom_form",{...base,message:"This session includes the 'custom_form' module, which needs its form config. Pass customFormConfig to mountProvisioned() to enable it."})}function unmappedStepTypeError(stepType){const base=createChecktivError("sdk_load_failed");return moduleErrorEvent("idv",{...base,message:`This session's current step ('${stepType}') has no matching visual module in this SDK build. Upgrade '@checktiv/sdk-web' to a version that renders this step.`})}var MODULE_IS_VISUAL={idv:true,fraud:false,custom_form:true};var STEP_TYPE_TO_VISUAL_MODULE={id_verification:"idv",custom_form:"custom_form"};var stepTypeToVisualModuleView=STEP_TYPE_TO_VISUAL_MODULE;function resolveCurrentStepVisualModule(stepType){return stepTypeToVisualModuleView[stepType]}function defaultLoadModule(name){if(name==="idv"){const factory2=getModule("idv");if(factory2===void 0)return Promise.resolve(null);return Promise.resolve({mount:(ctx,opts)=>factory2(ctx,{target:opts.target,onEvent:opts.onEvent,copy:opts.copy,layout:opts.layout,maxWidth:opts.maxWidth,onBeforeSubmit:opts.onBeforeSubmit,onBehaviorSegment:opts.onBehaviorSegment,synthetic:opts.synthetic,crossDeviceCopy:opts.crossDeviceCopy,onOpenCrossDevice:opts.onOpenCrossDevice})})}if(name==="custom_form"){const factory2=getModule("custom_form");if(factory2===void 0)return Promise.resolve(null);return Promise.resolve({mount:(ctx,opts)=>{if(opts.customFormConfig===void 0){opts.onEvent?.(customFormConfigRequiredError());return {destroy:()=>void 0}}return factory2(ctx,{target:opts.target,config:opts.customFormConfig,copy:opts.customFormCopy,onEvent:opts.onEvent,session:opts.session})}})}const factory=getModule("fraud");if(factory===void 0)return Promise.resolve(null);return Promise.resolve({mount:(ctx,opts)=>{const onConsent=opts.onConsent;if(onConsent===void 0){opts.onEvent?.(consentGateRequiredError());return {destroy:()=>void 0}}return factory(ctx,{onConsent,onEvent:opts.onEvent})}})}function moduleErrorFor(name,code){return moduleErrorEvent(name,createChecktivError(code))}function createMountProvisioned(ctx,opts,deps={}){const emit=e=>opts.onEvent?.(e);const fetchImpl=opts.fetchImpl??fetch;const resolveSession2=deps.resolveSession??(()=>resolveSession(ctx,fetchImpl));const loadModule=deps.loadModule??defaultLoadModule;const handles=[];let destroyed=false;let idvOpenCrossDevice=null;void(async()=>{try{await composeModules();}catch(err){if(destroyed)return;console.warn("[Checktiv] mountProvisioned composition failed.",err);emit(moduleErrorFor("idv","sdk_load_failed"));}})();async function composeModules(){const resolution=await resolveSession2();if(destroyed)return;let session;switch(resolution.kind){case "ok":session=resolution.session;break;case "wrong_token":warnWrongTokenPlane();emit(moduleErrorFor("idv","wrong_token_type"));return;case "unresolved":emit(moduleErrorFor("idv","session_expired"));return;case "nothing_to_render":emit({type:"checktiv.idv.processing",reason:"no_renderable_step"});return;default:return assertNever(resolution)}const currentStepVisualModule=resolveCurrentStepVisualModule(session.stepType);if(currentStepVisualModule===void 0&&session.modules.some(m=>MODULE_IS_VISUAL[m])){emit(unmappedStepTypeError(session.stepType));return}for(const name of session.modules){if(destroyed)return;if(MODULE_IS_VISUAL[name]&&name!==currentStepVisualModule){continue}if(name==="fraud"&&opts.onConsent===void 0){emit(consentGateRequiredError());continue}const mod=await loadModule(name);if(destroyed)return;if(mod===null){emit(missingModuleError(name));continue}let moduleTarget;let containerToRemove=null;if(MODULE_IS_VISUAL[name]){const resolvedParent=typeof opts.target==="string"?typeof document!=="undefined"?document.querySelector(opts.target):null:opts.target;if(resolvedParent!==null){const container=document.createElement("div");resolvedParent.appendChild(container);containerToRemove=container;moduleTarget=container;}else {moduleTarget=opts.target;}}else {moduleTarget=opts.target;}let innerHandle;try{innerHandle=mod.mount(ctx,{target:moduleTarget,onEvent:opts.onEvent,onConsent:opts.onConsent,copy:opts.copy,layout:opts.layout,maxWidth:opts.maxWidth,onBeforeSubmit:opts.onBeforeSubmit,onBehaviorSegment:opts.onBehaviorSegment,synthetic:opts.synthetic,crossDeviceCopy:opts.crossDeviceCopy,onOpenCrossDevice:opts.onOpenCrossDevice,customFormConfig:opts.customFormConfig,customFormCopy:opts.customFormCopy,session:{sessionId:session.sessionId,stepId:session.stepId}});}catch(err){containerToRemove?.remove();throw err}if(name==="idv"){idvOpenCrossDevice=innerHandle.openCrossDevice??null;}const capturedContainer=containerToRemove;const handle={destroy(){try{innerHandle.destroy();}finally{capturedContainer?.remove();}}};if(destroyed){handle.destroy();return}handles.push(handle);}}return {destroy(){destroyed=true;while(handles.length>0){const handle=handles.pop();handle?.destroy();}},openCrossDevice(){idvOpenCrossDevice?.();}}}function init(opts,deps={}){const scope="publishableKey"in opts?{...parsePublishableKey(opts.publishableKey),publishableKey:opts.publishableKey}:{region:opts.region,mode:opts.mode,publishableKey:void 0};let sessionId="";const apiBaseOrigin=resolveApiBaseOrigin(opts.apiBase,scope.region,scope.mode);const ctx={region:scope.region,mode:scope.mode,publishableKey:scope.publishableKey,apiBaseOrigin,theme:opts.theme,locale:opts.locale??"en",betas:opts.betas??[],...opts.selfiePromptMap!==void 0?{selfiePromptMap:opts.selfiePromptMap}:{},...opts.selfieChromeCopy!==void 0?{selfieChromeCopy:opts.selfieChromeCopy}:{},tokens:deps.tokens??createTokenManager(opts.getSessionToken,()=>sessionId),getSessionId:()=>sessionId,setSessionId:id=>{sessionId=id;}};function mount2(...args){if(args[0]==="idv"){const factory2=getModule("idv");if(factory2===void 0)return missingIdvHandle(args[1]);return factory2(ctx,args[1])}if(args[0]==="custom_form"){const factory2=getModule("custom_form");if(factory2===void 0)return missingCustomFormHandle(args[1]);return factory2(ctx,args[1])}const factory=getModule("fraud");if(factory===void 0)return missingFraudHandle(args[1]);return factory(ctx,args[1])}return {mountProvisioned:provOpts=>createMountProvisioned(ctx,provOpts),mount:mount2}}function missingIdvHandle(opts){const base=createChecktivError("sdk_load_failed");opts.onEvent?.({type:"checktiv.idv.error",error:{...base,message:missingModuleMessage("idv")}});return {destroy:()=>void 0,unmount:()=>void 0}}function missingFraudHandle(opts){const base=createChecktivError("sdk_load_failed");opts.onEvent?.({type:"checktiv.fraud.error",error:{...base,message:missingModuleMessage("fraud")}});return {destroy:()=>void 0}}function missingCustomFormHandle(opts){const base=createChecktivError("sdk_load_failed");const error={type:"checktiv.custom_form.error",error:{...base,message:missingModuleMessage("custom_form")}};opts.onEvent?.(error);return {destroy:()=>void 0}}var RESUME_CLIENT_TOKEN_KEY_PREFIX="checktiv.rct.";function safeLocalStorage(){try{return globalThis.localStorage??null}catch{return null}}function createClientTokenStore(resumeKey,storage=safeLocalStorage()){const key=RESUME_CLIENT_TOKEN_KEY_PREFIX+resumeKey;return {read(){if(storage===null)return null;try{const raw=storage.getItem(key);return raw!==null&&raw.length>0?raw:null}catch{return null}},write(token){if(storage===null)return;try{storage.setItem(key,token);}catch{}},clear(){if(storage===null)return;try{storage.removeItem(key);}catch{}}}}async function requestSelfServiceResend(params){const fetchImpl=params.fetchImpl??fetch;const body=JSON.stringify({confirmEmail:params.confirmEmail});try{let res;if(params.mode==="short_code"){res=await fetchImpl(params.origin+shortCodeRefreshPath(params.shortCode),{method:"POST",headers:{"content-type":"application/json"},body});}return {requested:res.ok}}catch{return {requested:false}}}var version="1.6.0";var initialised=new WeakSet;function resolveVerifyOrigin(parsed){return getServiceOrigin(sdkPublicSettings.apps.verify.subdomain,"prod",parsed.region,sdkPublicSettings)}function buildPopupUrl(parsed,opts){const origin=resolveVerifyOrigin(parsed);if(opts.applicantLinkToken){return `${origin}/start?lt=${encodeURIComponent(opts.applicantLinkToken)}`}return `${origin}/`}function launchPopup(url){const w=460;const h=760;const left=Math.max(0,Math.floor((window.screen.width-w)/2));const top=Math.max(0,Math.floor((window.screen.height-h)/2));const features=`popup=yes,width=${w},height=${h},left=${left},top=${top}`;const popup=window.open(url,"checktiv",features);if(!popup){window.location.href=url;return null}return popup}var COMPLETE_EVENT_TYPE="autohost.kyc.complete";function isCompletionMessage(data){if(typeof data!=="object"||data===null)return false;if(!("type"in data))return false;return data.type===COMPLETE_EVENT_TYPE}function listenForCompletion(expectedOrigin,onComplete){if(!onComplete)return;const handler=event=>{if(event.origin!==expectedOrigin)return;const data=event.data;if(!isCompletionMessage(data))return;onComplete(data);};window.addEventListener("message",handler);}function buildButton(onClick){const children="Start verification";return k("button",{type:"button",onClick,style:'display: inline-flex; align-items: center; justify-content: center; padding: 10px 20px; font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif; font-size: 14px; font-weight: 600; color: #fff; background: #0b5fff; border: none; border-radius: 6px; cursor: pointer;'},children)}function resolveTarget(opts){if(opts.target)return opts.target;return document.querySelector("[data-checktiv]")??document.querySelector("[data-autohost-kyc]")}function mountButton(opts){const parsed=parsePublishableKey(opts.publishableKey);const target=resolveTarget(opts);if(!target){console.warn("[Checktiv] No mount target found. Either pass `target` explicitly or add `<div data-checktiv>` to your page.");return}if(initialised.has(target))return;initialised.add(target);const shadow=mountShadowHost(target);const verifyOrigin=resolveVerifyOrigin(parsed);listenForCompletion(verifyOrigin,opts.onComplete);const onClick=()=>{const popupUrl=buildPopupUrl(parsed,opts);launchPopup(popupUrl);};R(buildButton(onClick),shadow);}function completionSessionId(e){if(e.type!=="checktiv.idv.submitted"&&e.type!=="checktiv.custom_form.submitted"){return null}const sid="sessionId"in e?e.sessionId:void 0;return typeof sid==="string"&&sid.length>0?sid:null}function isSessionExpiredEvent(e){if(!e.type.endsWith(".error")||!("error"in e))return false;const err=e.error;if(typeof err!=="object"||err===null||!("code"in err))return false;return err.code==="session_expired"}function mount(target,opts){const fetchImpl=opts.fetchImpl??fetch;const scope="publishableKey"in opts?{...parsePublishableKey(opts.publishableKey),publishableKey:opts.publishableKey}:{region:opts.region,mode:opts.mode,publishableKey:void 0};const mintOrigin=resolveApiBaseOrigin(opts.apiBase,scope.region,scope.mode);const store=opts.resumeKey!==void 0?createClientTokenStore(opts.resumeKey):null;let clientTokenPromise=null;const getClientToken=()=>{if(clientTokenPromise!==null)return clientTokenPromise;const persisted=store?.read()??null;if(persisted!==null){clientTokenPromise=Promise.resolve(persisted);return clientTokenPromise}const p=opts.fetchToken();clientTokenPromise=p;void p.then(tok=>store?.write(tok),()=>{if(clientTokenPromise===p)clientTokenPromise=null;});return p};const mintWorkingToken=createWorkingTokenSource(mintOrigin,getClientToken,scope.publishableKey,fetchImpl);const tokens=createWorkingTokenManager(mintWorkingToken);const base={getSessionToken:()=>tokens.get(),...opts.apiBase!==void 0?{apiBase:opts.apiBase}:{},...opts.theme!==void 0?{theme:opts.theme}:{}};const initOptions=scope.publishableKey!==void 0?{...base,publishableKey:scope.publishableKey}:{...base,region:scope.region,mode:scope.mode};const needsChannel=opts.onEvent!==void 0||opts.onComplete!==void 0||store!==null;const onEvent=needsChannel?e=>{opts.onEvent?.(e);const sessionId=completionSessionId(e);if(sessionId!==null){store?.clear();opts.onComplete?.({sessionId});}else if(isSessionExpiredEvent(e)){store?.clear();}}:void 0;const client=init(initOptions,{tokens});const handle=client.mountProvisioned({target,fetchImpl,onEvent,onConsent:opts.onConsent,...opts.layout!==void 0?{layout:opts.layout}:{},...opts.maxWidth!==void 0?{maxWidth:opts.maxWidth}:{},...opts.copy!==void 0?{copy:opts.copy}:{},...opts.crossDeviceCopy!==void 0?{crossDeviceCopy:opts.crossDeviceCopy}:{},...opts.onOpenCrossDevice!==void 0?{onOpenCrossDevice:opts.onOpenCrossDevice}:{}});const requestResend=confirmEmail=>{if(opts.shortCode===void 0)return Promise.resolve({requested:false});return requestSelfServiceResend({mode:"short_code",origin:mintOrigin,shortCode:opts.shortCode,confirmEmail,fetchImpl})};return {destroy(){handle.destroy();tokens.stop();},openCrossDevice:()=>handle.openCrossDevice?.(),requestResend}}function applicantToWire(a){const wire={};if(a.externalId!==void 0)wire.external_id=a.externalId;if(a.email!==void 0)wire.email=a.email;if(a.phone!==void 0)wire.phone=a.phone;if(a.firstName!==void 0)wire.first_name=a.firstName;if(a.middleName!==void 0)wire.middle_name=a.middleName;if(a.lastName!==void 0)wire.last_name=a.lastName;if(a.legalName!==void 0)wire.legal_name=a.legalName;if(a.dateOfBirth!==void 0)wire.date_of_birth=a.dateOfBirth;if(a.address!==void 0)wire.address=a.address;if(a.referenceName!==void 0)wire.reference_name=a.referenceName;return wire}function readCreatedClientToken(body){if(typeof body!=="object"||body===null||!("data"in body))return null;const data=body.data;if(typeof data!=="object"||data===null||!("client_token"in data))return null;const clientToken=data.client_token;return typeof clientToken==="string"&&clientToken.length>0?clientToken:null}var sessions={async create(input,options){if(typeof window!=="undefined"||typeof document!=="undefined"){throw new Error("checktiv.sessions.create must run on your server: it needs your secret key. Never call it in the browser.")}const fetchImpl=options.fetchImpl??fetch;const headers={Authorization:`Bearer ${options.secretKey}`,"content-type":"application/json"};if(options.idempotencyKey!==void 0)headers["Idempotency-Key"]=options.idempotencyKey;const body=JSON.stringify({workflow_template_id:input.templateId,applicant:applicantToWire(input.applicant)});const res=await fetchImpl(`${options.apiBase}/v1/sessions`,{method:"POST",headers,body});if(!res.ok){throw new Error(`Checktiv sessions.create failed (status ${res.status}). Verify the apiBase origin and secret key.`)}let parsed;try{parsed=await res.json();}catch{throw new Error("Checktiv sessions.create returned a non-JSON response.")}const clientToken=readCreatedClientToken(parsed);if(clientToken===null){throw new Error("Checktiv sessions.create response carried no client token. Enable the working-token capability for this environment, then retry.")}return {clientToken}}};
12
+
13
+ export { init, mount, mountButton, sessions, version };
@@ -0,0 +1,5 @@
1
+ import { WORKING_TOKEN_MINT_PATH, PUBLISHABLE_KEY_HEADER } from './chunk-KK66RKPI.js';
2
+
3
+ var PUBLISHABLE_KEY_REGEX=/^ah_pk_(us|eu)_(live|test)_[A-Za-z0-9_-]{8,}$/;var InvalidPublishableKeyError=class extends Error{constructor(message){super(message);this.name="InvalidPublishableKeyError";}};function parsePublishableKey(key){const match=PUBLISHABLE_KEY_REGEX.exec(key);if(!match){throw new InvalidPublishableKeyError(`Invalid publishable key format. Expected ah_pk_<us|eu>_<live|test>_<token>, got: ${maskKey(key)}`)}const region=match[1];const mode=match[2];if(region!=="us"&&region!=="eu"){throw new InvalidPublishableKeyError(`Invalid region in publishable key: ${maskKey(key)}`)}if(mode!=="test"&&mode!=="live"){throw new InvalidPublishableKeyError(`Invalid mode in publishable key: ${maskKey(key)}`)}return {region,mode}}function maskKey(key){if(key.length<=8)return "***";return `${key.slice(0,6)}...${key.slice(-2)}`}var DEFAULT_REFRESH_MARGIN_MS=6e4;function createWorkingTokenManager(source,deps={}){const now=deps.now??(()=>Date.now());const setTimer=deps.setTimer??((fn,ms)=>setTimeout(fn,ms));const clearTimer=deps.clearTimer??(handle=>clearTimeout(handle));const marginMs=deps.marginMs??DEFAULT_REFRESH_MARGIN_MS;const onProactiveError=deps.onProactiveError;let cached=null;let pending=null;let timer=null;let stopped=false;const clearScheduled=()=>{if(timer!==null){clearTimer(timer);timer=null;}};const scheduleProactive=expiresAt=>{clearScheduled();if(stopped)return;const expiryMs=Date.parse(expiresAt);if(Number.isNaN(expiryMs))return;const delay=expiryMs-now()-marginMs;if(delay<=0)return;timer=setTimer(()=>{timer=null;void doRefresh("expired").catch(err=>onProactiveError?.(err));},delay);};const mintOnce=reason=>source(reason).then(minted=>{scheduleProactive(minted.expiresAt);return minted.token});const doRefresh=reason=>{if(pending!==null)return pending;const p=mintOnce(reason);pending=p;cached=p;void p.then(()=>{if(pending===p)pending=null;},()=>{if(pending===p)pending=null;if(cached===p)cached=null;});return p};return {get(){if(cached!==null)return cached;const p=mintOnce("initial");cached=p;void p.catch(()=>{if(cached===p)cached=null;});return p},refresh(reason){return doRefresh(reason)},stop(){stopped=true;clearScheduled();}}}function parseWorkingTokenMintResponse(body){if(typeof body!=="object"||body===null)return null;if(!("workingToken"in body)||!("expiresAt"in body))return null;const workingToken=body.workingToken;const expiresAt=body.expiresAt;if(typeof workingToken!=="string"||workingToken.length===0)return null;if(typeof expiresAt!=="string"||expiresAt.length===0)return null;return {workingToken,expiresAt}}async function mintWorkingTokenFacet(origin,clientToken,publishableKey,fetchImpl){const headers={Authorization:`Bearer ${clientToken}`};if(publishableKey!==void 0)headers[PUBLISHABLE_KEY_HEADER]=publishableKey;const res=await fetchImpl(origin+WORKING_TOKEN_MINT_PATH,{method:"POST",headers});if(!res.ok){throw new Error(`Checktiv working-token mint failed (status ${res.status}).`)}let body;try{body=await res.json();}catch{throw new Error("Checktiv working-token mint returned a non-JSON body.")}const parsed=parseWorkingTokenMintResponse(body);if(parsed===null)throw new Error("Checktiv working-token mint returned a malformed body.");return parsed}function createWorkingTokenSource(origin,getClientToken,publishableKey,fetchImpl){return async()=>{const clientToken=await getClientToken();const minted=await mintWorkingTokenFacet(origin,clientToken,publishableKey,fetchImpl);return {token:minted.workingToken,expiresAt:minted.expiresAt}}}
4
+
5
+ export { InvalidPublishableKeyError, createWorkingTokenManager, createWorkingTokenSource, parsePublishableKey };
@@ -0,0 +1,7 @@
1
+ import { u } from './chunk-HV2QKVJX.js';
2
+ import { R, k } from './chunk-XOGHMNBX.js';
3
+ import { createCaptureController, isBiometricPhase, coachingKindForState } from './chunk-TORKYG3K.js';
4
+
5
+ function coachingFallback(kind){switch(kind){case "move_closer":return "Move a little closer.";case "move_farther":return "Move a little farther away.";case "reduce_glare":return "Reduce glare: tilt away from bright light.";case "too_dark":return "Find a brighter, well-lit spot.";case "wrong_side":return "Show the other side of your document.";case "hold_steady":return "Hold steady and keep everything in frame."}}function statusFallback(phase){switch(phase){case "ready":return "Getting the camera ready.";case "document_front":return "Position the front of your document in the frame.";case "document_back":return "Now show the back of your document.";case "selfie":return "Center your face in the frame.";case "liveness":return "Follow the on-screen prompts to confirm it is you.";case "uploading":return "Uploading. This takes a few seconds.";case "coaching":return "Hold steady and keep everything in frame."}}function errorFallback(kind){switch(kind){case "cv_gate_failed":return "We could not read that capture. Please try again in good lighting.";case "upload_failed":return "The upload did not finish. Check your connection and try again.";case "sdk_load_failed":return "The capture tools could not load. Refresh, or continue on your phone.";case "biometric_unsupported":return "This device cannot run the selfie check. Please continue on your phone.";case "camera_unsupported":return "Your camera does not meet the minimum resolution for capture. Please continue on your phone.";case "selfie_camera_denied":return "Camera access was blocked. Allow the camera, or continue on your phone.";case "liveness_camera_denied":return "Camera access was blocked. Allow the camera, or continue on your phone.";case "liveness_timeout":return "The check timed out. Please try again.";case "liveness_server_error":return "Something went wrong on our side. Please try again.";case "liveness_runtime_error":return "The check could not run. Refresh and try again.";case "liveness_cancelled":return "The check was canceled. Please try again when you are ready.";case "protocol_mismatch":return "This version of the verification tool is no longer supported. Please contact the operator to continue.";default:{const _exhaustive=kind;return _exhaustive}}}function terminalFallback(kind){switch(kind){case "mint_error":return "We could not start verification. Please try again.";case "submit_error":return "We could not submit your capture. Please try again.";case "token_expired":return "This step expired for your security. Please refresh to start again.";case "capture_superseded":return "Verification is active on another device. Finish there, or select Try again to continue here.";default:{const _exhaustive=kind;return _exhaustive}}}var fallbackCopy={cvReject:(_attemptIndex,kind)=>`We could not use that photo. ${coachingFallback(kind)}`,error:errorFallback,status:statusFallback,coaching:coachingFallback,terminal:terminalFallback,tryAgain:()=>"Try again",frameTitle:()=>"Identity verification capture"};var CSS_LENGTH_PATTERN=/^\d+(?:\.\d+)?(?:px|rem|em|vw|vh|%|ch)$/;function isValidCssLength(value){return CSS_LENGTH_PATTERN.test(value)}function maxWidthStyle(maxWidth){if(maxWidth===void 0||!isValidCssLength(maxWidth))return void 0;return `--idv-capture-max-width: ${maxWidth};`}var IFRAME_SANDBOX="allow-scripts allow-same-origin";function phaseOf(state){if(state.kind==="capturing")return state.phase;return "ready"}function statusLine(state,copy){if(state.kind==="capturing"&&state.phase==="coaching"&&state.coaching!==null){return (copy.coaching??fallbackCopy.coaching)(state.coaching)}return (copy.status??fallbackCopy.status)(phaseOf(state))}function CvRejectAlert({reason,attemptIndex,copy}){const kind=coachingKindForState(reason);const text=(copy.cvReject??fallbackCopy.cvReject)(attemptIndex,kind);return u("div",{role:"status","data-testid":"idv-cv-reject-alert",className:"idv-capture-cv-reject",style:"margin-bottom: 0.75rem;",children:text})}function CaptureFrame(props){const{colorMode="light",maxWidth}=props;const style=maxWidthStyle(maxWidth);return u("div",{className:"idv-capture-root","data-color-mode":colorMode,style,children:renderCaptureArm(props)})}function renderCaptureArm({state,attemptIndex,getEmbedSrc,onTryAgain,copy,layout="inline",immersiveActive=false,colorMode="light"}){switch(state.kind){case "minting":return u("div",{children:[u("div",{"data-testid":"idv-capture-skeleton","data-color-mode":colorMode,className:"idv-capture-skeleton idv-capture-skeleton--document idv-capture-skeleton--standalone","aria-hidden":"true"}),u("p",{className:"idv-capture-status","aria-live":"polite",children:(copy.status??fallbackCopy.status)("ready")})]});case "mint_error":case "submit_error":case "token_expired":case "capture_superseded":return u("div",{className:"idv-capture-error",role:"alert",children:[u("p",{children:(copy.terminal??fallbackCopy.terminal)(state.kind)}),u("button",{type:"button",onClick:onTryAgain,className:"idv-capture-retry",children:copy.tryAgain??fallbackCopy.tryAgain()})]});case "capture_error":{const errorKind=state.errorKind;const terminal=errorKind==="protocol_mismatch";return u("div",{className:"idv-capture-error",role:"alert",children:[u("p",{children:(copy.error??fallbackCopy.error)(errorKind)}),!terminal&&u("button",{type:"button",onClick:onTryAgain,className:"idv-capture-retry",children:copy.tryAgain??fallbackCopy.tryAgain()})]})}case "submitting":case "submit_pending":return u("p",{className:"idv-capture-status",children:(copy.status??fallbackCopy.status)("uploading")});case "waiting_for_init":case "ready":case "capturing":{const phase=phaseOf(state);const biometric=isBiometricPhase(phase);const frameClass=biometric?"idv-capture-frame idv-capture-frame--biometric":"idv-capture-frame";const reason=state.kind==="capturing"?state.lastCvRejectReason:null;const biometricLoading=biometric&&state.kind==="capturing"&&state.biometricLoading;const initialLoading=state.kind==="waiting_for_init";const showSkeleton=biometricLoading||initialLoading;const skeletonClass=initialLoading?"idv-capture-skeleton idv-capture-skeleton--document":"idv-capture-skeleton";const embedSrc=getEmbedSrc(state.embedOrigin);const immersive=layout==="immersive";const wrapperClass=immersive?"idv-capture-active idv-capture-immersive":"idv-capture-active";const frameTitle=copy.frameTitle??fallbackCopy.frameTitle();let iframeEl=null;const focusFrame=()=>iframeEl?.focus();return u("div",{className:wrapperClass,"data-color-mode":colorMode,role:immersiveActive?"dialog":void 0,"aria-modal":immersiveActive?"true":void 0,"aria-label":immersiveActive?frameTitle:void 0,children:[reason!==null&&u(CvRejectAlert,{reason,attemptIndex,copy}),showSkeleton&&u("div",{"data-testid":"idv-capture-skeleton","data-color-mode":colorMode,className:skeletonClass,"aria-hidden":"true"}),immersiveActive&&u("div",{className:"idv-capture-sentinel",tabIndex:0,onFocus:focusFrame}),u("iframe",{ref:el=>{iframeEl=el;},className:frameClass,title:frameTitle,src:embedSrc,allow:"camera",sandbox:IFRAME_SANDBOX}),immersiveActive&&u("div",{className:"idv-capture-sentinel",tabIndex:0,onFocus:focusFrame}),u("p",{className:"idv-capture-status","aria-live":"polite",children:statusLine(state,copy)})]})}default:{const _exhaustive=state;return _exhaustive}}}var IMMERSIVE_MEDIA="(pointer: coarse) and (max-width: 640px), (pointer: coarse) and (max-height: 640px)";function matchesImmersive(){return typeof window!=="undefined"&&typeof window.matchMedia==="function"&&window.matchMedia(IMMERSIVE_MEDIA).matches}function subscribeImmersive(cb){if(typeof window==="undefined"||typeof window.matchMedia!=="function"){return ()=>{}}const mql=window.matchMedia(IMMERSIVE_MEDIA);mql.addEventListener("change",cb);return ()=>{mql.removeEventListener("change",cb);}}function mount(element,options){const{copy,layout,maxWidth,onState,onControllerEvent,...deps}=options;const resolvedInitPayload=deps.initPayload();const controller=createCaptureController({...deps,initPayload:()=>resolvedInitPayload,getIframe:()=>element.querySelector("iframe.idv-capture-frame")});let destroyed=false;let state={kind:"minting"};let attemptIndex=0;const computeImmersiveActive=()=>layout==="immersive"&&matchesImmersive();let immersiveActive=computeImmersiveActive();let prevFocusable=false;let prevStateKind=state.kind;const IMMERSIVE_FILL_TOLERANCE_PX=2;let selfCheckRaf;let selfCheckWarned=false;const scheduleImmersiveSelfCheck=()=>{if(typeof requestAnimationFrame!=="function")return;if(selfCheckRaf!==void 0&&typeof cancelAnimationFrame==="function"){cancelAnimationFrame(selfCheckRaf);}selfCheckRaf=requestAnimationFrame(()=>{selfCheckRaf=void 0;if(destroyed||selfCheckWarned||typeof window==="undefined")return;const overlay=element.querySelector(".idv-capture-immersive");if(overlay===null)return;const rect=overlay.getBoundingClientRect();const vw=window.innerWidth;const vh=window.innerHeight;if(Math.abs(rect.width-vw)>IMMERSIVE_FILL_TOLERANCE_PX||Math.abs(rect.height-vh)>IMMERSIVE_FILL_TOLERANCE_PX){selfCheckWarned=true;console.warn("[Checktiv] immersive capture overlay does not fill the viewport",rect.width,rect.height,vw,vh);}});};const ERROR_ARM_KINDS={minting:false,mint_error:true,waiting_for_init:false,ready:false,capturing:false,submitting:false,submit_error:true,submit_pending:false,capture_superseded:true,token_expired:true,capture_error:true};const isErrorArm=kind=>ERROR_ARM_KINDS[kind];const onTryAgain=()=>{if(typeof window!=="undefined")window.location.reload();};const paint=()=>{if(destroyed)return;R(k(CaptureFrame,{state,attemptIndex,getEmbedSrc:deps.getEmbedSrc,onTryAgain,copy,layout,maxWidth,immersiveActive,colorMode:resolvedInitPayload.theme.colorMode}),element);const iframeEl=element.querySelector("iframe.idv-capture-frame");const iframePresent=iframeEl!==null;const focusable=immersiveActive&&iframePresent;if(focusable&&!prevFocusable&&!destroyed){iframeEl?.focus();scheduleImmersiveSelfCheck();}if(isErrorArm(state.kind)&&state.kind!==prevStateKind){element.querySelector(".idv-capture-retry")?.focus();}prevFocusable=focusable;prevStateKind=state.kind;};const rerender=()=>{if(destroyed)return;immersiveActive=computeImmersiveActive();paint();};const unsubImmersive=layout==="immersive"?subscribeImmersive(rerender):void 0;const safeObserve=(fn,arg)=>{if(fn===void 0)return;try{fn(arg);}catch(err){console.warn("[Checktiv] capture observer threw; ignoring (observational only).",err);}};const unsubState=controller.subscribe(next=>{state=next;paint();safeObserve(onState,next);});const offReject=controller.on("selfie-cv-reject",event=>{if(event.type==="selfie-cv-reject"){attemptIndex=event.attemptIndex;paint();}safeObserve(onControllerEvent,event);});const offComplete=controller.on("all-complete",event=>{safeObserve(onControllerEvent,event);});controller.start();return {destroy(){if(destroyed)return;destroyed=true;unsubState();offReject();offComplete();if(unsubImmersive!==void 0)unsubImmersive();if(selfCheckRaf!==void 0&&typeof cancelAnimationFrame==="function"){cancelAnimationFrame(selfCheckRaf);}R(null,element);controller.destroy();}}}
6
+
7
+ export { fallbackCopy, mount };
@@ -1,5 +1,5 @@
1
1
  import { getServiceOrigin } from './chunk-QFA3K5ZV.js';
2
2
 
3
- var sdkPublicSettings={"project":{"marketingApex":"checktiv.com"},"apps":{"verify":{"subdomain":"verify"},"workspace-embed":{"subdomain":"workspace"}},"services":{"sdk-api":{"subdomain":"sdk-api"},"sdk-cdn":{"subdomain":"sdk"}},"regions":{"us":{"apex":"us.checktiv.com"},"eu":{"apex":"eu.checktiv.com"}}};var PUBLISHABLE_KEY_HEADER="X-Publishable-Key";function dataPlaneHeaders(ctx,token,opts={}){const headers={Authorization:`Bearer ${token}`};if(ctx.publishableKey!==void 0){headers[PUBLISHABLE_KEY_HEADER]=ctx.publishableKey;}if(opts.withJsonBody)headers["content-type"]="application/json";return headers}function resolveSdkApiOrigin(region,_mode,_hostname){return getServiceOrigin(sdkPublicSettings.services["sdk-api"].subdomain,"prod",region,sdkPublicSettings)}function isCanonicalOrigin(value){if(typeof value!=="string"||value.length===0)return false;try{return new URL(value).origin===value}catch{return false}}function resolveApiBaseOrigin(apiBase,region,mode,hostname){if(isCanonicalOrigin(apiBase))return apiBase;return resolveSdkApiOrigin(region)}var SESSIONS_ME_PATH="/sdk/v1/sessions/me";var WORKING_TOKEN_MINT_PATH="/sdk/v1/working-token";var CAPTURE_TOKEN_MINT_PATH="/sdk/v1/idv/capture-token";function stepSubmitPath(_sessionId,stepId){return `${SESSIONS_ME_PATH}/steps/${encodeURIComponent(stepId)}/submit`}var TELEMETRY_PATH="/sdk/v1/telemetry";var SESSIONS_ME_REFRESH_LINK_PATH="/sdk/v1/sessions/me/refresh-link";function shortCodeRefreshPath(code){return `/sdk/v1/short-codes/${encodeURIComponent(code)}/refresh`}function formUploadUrlPath(stepId){return `${SESSIONS_ME_PATH}/steps/${encodeURIComponent(stepId)}/form-upload-url`}
3
+ var sdkPublicSettings={"project":{"marketingApex":"checktiv.com"},"apps":{"verify":{"subdomain":"verify"},"workspace-embed":{"subdomain":"workspace"}},"services":{"sdk-api":{"subdomain":"sdk-api"},"sdk-cdn":{"subdomain":"sdk"}},"regions":{"us":{"apex":"us.checktiv.com"},"eu":{"apex":"eu.checktiv.com"}}};var PUBLISHABLE_KEY_HEADER="X-Publishable-Key";function dataPlaneHeaders(ctx,token,opts={}){const headers={Authorization:`Bearer ${token}`};if(ctx.publishableKey!==void 0){headers[PUBLISHABLE_KEY_HEADER]=ctx.publishableKey;}if(opts.withJsonBody)headers["content-type"]="application/json";return headers}function resolveSdkApiOrigin(region,_mode,_hostname){return getServiceOrigin(sdkPublicSettings.services["sdk-api"].subdomain,"prod",region,sdkPublicSettings)}function isCanonicalOrigin(value){if(typeof value!=="string"||value.length===0)return false;try{return new URL(value).origin===value}catch{return false}}function resolveApiBaseOrigin(apiBase,region,mode,hostname){if(isCanonicalOrigin(apiBase))return apiBase;return resolveSdkApiOrigin(region)}var SESSIONS_ME_PATH="/sdk/v1/sessions/me";var SESSIONS_CROSS_DEVICE_STATUS_PATH=`${SESSIONS_ME_PATH}/cross-device-status`;var WORKING_TOKEN_MINT_PATH="/sdk/v1/working-token";var CAPTURE_TOKEN_MINT_PATH="/sdk/v1/idv/capture-token";function stepSubmitPath(_sessionId,stepId){return `${SESSIONS_ME_PATH}/steps/${encodeURIComponent(stepId)}/submit`}var TELEMETRY_PATH="/sdk/v1/telemetry";var SESSIONS_ME_REFRESH_LINK_PATH="/sdk/v1/sessions/me/refresh-link";function shortCodeRefreshPath(code){return `/sdk/v1/short-codes/${encodeURIComponent(code)}/refresh`}function formUploadUrlPath(stepId){return `${SESSIONS_ME_PATH}/steps/${encodeURIComponent(stepId)}/form-upload-url`}
4
4
 
5
- export { CAPTURE_TOKEN_MINT_PATH, PUBLISHABLE_KEY_HEADER, SESSIONS_ME_PATH, SESSIONS_ME_REFRESH_LINK_PATH, TELEMETRY_PATH, WORKING_TOKEN_MINT_PATH, dataPlaneHeaders, formUploadUrlPath, isCanonicalOrigin, resolveApiBaseOrigin, sdkPublicSettings, shortCodeRefreshPath, stepSubmitPath };
5
+ export { CAPTURE_TOKEN_MINT_PATH, PUBLISHABLE_KEY_HEADER, SESSIONS_CROSS_DEVICE_STATUS_PATH, SESSIONS_ME_PATH, SESSIONS_ME_REFRESH_LINK_PATH, TELEMETRY_PATH, WORKING_TOKEN_MINT_PATH, dataPlaneHeaders, formUploadUrlPath, isCanonicalOrigin, resolveApiBaseOrigin, sdkPublicSettings, shortCodeRefreshPath, stepSubmitPath };