@sekyro/web 0.1.0-rc.7 → 0.1.0-rc.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/LICENSE +25 -16
- package/README.md +3 -5
- package/THIRD-PARTY-NOTICES.txt +154 -0
- package/dist/background-monitor-A7FKJOAG.js +1 -0
- package/dist/capture-session-doc-YBE3UMJJ.js +1 -0
- package/dist/{capture-session-v3-Okq0EQHG.d.ts → capture-session-v3-CQK-G-qX.d.ts} +72 -3
- package/dist/{capture-session-v3-UQU_WjO2.d.cts → capture-session-v3-Dvob-uH2.d.cts} +72 -3
- package/dist/chunk-4RS2YIL4.js +1 -0
- package/dist/chunk-7V2M6Y2W.js +1 -0
- package/dist/chunk-7ZCZY3ZP.js +1 -0
- package/dist/chunk-A3FUGHAH.js +2 -0
- package/dist/chunk-BPE5NSQ2.js +1 -0
- package/dist/chunk-CJHMFPL6.js +1 -0
- package/dist/chunk-DFTCAWMP.js +1 -0
- package/dist/chunk-DK5YPBDQ.js +1 -0
- package/dist/chunk-DQWW4OCK.js +1 -0
- package/dist/chunk-FHJ7HO3M.js +1 -0
- package/dist/chunk-G6LKLN4U.js +1 -0
- package/dist/chunk-GI3UFGRQ.js +1 -0
- package/dist/{chunk-IYUOYINS.js → chunk-LQ7C44JG.js} +1 -1
- package/dist/chunk-M43ET4NJ.js +1 -0
- package/dist/chunk-MXWLCDFX.js +1 -0
- package/dist/chunk-MY6EXEL2.js +1 -0
- package/dist/chunk-O5WKNZ2C.js +1 -0
- package/dist/chunk-OKWG3PVH.js +1 -0
- package/dist/chunk-POIQGEZM.js +1 -0
- package/dist/chunk-RI3E7GBN.js +1 -0
- package/dist/chunk-RNRFHUJA.js +1 -0
- package/dist/chunk-RVHAKRAI.js +1 -0
- package/dist/chunk-SMKCBUJL.js +1 -0
- package/dist/chunk-TDLIXFDT.js +1 -0
- package/dist/chunk-XLN5OT25.js +1 -0
- package/dist/chunk-YDQBVWXG.js +1 -0
- package/dist/chunk-YPG7CB4O.js +1 -0
- package/dist/client/index.cjs +1 -1
- package/dist/client/index.d.cts +13 -3
- package/dist/client/index.d.ts +13 -3
- package/dist/client/index.js +1 -1
- package/dist/core/index.cjs +1 -1
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +1 -1
- package/dist/core/ocr/worker.bundle.js +42 -0
- package/dist/core/ocr/worker.cjs +42 -0
- package/dist/core/ocr/worker.d.cts +84 -0
- package/dist/core/ocr/worker.d.ts +84 -0
- package/dist/core/ocr/worker.js +41 -0
- package/dist/core/v3/detect-worker.cjs +1 -1
- package/dist/core/v3/detect-worker.d.cts +1 -1
- package/dist/core/v3/detect-worker.d.ts +1 -1
- package/dist/core/v3/detect-worker.js +1 -1
- package/dist/create-document-capture-T4APHJMY.js +1 -0
- package/dist/create-portrait-capture-B57GE5FU.js +1 -0
- package/dist/create-verification-C0AVIcVW.d.ts +2787 -0
- package/dist/create-verification-DoFpgzok.d.cts +2787 -0
- package/dist/{detect-worker-CKXHlXx9.d.cts → detect-worker-DclNxkZT.d.cts} +6 -0
- package/dist/{detect-worker-CKXHlXx9.d.ts → detect-worker-DclNxkZT.d.ts} +6 -0
- package/dist/detector-scanic-YCDNLCGV.js +1 -0
- package/dist/icao-gate-D8qm1O2t.d.cts +1655 -0
- package/dist/icao-gate-D8qm1O2t.d.ts +1655 -0
- package/dist/icao-gate-PWBMKRGC.js +1 -0
- package/dist/icao-tuning-4GGVX6B4.js +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +52 -6
- package/dist/index.d.ts +52 -6
- package/dist/index.js +1 -1
- package/dist/internal/index.cjs +1 -1
- package/dist/internal/index.d.cts +345 -308
- package/dist/internal/index.d.ts +345 -308
- package/dist/internal/index.js +1 -1
- package/dist/keyframe-rank-YAJLYJYF.js +1 -0
- package/dist/landmarker-KB7LVXAU.js +1 -0
- package/dist/mrz-band-VYHOTDHY.js +1 -0
- package/dist/plan-runner-UBK4B4CG.js +1 -0
- package/dist/segmenter-USLNBX65.js +1 -0
- package/dist/turnstile-FATNZ4AG.js +1 -0
- package/package.json +22 -4
- package/sbom.cdx.json +8 -8
- package/dist/chunk-B45J4KC3.js +0 -1
- package/dist/chunk-BMA36W2W.js +0 -1
- package/dist/chunk-P7ECRN47.js +0 -1
- package/dist/chunk-YOB4ZTYN.js +0 -1
- package/dist/chunk-YQBK6OIM.js +0 -1
- package/dist/create-verification-C2JhOO6Y.d.cts +0 -533
- package/dist/create-verification-CGazwtAh.d.ts +0 -533
- package/dist/detector-scanic-VQFFXKTL.js +0 -1
- package/dist/hosted-client-kBeq-mnJ.d.cts +0 -602
- package/dist/hosted-client-kBeq-mnJ.d.ts +0 -602
|
@@ -1,602 +0,0 @@
|
|
|
1
|
-
/** Session lifecycle status (spec §4 two-field status/outcome model). */
|
|
2
|
-
type SessionStatus = "created" | "in_progress" | "review_pending" | "completed" | "expired" | "failed";
|
|
3
|
-
/** Terminal verdict, orthogonal to `status`; `null` until terminal/review. */
|
|
4
|
-
type SessionOutcome = "approved" | "review" | "rejected";
|
|
5
|
-
/** Per-check seven-state machine (spec §4.3). */
|
|
6
|
-
type CheckState = "pending" | "input_required" | "processing" | "passed" | "failed" | "review" | "skipped";
|
|
7
|
-
/** The frozen check-type vocabulary (CHECK_TYPES). `phone_otp` joined in Task 13. */
|
|
8
|
-
type CheckType = "liveness" | "face_match" | "doc_ocr" | "population_registry" | "phone_otp";
|
|
9
|
-
type LivenessReason = "no_face" | "media_unreadable" | "clip_too_short" | "spoof_detected" | "review_band" | "liveness_inconclusive" | "mobile_required" | "uncalibrated_capture_channel";
|
|
10
|
-
type PopulationReason = "nni_not_found" | "nni_invalid" | "registry_unavailable" | "result_from_cache" | "nationality_not_allowed" | "underage" | "age_unverifiable" | "name_mismatch" | "birth_date_mismatch" | "nationality_mismatch";
|
|
11
|
-
type FaceMatchReason = "no_face_source" | "no_face_reference" | "low_quality_reference" | "below_threshold" | "review_band" | "match_inconclusive";
|
|
12
|
-
type DocReason = "side_missing" | "mrz_checksum_failed" | "unreadable" | "expired_document" | "authenticity_review" | "document_authenticity" | "registry_mismatch" | "document_nni_mismatch" | "document_type_not_accepted" | "nationality_not_allowed" | "underage" | "age_unverifiable" | "name_mismatch" | "birth_date_mismatch" | "nationality_mismatch" | "document_number_mismatch";
|
|
13
|
-
/**
|
|
14
|
-
* Profile v2 step 3 matching reasons: a field the partner sent at session
|
|
15
|
-
* create (`subject`) differs from the reference identity (document or
|
|
16
|
-
* registry). All four are final. `document_number_mismatch` is `doc_ocr` only.
|
|
17
|
-
*/
|
|
18
|
-
type MatchReason = "name_mismatch" | "birth_date_mismatch" | "nationality_mismatch" | "document_number_mismatch";
|
|
19
|
-
/**
|
|
20
|
-
* Profile v2 step 4 decision-mode reasons (the app decides automatically
|
|
21
|
-
* instead of sending the case to human review). These park the step at
|
|
22
|
-
* `input_required` while attempts remain: `liveness_inconclusive` /
|
|
23
|
-
* `match_inconclusive` (middle score band) and `document_authenticity`
|
|
24
|
-
* (retake the original card). `mobile_required` is kept for compatibility:
|
|
25
|
-
* the backend now answers a non-phone capture with a request-level
|
|
26
|
-
* `409 mobile_required` (continue on a phone; nothing used, not billed).
|
|
27
|
-
*/
|
|
28
|
-
type DecisionReason = "liveness_inconclusive" | "match_inconclusive" | "document_authenticity" | "mobile_required";
|
|
29
|
-
/**
|
|
30
|
-
* phone_otp reasons (Task 13). All transient — the caller fixes them by
|
|
31
|
-
* re-entering / resending: `otp_mismatch` (wrong or missing code),
|
|
32
|
-
* `otp_expired` (code lapsed or no active send), `otp_send_failed` (the OTP
|
|
33
|
-
* service was unreachable / a send returned no token).
|
|
34
|
-
*/
|
|
35
|
-
type PhoneOtpReason = "otp_mismatch" | "otp_expired" | "otp_send_failed";
|
|
36
|
-
/**
|
|
37
|
-
* Any frozen reason code. The backend declares the field `string`, but the
|
|
38
|
-
* taxonomy is frozen (do-not-drift) — the union IS the contract. NB: liveness
|
|
39
|
-
* and face_match both carry `review_band`.
|
|
40
|
-
*/
|
|
41
|
-
type CheckReason = LivenessReason | PopulationReason | FaceMatchReason | DocReason | PhoneOtpReason;
|
|
42
|
-
/**
|
|
43
|
-
* Session-level failure reasons: the session was stopped by a policy gate,
|
|
44
|
-
* not by a failed check. All are terminal (no retry on this session):
|
|
45
|
-
* - `location_not_allowed` / `anonymizer_blocked` (profile v2 step 2): the
|
|
46
|
-
* person's IP location is not allowed, or an anonymizer (VPN / proxy / Tor)
|
|
47
|
-
* was detected while the app blocks them;
|
|
48
|
-
* - `capture_tampered` (step 4): the device reported a tampered capture
|
|
49
|
-
* (virtual camera, hooking, emulator…) while the app blocks it;
|
|
50
|
-
* - `device_velocity_exceeded` (step 4): this device already verified too
|
|
51
|
-
* many different people while the app blocks it;
|
|
52
|
-
* - `device_cooldown` (step 4): this device had too many rejected sessions —
|
|
53
|
-
* {@link HostedSessionView.retryAfter} says when it may try again.
|
|
54
|
-
*/
|
|
55
|
-
type SessionFailureReason = "location_not_allowed" | "anonymizer_blocked" | "capture_tampered" | "device_velocity_exceeded" | "device_cooldown";
|
|
56
|
-
/**
|
|
57
|
-
* The profile-v2 policy reasons a session can end on: the two session-level
|
|
58
|
-
* reasons plus the failed check's policy reasons (`document_type_not_accepted`,
|
|
59
|
-
* `nationality_not_allowed`, `underage`, `age_unverifiable`,
|
|
60
|
-
* `document_nni_mismatch`).
|
|
61
|
-
*/
|
|
62
|
-
type PolicyFailureReason = SessionFailureReason | "document_type_not_accepted" | "nationality_not_allowed" | "underage" | "age_unverifiable" | "document_nni_mismatch";
|
|
63
|
-
/**
|
|
64
|
-
* How the person proves their identity when the app makes the document
|
|
65
|
-
* optional for registry nationals (profile v2 step 3): type their national
|
|
66
|
-
* number (NNI) and skip the document, or photograph their document.
|
|
67
|
-
*/
|
|
68
|
-
type IdentityMethod = "national_number" | "document_photo";
|
|
69
|
-
/**
|
|
70
|
-
* The identity-method choice of a session (`HostedSessionView.methodChoice`).
|
|
71
|
-
* While `available && selected === null` no check can be submitted (409
|
|
72
|
-
* `method_required`): the page asks first and sends the answer with
|
|
73
|
-
* `POST /hosted/method` ({@link HostedClient.selectMethod}).
|
|
74
|
-
*/
|
|
75
|
-
interface MethodChoiceView {
|
|
76
|
-
/** The session offers the choice (the app's document mode is `optional`). */
|
|
77
|
-
available: boolean;
|
|
78
|
-
/** The chosen method, or `null` while the person has not chosen. */
|
|
79
|
-
selected: IdentityMethod | null;
|
|
80
|
-
/** The methods to offer, in display order. */
|
|
81
|
-
options: IdentityMethod[];
|
|
82
|
-
}
|
|
83
|
-
/** A document type the backend reads today (kyc-docs-v2 vocabulary). */
|
|
84
|
-
type AcceptedDocumentType = "carte_identite" | "passport";
|
|
85
|
-
/**
|
|
86
|
-
* phone_otp DISPLAY-SAFE surface (Task 16). The backend stashes the OTP
|
|
87
|
-
* service `verifToken` on the check's persisted outputs (the doc_ocr partial
|
|
88
|
-
* mechanism), but that token is NEVER projected here — only the fields the
|
|
89
|
-
* hosted OTP step renders. `numberSource` (org-authored config) drives the
|
|
90
|
-
* send-phase UI (prefilled display vs entry); the rest appear ONLY once a send
|
|
91
|
-
* has parked the check (`sentToMasked` present ⇒ verify phase).
|
|
92
|
-
*/
|
|
93
|
-
interface HostedOtpView {
|
|
94
|
-
/**
|
|
95
|
-
* Per-step `config.numberSource` — drives the send-phase UI (prefilled
|
|
96
|
-
* display vs entry). Narrowed to the frontend contract; the backend field is
|
|
97
|
-
* `string` (dynamic config) but the projection only ever emits these three.
|
|
98
|
-
*/
|
|
99
|
-
numberSource?: "prefilled" | "user_entered" | "prefilled_or_entered";
|
|
100
|
-
/** Masked target the last send went to (e.g. `+222 ** ** 34 56`); absent pre-send. */
|
|
101
|
-
sentToMasked?: string;
|
|
102
|
-
/** Delivery channel of the last send. */
|
|
103
|
-
channel?: "sms" | "whatsapp";
|
|
104
|
-
/** ISO-8601 OTP expiry from the last send — drives the verify-phase countdown. */
|
|
105
|
-
expiresAt?: string;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Per-check projection in a {@link HostedSessionView} — the spec'd hosted step
|
|
109
|
-
* shape. NEVER carries `calibratedScore` or the raw check `outputs`; the only
|
|
110
|
-
* output-derived data is the phone_otp `HostedOtpView` display subset
|
|
111
|
-
* (masked number/channel/expiry — never the verifToken).
|
|
112
|
-
*/
|
|
113
|
-
interface HostedStepView {
|
|
114
|
-
checkType: CheckType;
|
|
115
|
-
state: CheckState;
|
|
116
|
-
/** Frozen-taxonomy reason code explaining a `failed`/`review` state. */
|
|
117
|
-
reason?: CheckReason;
|
|
118
|
-
/**
|
|
119
|
-
* Submissions the page may still make for this check (`max(0, cap - attempts)`).
|
|
120
|
-
* Meaningful only while the check is executable — a finalized check may still
|
|
121
|
-
* report more than 0, but re-submitting it 409s regardless.
|
|
122
|
-
*/
|
|
123
|
-
attemptsRemaining: number;
|
|
124
|
-
/** doc_ocr only: sides already accepted into the partial accumulator (['recto'] or ['verso']). */
|
|
125
|
-
acceptedSides?: ("recto" | "verso")[];
|
|
126
|
-
/** phone_otp only: the display-safe OTP send/config surface (never the verifToken). */
|
|
127
|
-
otp?: HostedOtpView;
|
|
128
|
-
/**
|
|
129
|
-
* The check failed after using all of its attempts — no retry is left.
|
|
130
|
-
* Absent on older APIs (treat absent as `false`).
|
|
131
|
-
*/
|
|
132
|
-
attemptsExhausted?: boolean;
|
|
133
|
-
/**
|
|
134
|
-
* population_registry only: the session is not bound to an NNI, but the
|
|
135
|
-
* document step already read a valid one — the page submits the registry
|
|
136
|
-
* check with an EMPTY input (no NNI field) and the backend uses the
|
|
137
|
-
* document's number. Absent on older APIs.
|
|
138
|
-
*/
|
|
139
|
-
nniFromDocument?: boolean;
|
|
140
|
-
/**
|
|
141
|
-
* liveness / face_match (profile v2 step 4, decision mode `automatic`): the
|
|
142
|
-
* capture must come from a phone — the liveness band is calibrated on
|
|
143
|
-
* mobile captures only. A desktop page hands the person off to their phone
|
|
144
|
-
* instead of capturing (a desktop submission answers `mobile_required`).
|
|
145
|
-
* Absent on older APIs and in `review` mode.
|
|
146
|
-
*/
|
|
147
|
-
requiresMobile?: boolean;
|
|
148
|
-
}
|
|
149
|
-
/** A locale the Sekyro AI-hosted voice clips are recorded in. */
|
|
150
|
-
type HostedVoiceLocale = "ar" | "fr" | "en";
|
|
151
|
-
/**
|
|
152
|
-
* The session's Sekyro AI-hosted voice-guidance clips (the active clip set).
|
|
153
|
-
*
|
|
154
|
-
* `clips[locale]` maps a voice key (`fcv3.*`, the `@sekyro/react` voice-key
|
|
155
|
-
* namespace) to an ABSOLUTE URL on the Sekyro AI assets host
|
|
156
|
-
* (`https://assets.sekyro.ai/voice/<setId>/<locale>/<name>.mp3`; staging:
|
|
157
|
-
* `assets-staging.sekyro.ai`). URLs are immutable per `setId`. A locale or key
|
|
158
|
-
* may be missing — the player falls back to the device voice for it.
|
|
159
|
-
*
|
|
160
|
-
* A page with a Content-Security-Policy must allow the assets origin in
|
|
161
|
-
* `media-src` for the clips to play (see the partner web-SDK guide, CSP note).
|
|
162
|
-
*/
|
|
163
|
-
interface HostedVoiceView {
|
|
164
|
-
/** Identifier of the active clip set (part of every clip URL). */
|
|
165
|
-
setId: string;
|
|
166
|
-
/** Per-locale map of voice key (`fcv3.*`) → absolute clip URL. */
|
|
167
|
-
clips: {
|
|
168
|
-
readonly [L in HostedVoiceLocale]?: Readonly<Record<string, string>>;
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
/** A branding colour key (each value is `#rrggbb`). */
|
|
172
|
-
type HostedBrandingColorKey = "brand" | "brandFg" | "bg" | "surface" | "fg" | "fgMuted" | "danger" | "success" | "warning";
|
|
173
|
-
/**
|
|
174
|
-
* The org / app branding of a session (`HostedSessionView.branding`): only the
|
|
175
|
-
* fields set in the dashboard, merged per field (app over org). A field the
|
|
176
|
-
* org and app left unset is ABSENT — keep your default for it; the whole
|
|
177
|
-
* object is absent when nothing is set. `logoUrl` is a short-lived signed URL
|
|
178
|
-
* (15 minutes).
|
|
179
|
-
*/
|
|
180
|
-
interface HostedBranding {
|
|
181
|
-
/** Signed URL of the logo (PNG or sanitized SVG); absent when none is set. */
|
|
182
|
-
logoUrl?: string;
|
|
183
|
-
/** Colours as `#rrggbb`. */
|
|
184
|
-
colors?: Partial<Record<HostedBrandingColorKey, string>>;
|
|
185
|
-
/** Corner radius step. */
|
|
186
|
-
radius?: "none" | "sm" | "md" | "lg" | "full";
|
|
187
|
-
/** Font choice (system fallbacks when the font is not installed). */
|
|
188
|
-
fontFamily?: "system" | "inter" | "ibm-plex-sans-arabic" | "noto-sans-arabic" | "roboto";
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Token-addressed hosted-page bootstrap (`GET /hosted/session`). A separate
|
|
192
|
-
* shape from the partner `SessionView`: `sessionId` instead of `id`,
|
|
193
|
-
* hosted step hints, the consent flag, and the org display name (may be `''`
|
|
194
|
-
* when the org lookup degrades).
|
|
195
|
-
*/
|
|
196
|
-
interface HostedSessionView {
|
|
197
|
-
sessionId: string;
|
|
198
|
-
status: SessionStatus;
|
|
199
|
-
outcome: SessionOutcome | null;
|
|
200
|
-
steps: HostedStepView[];
|
|
201
|
-
/** ISO-8601 timestamp (Date on the server, string on the wire). */
|
|
202
|
-
expiresAt: string;
|
|
203
|
-
consentRecorded: boolean;
|
|
204
|
-
orgName: string;
|
|
205
|
-
/**
|
|
206
|
-
* The FIRST allowlisted web-SDK origin of the owning org (Task 12), or null
|
|
207
|
-
* when none is registered. The hosted page posts the SDK popup postMessage
|
|
208
|
-
* events (event name + sessionId ONLY) to exactly this origin — never `'*'`.
|
|
209
|
-
* The backend declares it required (`string | null`); optional here so
|
|
210
|
-
* pre-Task-12 consumers/fixtures stay valid (additive field, always on the
|
|
211
|
-
* wire from Task 12 onward).
|
|
212
|
-
*/
|
|
213
|
-
sdkOrigin?: string | null;
|
|
214
|
-
/**
|
|
215
|
-
* Cloudflare Turnstile site key the browser must solve an execute-mode
|
|
216
|
-
* challenge against before submitting `liveness` (Plan A Task 5): the org's
|
|
217
|
-
* own widget key when the request origin is one of the org's allowlisted SDK
|
|
218
|
-
* origins, else the hosted widget key, else `null`. `null` means the session
|
|
219
|
-
* cannot be attested from the browser — the SDK sends `{sandbox: true}`,
|
|
220
|
-
* which the backend honours ONLY on sandbox sessions (fails closed on live).
|
|
221
|
-
*/
|
|
222
|
-
turnstileSiteKey: string | null;
|
|
223
|
-
/**
|
|
224
|
-
* The session was minted with a server-bound NNI (`POST /sessions`
|
|
225
|
-
* `input.nni`, Plan A Task 2): `population_registry` is submitted with an
|
|
226
|
-
* EMPTY input and the backend reads the sealed value. `false` means the
|
|
227
|
-
* person must supply the NNI (hosted population form); the SDK never submits
|
|
228
|
-
* the registry check on an unbound session. The VALUE is never exposed. The
|
|
229
|
-
* backend declares it required; optional here so pre-Task-8 fixtures stay
|
|
230
|
-
* valid (additive field, always on the wire from Task 8 onward).
|
|
231
|
-
*/
|
|
232
|
-
nniBound?: boolean;
|
|
233
|
-
/**
|
|
234
|
-
* The Sekyro AI-hosted voice-guidance clips of this session, or `null` when no
|
|
235
|
-
* clip set is active (the device voice is used). Optional: older APIs omit
|
|
236
|
-
* the field — treat absent like `null`.
|
|
237
|
-
*/
|
|
238
|
-
voice?: HostedVoiceView | null;
|
|
239
|
-
/**
|
|
240
|
-
* Why the session ended, when a profile-v2 policy stopped it: a
|
|
241
|
-
* {@link SessionFailureReason}, or the failed check's reason when it is a
|
|
242
|
-
* policy reason (eligibility, or `document_nni_mismatch`). Absent otherwise
|
|
243
|
-
* (and on older APIs).
|
|
244
|
-
*/
|
|
245
|
-
failureReason?: PolicyFailureReason;
|
|
246
|
-
/**
|
|
247
|
-
* The document types the person may pick (resolved for issuer `MR`). Absent
|
|
248
|
-
* on older APIs — treat absent as every type (`carte_identite`, `passport`).
|
|
249
|
-
*/
|
|
250
|
-
acceptedDocumentTypes?: AcceptedDocumentType[];
|
|
251
|
-
/**
|
|
252
|
-
* The identity-method choice (profile v2 step 3). Absent when the session
|
|
253
|
-
* has no choice (and on older APIs). While `available && selected === null`
|
|
254
|
-
* every check submission answers 409 `method_required`.
|
|
255
|
-
*/
|
|
256
|
-
methodChoice?: MethodChoiceView;
|
|
257
|
-
/**
|
|
258
|
-
* ISO-8601 time from which this device may verify again — set with
|
|
259
|
-
* `failureReason: 'device_cooldown'` (profile v2 step 4). Absent otherwise
|
|
260
|
-
* (and on older APIs).
|
|
261
|
-
*/
|
|
262
|
-
retryAfter?: string;
|
|
263
|
-
/**
|
|
264
|
-
* The org / app branding (settings spec §5.1). Absent on older APIs — keep
|
|
265
|
-
* the default theme. Map it with `brandingToTheme()` from `@sekyro/react`.
|
|
266
|
-
*/
|
|
267
|
-
branding?: HostedBranding;
|
|
268
|
-
}
|
|
269
|
-
/** `POST /hosted/consent` result — 201 on first record, 200 `{alreadyRecorded: true}` on replay. */
|
|
270
|
-
interface RecordConsentResult {
|
|
271
|
-
alreadyRecorded: boolean;
|
|
272
|
-
}
|
|
273
|
-
/** Consent locale — the page's `[locale]` URL segment echoed back (HostedConsentSchema picklist). */
|
|
274
|
-
type ConsentLocale = "ar" | "fr" | "en";
|
|
275
|
-
/** Per-check projection in a {@link SessionView} — enum/id only, never civil data. */
|
|
276
|
-
interface SessionStepView {
|
|
277
|
-
checkType: CheckType;
|
|
278
|
-
state: CheckState;
|
|
279
|
-
reason?: CheckReason;
|
|
280
|
-
calibratedScore?: number;
|
|
281
|
-
/** The check failed after using all of its attempts. Absent on older APIs. */
|
|
282
|
-
attemptsExhausted?: boolean;
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Client-facing session projection returned by
|
|
286
|
-
* `POST /sessions/:id/checks/:checkType`. Whitelist-only — never the client token.
|
|
287
|
-
*/
|
|
288
|
-
interface SessionView {
|
|
289
|
-
id: string;
|
|
290
|
-
status: SessionStatus;
|
|
291
|
-
outcome: SessionOutcome | null;
|
|
292
|
-
/** Profile-v2 policy stop reason; absent on ordinary failures and older APIs. */
|
|
293
|
-
failureReason?: PolicyFailureReason;
|
|
294
|
-
steps: SessionStepView[];
|
|
295
|
-
/** ISO-8601 timestamp (Date on the server, string on the wire). */
|
|
296
|
-
expiresAt: string;
|
|
297
|
-
/** ISO-8601 timestamp (Date on the server, string on the wire). */
|
|
298
|
-
createdAt?: string;
|
|
299
|
-
}
|
|
300
|
-
/** Media class — selects size cap, MIME allowlist and promoted prefix (media.policy.ts). */
|
|
301
|
-
type MediaKind = "image" | "clip";
|
|
302
|
-
/**
|
|
303
|
-
* Body of `POST /sessions/:id/media`. `contentType`/`contentLength` are the
|
|
304
|
-
* exact values SIGNED into the presigned PUT — the PUT must send them verbatim.
|
|
305
|
-
* Allowlists (media.policy.ts): image → image/jpeg | image/png (5 MB cap);
|
|
306
|
-
* clip → video/webm | video/mp4 (15 MB cap). BARE types only — no `;codecs=` params.
|
|
307
|
-
*/
|
|
308
|
-
interface PresignRequest {
|
|
309
|
-
kind: MediaKind;
|
|
310
|
-
contentType: string;
|
|
311
|
-
contentLength: number;
|
|
312
|
-
}
|
|
313
|
-
/** Result of a presign — the presigned PUT URL plus the pending object key. */
|
|
314
|
-
interface PresignUploadResult {
|
|
315
|
-
key: string;
|
|
316
|
-
uploadUrl: string;
|
|
317
|
-
/** Presign TTL in seconds (900 = 15 min). */
|
|
318
|
-
expiresIn: number;
|
|
319
|
-
}
|
|
320
|
-
/** Result of `POST /sessions/:id/media/complete` — the PROMOTED (class-prefixed) key. */
|
|
321
|
-
interface CompleteMediaResult {
|
|
322
|
-
ready: true;
|
|
323
|
-
/** e.g. `clips/{sessionId}/{uuid}` or `doc-images/{sessionId}/{uuid}` — submit THIS key, not the pending one. */
|
|
324
|
-
key: string;
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Liveness attestation bag (attestation-verifier.service.ts). The web SDK sends
|
|
328
|
-
* `{channel: 'hosted_web', siteKey, turnstileToken}` — `siteKey` echoes the
|
|
329
|
-
* `HostedSessionView.turnstileSiteKey` the challenge was rendered with, so the
|
|
330
|
-
* backend picks the matching widget secret deterministically (Turnstile tokens
|
|
331
|
-
* are single-use: siteverify runs exactly once, never "org then global").
|
|
332
|
-
* `sandbox: true` is honored only on sandbox sessions; `signature` is the
|
|
333
|
-
* future native-SDK channel.
|
|
334
|
-
*/
|
|
335
|
-
interface AttestationInput {
|
|
336
|
-
sandbox?: boolean;
|
|
337
|
-
signature?: string;
|
|
338
|
-
channel?: "hosted_web";
|
|
339
|
-
turnstileToken?: string;
|
|
340
|
-
/** The Turnstile site key the token was minted with (selects the verifying secret). */
|
|
341
|
-
siteKey?: string;
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* liveness executor input: a promoted `clips/…` key + optional attestation.
|
|
345
|
-
* `faceMatch` (v2 latency §3.2) carries the already-promoted `doc-images/…`
|
|
346
|
-
* keyframe so the backend can run face_match IN THE SAME submission when its
|
|
347
|
-
* bundle flag is on and `face_match` is the next pending step. Backends that
|
|
348
|
-
* do not bundle ignore it (the input bag is an open record) — the SDK then
|
|
349
|
-
* submits `face_match` itself with the same key (see liveness-flow.ts).
|
|
350
|
-
*/
|
|
351
|
-
interface LivenessInput {
|
|
352
|
-
clipKey: string;
|
|
353
|
-
attestation?: AttestationInput;
|
|
354
|
-
/** Declared capture channel — the liveness band is mobile-calibrated, so the
|
|
355
|
-
* backend clamps non-mobile verdicts to review (uncalibrated_capture_channel).
|
|
356
|
-
* Client-declared by design (not a security boundary); absent = legacy
|
|
357
|
-
* clients, treated as mobile server-side during the rollout window. */
|
|
358
|
-
captureChannel?: 'mobile' | 'desktop';
|
|
359
|
-
/** Capture metadata (engine, dimensions, clip length, face-capture timing)
|
|
360
|
-
* — the backend's allowlisted, non-PII `capture` block (session insights). */
|
|
361
|
-
capture?: LivenessCaptureInput;
|
|
362
|
-
/** The promoted face_match probe key, for a bundled liveness + face_match run. */
|
|
363
|
-
faceMatch?: {
|
|
364
|
-
imageKey: string;
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
/** `LivenessInput.capture`: what the SDK's `captured` event measured. All ms are whole, ≥ 0. */
|
|
368
|
-
interface LivenessCaptureInput {
|
|
369
|
-
engine?: 'v1' | 'v3';
|
|
370
|
-
width?: number;
|
|
371
|
-
height?: number;
|
|
372
|
-
clipMs?: number;
|
|
373
|
-
cameraReadyMs?: number;
|
|
374
|
-
faceAcquireMs?: number;
|
|
375
|
-
captureMs?: number;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* population_registry adapter input. `nni` is the 10-digit NNI for an UNBOUND
|
|
379
|
-
* session; a session minted with a server-side `input.nni` is BOUND to it
|
|
380
|
-
* (Plan A Task 2) — the browser submits `{}` and the backend reads the sealed
|
|
381
|
-
* value. Sending a DIFFERENT nni on a bound session answers 409 `nni_locked`.
|
|
382
|
-
*/
|
|
383
|
-
interface PopulationInput {
|
|
384
|
-
nni?: string;
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* face_match executor input: a promoted `doc-images/…` key (the source selfie frame).
|
|
388
|
-
* The same key may already have ridden along as {@link LivenessInput.faceMatch}.
|
|
389
|
-
*/
|
|
390
|
-
interface FaceMatchInput {
|
|
391
|
-
imageKey: string;
|
|
392
|
-
}
|
|
393
|
-
/** Document side (docs.types.ts DocSide). */
|
|
394
|
-
type DocSide = "recto" | "verso" | "single";
|
|
395
|
-
/** doc_ocr executor input: a promoted `doc-images/…` key + which side it shows. */
|
|
396
|
-
interface DocOcrInput {
|
|
397
|
-
imageKey: string;
|
|
398
|
-
side: DocSide;
|
|
399
|
-
}
|
|
400
|
-
/**
|
|
401
|
-
* phone_otp executor input (Task 13): a two-phase check. `send` dispatches (or
|
|
402
|
-
* resends) an OTP — resolving the number from the trusted server-side prefill
|
|
403
|
-
* or the user-entered `phone` per the step's `numberSource`; `verify` checks
|
|
404
|
-
* the entered `code` against the parked token. `phone` is IGNORED for a
|
|
405
|
-
* `prefilled` step (a client number is never trusted as "prefilled").
|
|
406
|
-
*/
|
|
407
|
-
interface PhoneOtpInput {
|
|
408
|
-
/** Phase selector: `send` dispatches/resends, `verify` checks the code. Defaults to `send`. */
|
|
409
|
-
action: "send" | "verify";
|
|
410
|
-
/** USER-entered E.164 number (`user_entered` / `prefilled_or_entered` sends only). */
|
|
411
|
-
phone?: string;
|
|
412
|
-
/** The code the user typed — `verify` only. */
|
|
413
|
-
code?: string;
|
|
414
|
-
/** Delivery channel override for `send` (default `sms`). */
|
|
415
|
-
channel?: "sms" | "whatsapp";
|
|
416
|
-
/** OTP message locale override for `send`. */
|
|
417
|
-
locale?: "ar" | "fr" | "en";
|
|
418
|
-
}
|
|
419
|
-
/** Per-check-type submission input shapes, keyed by the frozen vocabulary. */
|
|
420
|
-
interface CheckInputByType {
|
|
421
|
-
liveness: LivenessInput;
|
|
422
|
-
face_match: FaceMatchInput;
|
|
423
|
-
doc_ocr: DocOcrInput;
|
|
424
|
-
population_registry: PopulationInput;
|
|
425
|
-
phone_otp: PhoneOtpInput;
|
|
426
|
-
}
|
|
427
|
-
/**
|
|
428
|
-
* Body of `POST /sessions/:id/checks/:checkType` (SubmitCheckSchema).
|
|
429
|
-
* `forceOutcome` is SANDBOX-ONLY (plan D-C) — a live session rejects it with
|
|
430
|
-
* 403 `force_outcome_forbidden`.
|
|
431
|
-
*/
|
|
432
|
-
interface SubmitCheckBody {
|
|
433
|
-
input?: Record<string, unknown>;
|
|
434
|
-
forceOutcome?: "pass" | "fail";
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Strip MIME parameters: `video/webm;codecs=vp8,opus` → `video/webm`.
|
|
439
|
-
*
|
|
440
|
-
* The capture engine (Task 4) emits `clipMimeType` WITH codec parameters, but
|
|
441
|
-
* the presign allowlist holds BARE types only (['video/webm','video/mp4'] /
|
|
442
|
-
* ['image/jpeg','image/png']) and the presigned PUT signs the exact declared
|
|
443
|
-
* Content-Type. Exported so pages can normalize once and stay byte-consistent
|
|
444
|
-
* between presign and PUT.
|
|
445
|
-
*/
|
|
446
|
-
declare function stripMimeParams(contentType: string): string;
|
|
447
|
-
/** Media-bearing check types → the input field the promoted key goes into. */
|
|
448
|
-
declare const MEDIA_INPUT_FIELD: {
|
|
449
|
-
readonly liveness: "clipKey";
|
|
450
|
-
readonly face_match: "imageKey";
|
|
451
|
-
readonly doc_ocr: "imageKey";
|
|
452
|
-
};
|
|
453
|
-
/** Check types that take an uploaded media key (population_registry does not). */
|
|
454
|
-
type MediaCheckType = keyof typeof MEDIA_INPUT_FIELD;
|
|
455
|
-
interface SubmitOptions {
|
|
456
|
-
/**
|
|
457
|
-
* Sent as `x-idempotency-key` (the header IdempotencyInterceptor reads).
|
|
458
|
-
* One key per LOGICAL submit — a flaky-network retry with the same key
|
|
459
|
-
* replays the first response without burning another attempt.
|
|
460
|
-
*/
|
|
461
|
-
idempotencyKey?: string;
|
|
462
|
-
/** SANDBOX-ONLY deterministic override (plan D-C); a live session 403s it. */
|
|
463
|
-
forceOutcome?: "pass" | "fail";
|
|
464
|
-
}
|
|
465
|
-
interface UploadMedia {
|
|
466
|
-
kind: MediaKind;
|
|
467
|
-
blob: Blob;
|
|
468
|
-
/** May carry codec params (engine `clipMimeType`) — stripped before presign AND PUT. */
|
|
469
|
-
contentType: string;
|
|
470
|
-
}
|
|
471
|
-
interface HostedClientOptions {
|
|
472
|
-
/** API origin, e.g. `https://api.sekyro.ai` — paths are `${apiOrigin}/api/v2/...`. */
|
|
473
|
-
apiOrigin: string;
|
|
474
|
-
/** The raw session token from the hosted URL (short code; legacy `cst_` during its TTL) — sent as `x-session-token` on every API call. */
|
|
475
|
-
sessionToken: string;
|
|
476
|
-
/** Injection seam (tests / non-window contexts). Defaults to `globalThis.fetch`. */
|
|
477
|
-
fetch?: typeof globalThis.fetch;
|
|
478
|
-
/** Per-request timeout for API calls (NOT the Spaces PUT). Default 30 000 ms. */
|
|
479
|
-
requestTimeoutMs?: number;
|
|
480
|
-
/**
|
|
481
|
-
* Tuning for the ONLY automatic retry the client performs: 409
|
|
482
|
-
* `idempotency_in_progress` (a concurrent identical request is mid-flight
|
|
483
|
-
* server-side; the real response lands once it finishes). `attempts` counts
|
|
484
|
-
* retries AFTER the first try. Defaults: 5 × 400 ms.
|
|
485
|
-
*/
|
|
486
|
-
inProgressRetry?: {
|
|
487
|
-
attempts?: number;
|
|
488
|
-
delayMs?: number;
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* Hand-authored typed client for the five session-token endpoints:
|
|
493
|
-
*
|
|
494
|
-
* GET /api/v2/hosted/session → {@link getSession}
|
|
495
|
-
* POST /api/v2/hosted/consent → {@link recordConsent}
|
|
496
|
-
* POST /api/v2/hosted/method → {@link selectMethod}
|
|
497
|
-
* POST /api/v2/sessions/:id/media → {@link presign}
|
|
498
|
-
* POST /api/v2/sessions/:id/media/complete → {@link completeMedia}
|
|
499
|
-
* POST /api/v2/sessions/:id/checks/:checkType → {@link submitCheck}
|
|
500
|
-
*
|
|
501
|
-
* plus the bare presigned Spaces PUT ({@link uploadToSpaces}) and the
|
|
502
|
-
* presign→PUT→complete→submit composition ({@link uploadAndSubmit}).
|
|
503
|
-
*
|
|
504
|
-
* Envelopes (verified against sessions-docs.e2e-spec.ts):
|
|
505
|
-
* - success: `{success: true, data}` — unwrapped here, methods return the payload;
|
|
506
|
-
* - error: flat `{code, message}` → thrown as {@link HostedApiError}.
|
|
507
|
-
*
|
|
508
|
-
* The media/checks routes are `:id`-addressed while the token itself is the
|
|
509
|
-
* only credential the page starts with — the client learns its sessionId from
|
|
510
|
-
* `GET /hosted/session` (token-addressed) and lazily bootstraps it when a
|
|
511
|
-
* `:id` route is called first.
|
|
512
|
-
*
|
|
513
|
-
* No automatic retry EXCEPT bounded short-delay retry on 409
|
|
514
|
-
* `idempotency_in_progress`. Everything else — including 429 with its parsed
|
|
515
|
-
* `retryAfterSeconds` — is surfaced to the page to handle.
|
|
516
|
-
*/
|
|
517
|
-
declare class HostedClient {
|
|
518
|
-
private readonly apiOrigin;
|
|
519
|
-
private readonly sessionToken;
|
|
520
|
-
private readonly fetchImpl;
|
|
521
|
-
private readonly requestTimeoutMs;
|
|
522
|
-
private readonly retryAttempts;
|
|
523
|
-
private readonly retryDelayMs;
|
|
524
|
-
private sessionId;
|
|
525
|
-
private bootstrap;
|
|
526
|
-
constructor(opts: HostedClientOptions);
|
|
527
|
-
/** Token-addressed bootstrap — the hosted page's first call. Caches the sessionId. */
|
|
528
|
-
getSession(): Promise<HostedSessionView>;
|
|
529
|
-
/**
|
|
530
|
-
* Record consent once (201; an idempotent replay answers 200 with
|
|
531
|
-
* `alreadyRecorded: true`). Until recorded, media presign/complete AND check
|
|
532
|
-
* submission answer 409 `consent_required`.
|
|
533
|
-
*/
|
|
534
|
-
recordConsent(locale: ConsentLocale): Promise<RecordConsentResult>;
|
|
535
|
-
/**
|
|
536
|
-
* Send the person's identity method (profile v2 step 3) when the view offers
|
|
537
|
-
* a choice (`methodChoice.available`). Returns the updated hosted view —
|
|
538
|
-
* continue from it. 409 `method_locked` when the method can no longer
|
|
539
|
-
* change (a check of the chosen method was already submitted).
|
|
540
|
-
*/
|
|
541
|
-
selectMethod(method: IdentityMethod): Promise<HostedSessionView>;
|
|
542
|
-
/**
|
|
543
|
-
* Presign a Spaces PUT for a new pending object. `contentType` is stripped of
|
|
544
|
-
* MIME parameters defensively (the allowlist holds bare types; the engine's
|
|
545
|
-
* `clipMimeType` carries codec params) — PUT with the SAME bare type, or the
|
|
546
|
-
* signed-header check rejects the upload.
|
|
547
|
-
*/
|
|
548
|
-
presign(kind: MediaKind, contentType: string, contentLength: number): Promise<PresignUploadResult>;
|
|
549
|
-
/**
|
|
550
|
-
* Bare PUT to the presigned Spaces URL: EXACTLY the signed headers — the
|
|
551
|
-
* declared Content-Type and the blob body. NO `x-session-token` (the
|
|
552
|
-
* signature IS the credential; an extra header breaks nothing but leaks the
|
|
553
|
-
* token to a third-party host) and no JSON envelope.
|
|
554
|
-
*
|
|
555
|
-
* `contentType` is param-stripped here too (idempotent for bare types): the
|
|
556
|
-
* presign strips internally, so a caller composing manually with the engine's
|
|
557
|
-
* parameterful `clipMimeType` would otherwise sign `video/webm` but PUT
|
|
558
|
-
* `video/webm;codecs=…` — a signed-header mismatch S3 rejects at runtime.
|
|
559
|
-
*
|
|
560
|
-
* Timeout: 15 min (`AbortSignal.timeout(900_000)`, matching the presign TTL)
|
|
561
|
-
* rather than the API calls' 30 s — a 15 MB clip on a slow link legitimately
|
|
562
|
-
* exceeds 30 s, but a stalled in-flight socket must still be bounded (the TTL
|
|
563
|
-
* alone only bounds when a PUT can START).
|
|
564
|
-
*
|
|
565
|
-
* Failures are ALWAYS typed: non-2xx throws {@link HostedApiError} with the
|
|
566
|
-
* client-synthesized `upload_failed` (message carries a truncated S3 body
|
|
567
|
-
* snippet — e.g. SignatureDoesNotMatch); a mid-transfer drop → `network_error`;
|
|
568
|
-
* the timeout → `timeout`.
|
|
569
|
-
*/
|
|
570
|
-
uploadToSpaces(uploadUrl: string, blob: Blob, contentType: string): Promise<void>;
|
|
571
|
-
/** Finalize an upload: the backend sniffs + promotes; returns the PROMOTED key to submit. */
|
|
572
|
-
completeMedia(key: string): Promise<CompleteMediaResult>;
|
|
573
|
-
/**
|
|
574
|
-
* Submit one check. Sends `{input, forceOutcome?}` (SubmitCheckSchema) and the
|
|
575
|
-
* optional `x-idempotency-key` header. Returns the whitelisted SessionView.
|
|
576
|
-
*/
|
|
577
|
-
submitCheck<T extends CheckType>(checkType: T, input: CheckInputByType[T], opts?: SubmitOptions): Promise<SessionView>;
|
|
578
|
-
/**
|
|
579
|
-
* Convenience composition: presign → PUT → complete → submit, passing the
|
|
580
|
-
* PROMOTED key (from complete's response — never the pending presign key)
|
|
581
|
-
* into the check's media input field (`clipKey` for liveness, `imageKey` for
|
|
582
|
-
* face_match/doc_ocr). `extraInput` carries the remaining input fields
|
|
583
|
-
* (liveness `attestation`, doc_ocr `side`). The media content type is
|
|
584
|
-
* param-stripped ONCE and used for both presign and PUT, so the signed
|
|
585
|
-
* header always matches.
|
|
586
|
-
*/
|
|
587
|
-
uploadAndSubmit<T extends MediaCheckType>(checkType: T, media: UploadMedia, extraInput: Omit<CheckInputByType[T], (typeof MEDIA_INPUT_FIELD)[T]>, opts?: SubmitOptions): Promise<SessionView>;
|
|
588
|
-
/** The token's own sessionId — cached from getSession(), lazily bootstrapped. */
|
|
589
|
-
private ensureSessionId;
|
|
590
|
-
/**
|
|
591
|
-
* One API request: `${apiOrigin}/api/v2${path}`, `x-session-token` always,
|
|
592
|
-
* AbortSignal timeout (30 s default), `{success, data}` unwrap on 2xx, flat
|
|
593
|
-
* `{code, message}` → {@link HostedApiError} on non-2xx. EVERY failure is
|
|
594
|
-
* typed: a rejected fetch → `network_error`, the timeout → `timeout`, an
|
|
595
|
-
* unparseable 2xx body → `unknown_error` — the page never sees a raw
|
|
596
|
-
* TypeError/DOMException. The ONLY automatic retry is 409
|
|
597
|
-
* `idempotency_in_progress` (bounded, short delay).
|
|
598
|
-
*/
|
|
599
|
-
private api;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
export { type AcceptedDocumentType as A, type MediaCheckType as B, type CheckReason as C, type DecisionReason as D, type MediaKind as E, type FaceMatchReason as F, type PhoneOtpInput as G, type HostedBranding as H, type IdentityMethod as I, type PopulationInput as J, type PresignRequest as K, type LivenessReason as L, type MatchReason as M, type PresignUploadResult as N, type SessionStepView as O, type PhoneOtpReason as P, type SubmitCheckBody as Q, type RecordConsentResult as R, type SessionFailureReason as S, type SubmitOptions as T, type UploadMedia as U, stripMimeParams as V, type CheckState as a, type CheckType as b, type DocReason as c, type HostedBrandingColorKey as d, type HostedOtpView as e, type HostedSessionView as f, type HostedStepView as g, type HostedVoiceLocale as h, type HostedVoiceView as i, type MethodChoiceView as j, type PolicyFailureReason as k, type PopulationReason as l, type SessionOutcome as m, type SessionStatus as n, HostedClient as o, type AttestationInput as p, type SessionView as q, type CheckInputByType as r, type CompleteMediaResult as s, type ConsentLocale as t, type DocOcrInput as u, type DocSide as v, type FaceMatchInput as w, type HostedClientOptions as x, type LivenessCaptureInput as y, type LivenessInput as z };
|