@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,533 +0,0 @@
|
|
|
1
|
-
import { b as Detector } from './detect-worker-CKXHlXx9.cjs';
|
|
2
|
-
import { i as CaptureState$1, f as CaptureSessionV3Events, g as CaptureSessionV3Options, c as CaptureErrorKind$1 } from './capture-session-v3-UQU_WjO2.cjs';
|
|
3
|
-
import { C as CheckReason, S as SessionFailureReason, j as MethodChoiceView, I as IdentityMethod, i as HostedVoiceView, f as HostedSessionView, o as HostedClient, p as AttestationInput, q as SessionView, b as CheckType } from './hosted-client-kBeq-mnJ.cjs';
|
|
4
|
-
|
|
5
|
-
/** Gate guidance code. `'hold'` is emitted while the clip records. */
|
|
6
|
-
type GateHint = "center" | "closer" | "farther" | "light" | "still" | "hold";
|
|
7
|
-
/**
|
|
8
|
-
* Capture + verification state, as seen by the partner:
|
|
9
|
-
* - `idle → starting → gating → recording → captured` is the engine's run;
|
|
10
|
-
* - `uploading → checking → done` follows ONLY when the handle was obtained via
|
|
11
|
-
* {@link Verification.liveness} (the SDK uploads and submits after `captured`);
|
|
12
|
-
* - `error` on a camera / engine failure (see {@link CaptureError}).
|
|
13
|
-
*/
|
|
14
|
-
type CaptureState = "idle" | "starting" | "gating" | "recording" | "captured" | "uploading" | "checking" | "done" | "error";
|
|
15
|
-
/** Declared capture channel — the liveness band is mobile-calibrated. */
|
|
16
|
-
type CaptureChannel = "mobile" | "desktop";
|
|
17
|
-
/** Gate ring update: integrator progress 0..1 and the current guidance code. */
|
|
18
|
-
interface GateUpdate {
|
|
19
|
-
/** Gate integrator 0..1 — drive the ring off this directly. */
|
|
20
|
-
progress: number;
|
|
21
|
-
/** Current guidance code, `null` when no hint applies. */
|
|
22
|
-
hint: GateHint | null;
|
|
23
|
-
/**
|
|
24
|
-
* The detector currently sees a face (a non-zero engine presence factor). `false`
|
|
25
|
-
* with `hint: 'center'` means "no face in frame" rather than "off-center" —
|
|
26
|
-
* hosts use it to tell seeking from aligning, and for the no-face copy.
|
|
27
|
-
*/
|
|
28
|
-
faceDetected: boolean;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* What the engine captured. Fires BEFORE any upload. `clip` is absent only in
|
|
32
|
-
* the `degraded: 'NO_RECORDER'` case (no MediaRecorder on this browser).
|
|
33
|
-
*/
|
|
34
|
-
interface CapturedArtifacts {
|
|
35
|
-
/** Mirrored JPEG keyframe (the face_match probe). */
|
|
36
|
-
keyframe: Blob;
|
|
37
|
-
/** The 2.5 s liveness clip (MP4-first mime ladder). */
|
|
38
|
-
clip?: Blob;
|
|
39
|
-
/** Container mime the clip finalized with — may carry codec params. */
|
|
40
|
-
clipMime?: string;
|
|
41
|
-
/** Intrinsic video width at capture time. */
|
|
42
|
-
width: number;
|
|
43
|
-
/** Intrinsic video height at capture time. */
|
|
44
|
-
height: number;
|
|
45
|
-
/** Recording-start → recording-stop, when known. */
|
|
46
|
-
clipMs?: number;
|
|
47
|
-
/** `'mobile'` on phones/tablets (the calibrated channel), else `'desktop'`. */
|
|
48
|
-
captureChannel: CaptureChannel;
|
|
49
|
-
/** Set when the browser has no MediaRecorder: a keyframe-only capture. */
|
|
50
|
-
degraded?: "NO_RECORDER";
|
|
51
|
-
/** The capture engine that produced the artifacts (`'v3'` for this SDK). Always set by the SDK; optional in the type so host-built fixtures stay valid. */
|
|
52
|
-
engine?: CaptureEngineId;
|
|
53
|
-
/**
|
|
54
|
-
* Camera request (`getUserMedia`) → the preview is live, in whole
|
|
55
|
-
* milliseconds measured with `performance.now()`. Part of the face-capture
|
|
56
|
-
* timing the SDK forwards to the backend as `input.capture` on the liveness
|
|
57
|
-
* submission; absent when the phase was not observed.
|
|
58
|
-
*/
|
|
59
|
-
cameraReadyMs?: number;
|
|
60
|
-
/**
|
|
61
|
-
* Camera ready → the first face ACCEPTED by the gate (present and with
|
|
62
|
-
* size, centering and quality good enough to make progress — not merely
|
|
63
|
-
* detected), whole ms. Absent when no face was ever accepted.
|
|
64
|
-
*/
|
|
65
|
-
faceAcquireMs?: number;
|
|
66
|
-
/**
|
|
67
|
-
* Face-capture duration: FIRST accepted face → gate progress 100 % (capture
|
|
68
|
-
* complete, before the clip window and any upload), whole ms. A face lost
|
|
69
|
-
* and re-acquired keeps the first acceptance as its start.
|
|
70
|
-
*/
|
|
71
|
-
captureMs?: number;
|
|
72
|
-
}
|
|
73
|
-
/** Capture engine identifier carried on {@link CapturedArtifacts.engine}. */
|
|
74
|
-
type CaptureEngineId = "v1" | "v3";
|
|
75
|
-
/** Camera / engine failure kinds — collapsed to the public six. */
|
|
76
|
-
type CaptureErrorKind = "permission" | "notfound" | "inuse" | "insecure" | "unsupported" | "generic";
|
|
77
|
-
/** Camera / engine failure payload (`on('error')`). */
|
|
78
|
-
interface CaptureError {
|
|
79
|
-
kind: CaptureErrorKind;
|
|
80
|
-
/**
|
|
81
|
-
* A fresh attempt (`retry()`) can succeed — false for `insecure` (needs
|
|
82
|
-
* HTTPS) and `unsupported` (the browser cannot capture at all).
|
|
83
|
-
*/
|
|
84
|
-
retryable: boolean;
|
|
85
|
-
}
|
|
86
|
-
/** Event map of a {@link LivenessCaptureHandle}. */
|
|
87
|
-
interface LivenessCaptureEvents {
|
|
88
|
-
/** Every state transition. */
|
|
89
|
-
state: CaptureState;
|
|
90
|
-
/** Gate ring updates while gating/recording. */
|
|
91
|
-
gate: GateUpdate;
|
|
92
|
-
/** The capture result — fires BEFORE any upload. */
|
|
93
|
-
captured: CapturedArtifacts;
|
|
94
|
-
/** Camera / engine failure. */
|
|
95
|
-
error: CaptureError;
|
|
96
|
-
/**
|
|
97
|
-
* Clip mode only: the recording window just ended and the keyframe is already
|
|
98
|
-
* available, BEFORE the clip finalizes (iOS can lag ~1.5 s). Hosts freeze the
|
|
99
|
-
* display on `previewDataUrl` (a mirrored JPEG data URL) instead of leaving
|
|
100
|
-
* the live feed running; `captured` follows once the clip lands.
|
|
101
|
-
*/
|
|
102
|
-
frozen: {
|
|
103
|
-
previewDataUrl: string;
|
|
104
|
-
};
|
|
105
|
-
/**
|
|
106
|
-
* Device-profile hint, emitted when it changes: `'reduced'` asks the host to
|
|
107
|
-
* drop decorative animations (a LOW device class needs the frames for
|
|
108
|
-
* detection). Chrome only — never gate input.
|
|
109
|
-
*/
|
|
110
|
-
profile: {
|
|
111
|
-
animations: "full" | "reduced";
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
/** Which camera to open: the selfie camera (`'user'`) or the rear one (`'environment'`). */
|
|
115
|
-
type CameraFacing = "user" | "environment";
|
|
116
|
-
/** Options of {@link LivenessCaptureHandle.start}. */
|
|
117
|
-
interface LivenessStartOptions {
|
|
118
|
-
/**
|
|
119
|
-
* Camera for this attempt and its retries; default: the current one
|
|
120
|
-
* ({@link LivenessCaptureOptions.facing}, else `'user'`). Use `switchCamera()`
|
|
121
|
-
* to change camera mid-capture.
|
|
122
|
-
*/
|
|
123
|
-
facing?: CameraFacing;
|
|
124
|
-
}
|
|
125
|
-
/** Live capture handle returned by {@link createLivenessCapture} / {@link Verification.liveness}. */
|
|
126
|
-
interface LivenessCaptureHandle {
|
|
127
|
-
/** Current {@link CaptureState}. */
|
|
128
|
-
readonly state: CaptureState;
|
|
129
|
-
/** Subscribe; returns the unsubscribe function. */
|
|
130
|
-
on<K extends keyof LivenessCaptureEvents>(event: K, handler: (payload: LivenessCaptureEvents[K]) => void): () => void;
|
|
131
|
-
/**
|
|
132
|
-
* Ask for the camera and start gating. Resolves once the attempt is running or failed.
|
|
133
|
-
* `options.facing` picks the camera for this attempt and later retries.
|
|
134
|
-
*/
|
|
135
|
-
start(options?: LivenessStartOptions): Promise<void>;
|
|
136
|
-
/** Fresh attempt: resets the engine and restarts the camera. */
|
|
137
|
-
retry(): void;
|
|
138
|
-
/** Toggle user/environment camera (gate restarts from zero). */
|
|
139
|
-
switchCamera(): void;
|
|
140
|
-
/** Stop the camera, release the detector, drop all listeners. */
|
|
141
|
-
destroy(): void;
|
|
142
|
-
}
|
|
143
|
-
/** Options of {@link createLivenessCapture} / {@link Verification.liveness}. */
|
|
144
|
-
interface LivenessCaptureOptions {
|
|
145
|
-
/** Host-owned `<video playsInline muted>` element. */
|
|
146
|
-
video: HTMLVideoElement;
|
|
147
|
-
/** Initial camera; default `'user'`. `start({ facing })` overrides it. */
|
|
148
|
-
facing?: CameraFacing;
|
|
149
|
-
/** Base URL of the detector assets (tasks-vision wasm + tflite); default `/models-v3`. */
|
|
150
|
-
assetBaseUrl?: string;
|
|
151
|
-
/**
|
|
152
|
-
* Hold a Screen Wake Lock while the camera is live (`starting` / `gating` /
|
|
153
|
-
* `recording`) so the phone does not dim or lock mid-capture; re-taken when
|
|
154
|
-
* the page becomes visible again. Best-effort: unsupported browsers or a
|
|
155
|
-
* refused request (e.g. an iframe without `allow="screen-wake-lock"`) never
|
|
156
|
-
* affect the capture. Default `true`; `false` never requests the lock.
|
|
157
|
-
*/
|
|
158
|
-
keepScreenAwake?: boolean;
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* SDK-side failure reasons (status `'unavailable'`):
|
|
162
|
-
* - `no_recorder` — no MediaRecorder / unsupported clip container;
|
|
163
|
-
* - `attestation` — Turnstile failed client-side or `attestation_invalid` after one retry;
|
|
164
|
-
* - `network` — transport / API failure after the bounded replays;
|
|
165
|
-
* - `nni_unbound` — `population_registry` is the frontier but the session was
|
|
166
|
-
* minted WITHOUT a server-bound NNI (`POST /sessions` `input.nni`), so the
|
|
167
|
-
* SDK cannot submit it. Mint the session with the NNI (or complete the
|
|
168
|
-
* population step yourself) before starting the capture;
|
|
169
|
-
* - `method_required` — the session waits on the identity-method choice
|
|
170
|
-
* (profile v2 step 3; `on('method')` fired). Ask the person, call
|
|
171
|
-
* {@link Verification.selectMethod}, then capture again;
|
|
172
|
-
* - `inference_unavailable` — the model service stayed busy through the
|
|
173
|
-
* automatic retries (profile v2 step 4; `on('busy')` fired for each). No
|
|
174
|
-
* attempt was used and nothing was billed: let the person try again in a
|
|
175
|
-
* moment.
|
|
176
|
-
*
|
|
177
|
-
* A liveness step that needs a phone (`HostedStepView.requiresMobile`) on a
|
|
178
|
-
* desktop browser ends with the reason `mobile_required` (status
|
|
179
|
-
* `unavailable`): send the person to their phone. The SDK stops before any
|
|
180
|
-
* upload when the view says so; otherwise the backend answers the submit with
|
|
181
|
-
* a request-level `409 mobile_required` (no attempt used, nothing billed).
|
|
182
|
-
*/
|
|
183
|
-
type SdkFailureReason = "no_recorder" | "attestation" | "network" | "nni_unbound" | "method_required" | "inference_unavailable";
|
|
184
|
-
/** Backend reason taxonomy ∪ the SDK-side failure reasons. */
|
|
185
|
-
type ReasonCode = CheckReason | SessionFailureReason | SdkFailureReason;
|
|
186
|
-
/**
|
|
187
|
-
* - `approved` / `rejected` / `review` — the session's verdict;
|
|
188
|
-
* - `retry` — a retryable reason with attempts remaining (`autoRetry` on); the
|
|
189
|
-
* capture re-arms by itself;
|
|
190
|
-
* - `unavailable` — v2 could not run this capture (no MediaRecorder,
|
|
191
|
-
* attestation failed, network/API failure). Treat as "not completed".
|
|
192
|
-
*/
|
|
193
|
-
type VerificationStatus = "approved" | "rejected" | "review" | "retry" | "unavailable";
|
|
194
|
-
/** The verdict for this session / capture (`on('result')`). */
|
|
195
|
-
interface VerificationResult {
|
|
196
|
-
sessionId: string;
|
|
197
|
-
status: VerificationStatus;
|
|
198
|
-
/** Backend check or session-policy reason, or SDK-side reason for `unavailable`. */
|
|
199
|
-
reason?: ReasonCode;
|
|
200
|
-
/**
|
|
201
|
-
* `retry` (and a `rejected` on a still-parked step): submissions left for
|
|
202
|
-
* the parked check after this one, for the host's coaching copy.
|
|
203
|
-
*/
|
|
204
|
-
attemptsRemaining?: number;
|
|
205
|
-
/**
|
|
206
|
-
* ISO-8601 time from which this device may verify again — set on a
|
|
207
|
-
* `rejected` result with reason `device_cooldown` (profile v2 step 4).
|
|
208
|
-
*/
|
|
209
|
-
retryAfter?: string;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* `on('busy')` payload: the model service answered
|
|
213
|
-
* `503 inference_unavailable` and the SDK waits `retryAfterSeconds` before
|
|
214
|
-
* retry number `attempt` (1-based, at most 3). Show "busy, trying again" copy.
|
|
215
|
-
*/
|
|
216
|
-
interface VerificationBusy {
|
|
217
|
-
attempt: number;
|
|
218
|
-
retryAfterSeconds: number;
|
|
219
|
-
}
|
|
220
|
-
/** Consent locale picklist (mirrors the backend HostedConsentSchema). */
|
|
221
|
-
type VerificationLocale = "ar" | "fr" | "en";
|
|
222
|
-
/** Options of {@link createVerification}. */
|
|
223
|
-
interface VerificationOptions {
|
|
224
|
-
/** The session's client token (from `POST /api/v2/sessions` → `client_token`). */
|
|
225
|
-
clientToken: string;
|
|
226
|
-
/** API origin; default `https://api.sekyro.ai`. */
|
|
227
|
-
apiOrigin?: string;
|
|
228
|
-
/** Consent locale (echoed into the auditable consent record). */
|
|
229
|
-
locale: VerificationLocale;
|
|
230
|
-
/** Re-arm the capture on retryable reasons while attempts remain. Default `true`. */
|
|
231
|
-
autoRetry?: boolean;
|
|
232
|
-
/**
|
|
233
|
-
* How a `retry` verdict re-arms the capture (`autoRetry` on):
|
|
234
|
-
* - `'auto'` (default) — the camera restarts immediately;
|
|
235
|
-
* - `'manual'` — the handle settles at `done`; the host shows its coaching
|
|
236
|
-
* and calls `retry()` on the handle when the user is ready.
|
|
237
|
-
*/
|
|
238
|
-
rearm?: "auto" | "manual";
|
|
239
|
-
/** Injection seam for `fetch` (tests / non-window contexts). */
|
|
240
|
-
fetch?: typeof globalThis.fetch;
|
|
241
|
-
}
|
|
242
|
-
/** Event map of a {@link Verification}. */
|
|
243
|
-
interface VerificationEvents {
|
|
244
|
-
/** Verdict per capture (and once when the registry settles the session early). */
|
|
245
|
-
result: VerificationResult;
|
|
246
|
-
/** Every hosted-view update the SDK observes (bootstrap, consent, submits). */
|
|
247
|
-
view: HostedSessionView;
|
|
248
|
-
/**
|
|
249
|
-
* The session waits on the identity-method choice (profile v2 step 3) and
|
|
250
|
-
* the SDK stopped before submitting anything: show the options and call
|
|
251
|
-
* {@link Verification.selectMethod}.
|
|
252
|
-
*/
|
|
253
|
-
method: MethodChoiceView;
|
|
254
|
-
/**
|
|
255
|
-
* The model service is briefly unavailable and the SDK retries by itself
|
|
256
|
-
* (profile v2 step 4). A `result` follows: the verdict, or
|
|
257
|
-
* `unavailable / inference_unavailable` once the retries are spent.
|
|
258
|
-
*/
|
|
259
|
-
busy: VerificationBusy;
|
|
260
|
-
}
|
|
261
|
-
/** One session's verification, from {@link createVerification}. */
|
|
262
|
-
interface Verification {
|
|
263
|
-
/** Record consent once (no-op when the session already has it). */
|
|
264
|
-
consent(): Promise<void>;
|
|
265
|
-
/**
|
|
266
|
-
* Submit `population_registry` early with an empty input when it is the
|
|
267
|
-
* pending frontier and the backend holds the NNI: the SERVER-bound one, or
|
|
268
|
-
* the one the document step read (`nniFromDocument`). Retries once on
|
|
269
|
-
* `registry_unavailable`. Never rejects — failures surface through
|
|
270
|
-
* `result`. Idempotent.
|
|
271
|
-
*/
|
|
272
|
-
startRegistry(): Promise<void>;
|
|
273
|
-
/**
|
|
274
|
-
* The identity-method choice the session waits on (profile v2 step 3),
|
|
275
|
-
* bootstrapping the hosted view when needed; `null` when there is no
|
|
276
|
-
* pending choice, the bootstrap fails, or the verification was destroyed.
|
|
277
|
-
* Never rejects.
|
|
278
|
-
*/
|
|
279
|
-
methodChoice(): Promise<MethodChoiceView | null>;
|
|
280
|
-
/**
|
|
281
|
-
* Send the person's identity method (`POST /hosted/method`) and continue
|
|
282
|
-
* from the returned view. Rejects with the typed `HostedApiError` (e.g.
|
|
283
|
-
* 409 `method_locked`).
|
|
284
|
-
*/
|
|
285
|
-
selectMethod(method: IdentityMethod): Promise<void>;
|
|
286
|
-
/**
|
|
287
|
-
* The session's pending liveness step must be captured on a phone
|
|
288
|
-
* (`HostedStepView.requiresMobile`, profile v2 step 4 automatic decisions)
|
|
289
|
-
* and this browser is not one: show "continue on your phone" instead of
|
|
290
|
-
* starting the camera. Bootstraps the hosted view when needed; `false` when
|
|
291
|
-
* the bootstrap fails or the verification was destroyed. Never rejects.
|
|
292
|
-
* Optional so custom / older `Verification` implementations stay valid —
|
|
293
|
-
* treat an absent member as "no phone requirement".
|
|
294
|
-
*/
|
|
295
|
-
mobileRequired?(): Promise<boolean>;
|
|
296
|
-
/** Start a liveness capture bound to this verification; the SDK uploads + submits on `captured`. */
|
|
297
|
-
liveness(options: LivenessCaptureOptions): LivenessCaptureHandle;
|
|
298
|
-
/**
|
|
299
|
-
* The session's Sekyro AI-hosted voice clips (`view.voice`), bootstrapping the
|
|
300
|
-
* hosted view when it has not been fetched yet. Resolves `null` when the
|
|
301
|
-
* session has no active clip set, the API predates the field, the bootstrap
|
|
302
|
-
* fails, or the verification was destroyed. Never rejects.
|
|
303
|
-
*/
|
|
304
|
-
voiceClips(): Promise<HostedVoiceView | null>;
|
|
305
|
-
/** Subscribe; returns the unsubscribe function. */
|
|
306
|
-
on<K extends keyof VerificationEvents>(event: K, handler: (payload: VerificationEvents[K]) => void): () => void;
|
|
307
|
-
/** Destroy the active capture and drop all listeners. */
|
|
308
|
-
destroy(): void;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/** The engine surface the handle binds — CaptureSessionV3 or a test double. */
|
|
312
|
-
interface CaptureEngine {
|
|
313
|
-
readonly state: CaptureState$1;
|
|
314
|
-
on<K extends keyof CaptureSessionV3Events>(event: K, handler: (payload: CaptureSessionV3Events[K]) => void): () => void;
|
|
315
|
-
/** `facingMode` sets the camera for this attempt and later retries. */
|
|
316
|
-
start(options?: {
|
|
317
|
-
facingMode?: "user" | "environment";
|
|
318
|
-
}): Promise<void>;
|
|
319
|
-
retry(): void;
|
|
320
|
-
switchCamera(): void;
|
|
321
|
-
destroy(): void;
|
|
322
|
-
/** Device-profile chrome hint (LOW class → `'reduced'`); absent on doubles. */
|
|
323
|
-
readonly animations?: "full" | "reduced";
|
|
324
|
-
}
|
|
325
|
-
/** Internal construction seams (tests; Sekyro AI's own hosted page). */
|
|
326
|
-
interface LivenessCaptureInternals {
|
|
327
|
-
/** Replace the engine constructor (default: `new CaptureSessionV3(options)`). */
|
|
328
|
-
createEngine?: (options: CaptureSessionV3Options) => CaptureEngine;
|
|
329
|
-
/** Extra engine options merged in (worker offload, warmed detector, telemetry). */
|
|
330
|
-
engineOptions?: Partial<Pick<CaptureSessionV3Options, "createDetector" | "createWorker" | "telemetry" | "deviceClass">>;
|
|
331
|
-
/** Clock (default `performance.now`). */
|
|
332
|
-
now?: () => number;
|
|
333
|
-
}
|
|
334
|
-
/** fcv3.* guidance key → public gate hint code. */
|
|
335
|
-
declare function mapGuidanceHint(key: string): GateHint | null;
|
|
336
|
-
/** Engine state → public state (`preflight|acquiring → starting`, `positioning → gating`). */
|
|
337
|
-
declare function mapEngineState(state: CaptureState$1): CaptureState;
|
|
338
|
-
/** Engine error kinds → the public six (`models|cliptoolarge|recorder|overconstrained → generic`). */
|
|
339
|
-
declare function mapErrorKind(kind: CaptureErrorKind$1): CaptureErrorKind;
|
|
340
|
-
/** Handle + the hooks the verification layer uses to drive the flow states. */
|
|
341
|
-
interface LivenessCaptureInternalHandle {
|
|
342
|
-
handle: LivenessCaptureHandle;
|
|
343
|
-
/** Push a post-capture state (`uploading | checking | done`). */
|
|
344
|
-
setFlowState(state: Extract<CaptureState, "uploading" | "checking" | "done">): void;
|
|
345
|
-
}
|
|
346
|
-
declare function createLivenessCaptureInternal(options: LivenessCaptureOptions, internals?: LivenessCaptureInternals): LivenessCaptureInternalHandle;
|
|
347
|
-
/**
|
|
348
|
-
* Create a standalone liveness capture (no upload — pair it with your own
|
|
349
|
-
* submission, or use {@link Verification.liveness} for the full flow).
|
|
350
|
-
*/
|
|
351
|
-
declare function createLivenessCapture(options: LivenessCaptureOptions): LivenessCaptureHandle;
|
|
352
|
-
|
|
353
|
-
/** Preload state per asset base URL. */
|
|
354
|
-
type LivenessAssetsStatus = "idle" | "loading" | "ready" | "failed";
|
|
355
|
-
/** Options of {@link preloadLivenessAssets}. */
|
|
356
|
-
interface PreloadLivenessAssetsOptions {
|
|
357
|
-
/** Same value as the capture's `assetBaseUrl`; default `/models-v3`. */
|
|
358
|
-
assetBaseUrl?: string;
|
|
359
|
-
/** Defer the load to browser idle time (`requestIdleCallback`, 1.2 s timeout fallback). Default `false`. */
|
|
360
|
-
idle?: boolean;
|
|
361
|
-
/** Skip when the browser asks to save data (`navigator.connection.saveData`). Default `false`. */
|
|
362
|
-
respectSaveData?: boolean;
|
|
363
|
-
}
|
|
364
|
-
/** Blaze init deadline for the preload — generous: a slow ~11 MB wasm download must finish. */
|
|
365
|
-
declare const PRELOAD_BLAZE_INIT_TIMEOUT_MS = 120000;
|
|
366
|
-
/** Outer budget reclaiming only a genuinely hung load (≥ the init deadline + slack). */
|
|
367
|
-
declare const PRELOAD_BUDGET_MS = 130000;
|
|
368
|
-
type Loader = (base: string) => Promise<Detector>;
|
|
369
|
-
/** @internal Test seam: replace the detector loader (null restores the real one). */
|
|
370
|
-
declare function setPreloadLoaderForTests(next: Loader | null): void;
|
|
371
|
-
/** @internal Test seam: drop every entry (destroying warmed detectors). */
|
|
372
|
-
declare function resetLivenessAssetsForTests(): void;
|
|
373
|
-
/**
|
|
374
|
-
* Warm the face detector for `assetBaseUrl` so the capture starts instantly.
|
|
375
|
-
* Idempotent per base URL and never rejects: resolves the settled status.
|
|
376
|
-
* `'idle'` means nothing was preloaded here (SSR, no camera API, Data-Saver
|
|
377
|
-
* skip) — start normally. Calling again after `'failed'` retries the load.
|
|
378
|
-
* With `idle: true` the load is deferred (status stays `'idle'` until it
|
|
379
|
-
* starts); a later non-idle call — or a capture mounting meanwhile — starts it
|
|
380
|
-
* at once, and {@link releaseLivenessAssets} cancels it.
|
|
381
|
-
*/
|
|
382
|
-
declare function preloadLivenessAssets(options?: PreloadLivenessAssetsOptions): Promise<LivenessAssetsStatus>;
|
|
383
|
-
/** Current preload status for `assetBaseUrl` (default `/models-v3`). */
|
|
384
|
-
declare function getLivenessAssetsStatus(assetBaseUrl?: string): LivenessAssetsStatus;
|
|
385
|
-
/**
|
|
386
|
-
* Subscribe to status changes for `assetBaseUrl`; returns the unsubscribe
|
|
387
|
-
* function. Does NOT emit the current status on subscribe (read it with
|
|
388
|
-
* {@link getLivenessAssetsStatus}) — the
|
|
389
|
-
* `useSyncExternalStore(subscribe, getSnapshot)` contract, so it plugs into
|
|
390
|
-
* that hook directly.
|
|
391
|
-
*/
|
|
392
|
-
declare function subscribeLivenessAssets(listener: (status: LivenessAssetsStatus) => void, assetBaseUrl?: string): () => void;
|
|
393
|
-
/** Free the warmed detector (an SPA leaving the flow). Never call while a capture is mounted. */
|
|
394
|
-
declare function releaseLivenessAssets(assetBaseUrl?: string): void;
|
|
395
|
-
/**
|
|
396
|
-
* @internal The capture engine's detector source when a preload exists for
|
|
397
|
-
* `assetBaseUrl`: a non-owning view of the warm instance (waiting for an
|
|
398
|
-
* in-flight load), or — once that load failed — a cold detector OWNED by the
|
|
399
|
-
* session (default ladder + deadline). `undefined` when nothing was preloaded.
|
|
400
|
-
* Invoking it on an idle-scheduled preload starts that load now and joins it.
|
|
401
|
-
*/
|
|
402
|
-
declare function preloadedDetectorFactory(assetBaseUrl?: string): (() => Promise<Detector>) | undefined;
|
|
403
|
-
|
|
404
|
-
/** The client surface the flow needs — `HostedClient` or a test fake. */
|
|
405
|
-
type HostedClientLike = Pick<HostedClient, "getSession" | "recordConsent" | "selectMethod" | "presign" | "uploadToSpaces" | "completeMedia" | "submitCheck">;
|
|
406
|
-
/** The presign policy allowlist for `kind: 'clip'` (media.policy.ts mirror). */
|
|
407
|
-
declare const CLIP_MIME_ALLOWLIST: readonly string[];
|
|
408
|
-
/** Same-key transport replays AFTER the first try, and the pause between them. */
|
|
409
|
-
declare const TRANSPORT_REPLAY_ATTEMPTS = 2;
|
|
410
|
-
declare const TRANSPORT_REPLAY_DELAY_MS = 1000;
|
|
411
|
-
/**
|
|
412
|
-
* `503 inference_unavailable` (profile v2 step 4 — request-level: no state
|
|
413
|
-
* change, no attempt used, not billed): retries after `retryAfterSeconds`
|
|
414
|
-
* (default {@link INFERENCE_RETRY_DEFAULT_S}, capped at 30 s), at most
|
|
415
|
-
* {@link INFERENCE_RETRY_ATTEMPTS} times, each under a FRESH key (each retry
|
|
416
|
-
* is its own logical attempt; the backend never caches a 5xx envelope).
|
|
417
|
-
*/
|
|
418
|
-
declare const INFERENCE_RETRY_ATTEMPTS = 3;
|
|
419
|
-
declare const INFERENCE_RETRY_DEFAULT_S = 10;
|
|
420
|
-
/** A Turnstile challenge failed client-side (load / render / error-callback / timeout). */
|
|
421
|
-
declare class AttestationError extends Error {
|
|
422
|
-
constructor(message: string);
|
|
423
|
-
}
|
|
424
|
-
/** One logical submission: receives the client and ITS idempotency key. */
|
|
425
|
-
type SubmitExecutor = (client: HostedClientLike, idempotencyKey: string) => Promise<SessionView>;
|
|
426
|
-
interface SubmitRuntime {
|
|
427
|
-
client: HostedClientLike;
|
|
428
|
-
/** Force-record consent (the server just said it is missing). */
|
|
429
|
-
ensureConsent(opts: {
|
|
430
|
-
force: true;
|
|
431
|
-
}): Promise<void>;
|
|
432
|
-
sleep(ms: number): Promise<void>;
|
|
433
|
-
uuid(): string;
|
|
434
|
-
/** An `inference_unavailable` retry is about to wait (the `busy` event). */
|
|
435
|
-
onBusy?(info: VerificationBusy): void;
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Run one logical submission (ported use-submit semantics):
|
|
439
|
-
* - a fresh `crypto.randomUUID()` key per logical submission;
|
|
440
|
-
* - a transport-class failure replays the SAME executor under the SAME key
|
|
441
|
-
* (bounded) — the backend's IdempotencyInterceptor returns the first
|
|
442
|
-
* response instead of burning another attempt;
|
|
443
|
-
* - ONE `consent_required` recovery: force-record consent and re-run under a
|
|
444
|
-
* FRESH key (the 409 envelope is idempotency-cached under the old one);
|
|
445
|
-
* - ONE attestation retry (client-side Turnstile failure or a server
|
|
446
|
-
* `attestation_invalid`): `onAttestationInvalid` drops the cached token and
|
|
447
|
-
* the executor re-runs under a fresh key;
|
|
448
|
-
* - up to {@link INFERENCE_RETRY_ATTEMPTS} `inference_unavailable` retries
|
|
449
|
-
* after `retryAfterSeconds`, each under a FRESH key and with a fresh
|
|
450
|
-
* attestation (`onAttestationInvalid` — the Turnstile token was spent).
|
|
451
|
-
* Throws the final error otherwise.
|
|
452
|
-
*/
|
|
453
|
-
declare function runSubmission(rt: SubmitRuntime, executor: SubmitExecutor, hooks?: {
|
|
454
|
-
onAttestationInvalid?: () => void;
|
|
455
|
-
}): Promise<SessionView>;
|
|
456
|
-
interface LivenessFlowDeps extends SubmitRuntime {
|
|
457
|
-
artifacts: CapturedArtifacts;
|
|
458
|
-
/** Fresh attestation per call (Turnstile execute, or `{sandbox: true}`). */
|
|
459
|
-
getAttestation(): Promise<AttestationInput>;
|
|
460
|
-
/** Latest hosted view (frontier decisions). */
|
|
461
|
-
getView(): HostedSessionView;
|
|
462
|
-
/** Re-GET the view from the server (after a RESYNC code) and fold it in. */
|
|
463
|
-
refreshView(): Promise<HostedSessionView>;
|
|
464
|
-
/** Fold a submit response into the view. */
|
|
465
|
-
applySubmit(view: SessionView, submitted: CheckType): void;
|
|
466
|
-
/** Flow-state hook for the capture handle. */
|
|
467
|
-
onPhase(phase: "uploading" | "checking"): void;
|
|
468
|
-
/** The verification was destroyed (the only thing that cancels a chain). */
|
|
469
|
-
isCancelled(): boolean;
|
|
470
|
-
}
|
|
471
|
-
type LivenessFlowOutcome = {
|
|
472
|
-
kind: "settled";
|
|
473
|
-
} | {
|
|
474
|
-
kind: "resync";
|
|
475
|
-
} | {
|
|
476
|
-
kind: "unavailable";
|
|
477
|
-
reason: SdkFailureReason | "mobile_required";
|
|
478
|
-
} | {
|
|
479
|
-
kind: "cancelled";
|
|
480
|
-
};
|
|
481
|
-
/**
|
|
482
|
-
* Run the biometric submissions the CURRENT frontier allows, re-evaluating
|
|
483
|
-
* after every submit and after every RESYNC re-GET:
|
|
484
|
-
* - frontier `liveness` → clip upload + attestation + `liveness` (once per capture);
|
|
485
|
-
* - frontier `face_match` → keyframe upload + `face_match` (once per capture),
|
|
486
|
-
* allowed when liveness was NOT part of this capture (it had already
|
|
487
|
-
* settled — any state, incl. `failed`: the selfie-fallback case, where this
|
|
488
|
-
* capture only feeds face_match) or settled chainable from this capture
|
|
489
|
-
* (passed / review / processing / skipped — or absent);
|
|
490
|
-
* - anything else (terminal view, a non-biometric frontier, a check this
|
|
491
|
-
* capture already submitted) → `settled` for the caller to map the view.
|
|
492
|
-
* A RESYNC code re-GETs the view and re-enters (at most {@link RESYNC_REENTRY_MAX}
|
|
493
|
-
* times); the final RESYNC surfaces as `resync` for the caller to map.
|
|
494
|
-
*/
|
|
495
|
-
declare function runLivenessFlow(deps: LivenessFlowDeps): Promise<LivenessFlowOutcome>;
|
|
496
|
-
|
|
497
|
-
/** Production API origin — the `apiOrigin` default. */
|
|
498
|
-
declare const DEFAULT_API_ORIGIN = "https://api.sekyro.ai";
|
|
499
|
-
/** Pause before the single `registry_unavailable` re-submit. */
|
|
500
|
-
declare const REGISTRY_RETRY_DELAY_MS = 5000;
|
|
501
|
-
/** Bounded poll while a biometric verdict is still `processing` after the submits. */
|
|
502
|
-
declare const PROCESSING_POLL_DELAY_MS = 1500;
|
|
503
|
-
declare const PROCESSING_POLL_MAX = 10;
|
|
504
|
-
/**
|
|
505
|
-
* Construction seams — tests and Sekyro AI's own hosted page (`@sekyro/web/internal`).
|
|
506
|
-
* Not part of the partner contract.
|
|
507
|
-
*/
|
|
508
|
-
interface VerificationInternals {
|
|
509
|
-
/** Replace the HTTP client (default: `new HostedClient({...})`). */
|
|
510
|
-
client?: HostedClientLike;
|
|
511
|
-
/**
|
|
512
|
-
* Replace the Turnstile challenge (default: {@link executeTurnstile}). The
|
|
513
|
-
* `signal` aborts when the verification is destroyed (M1).
|
|
514
|
-
*/
|
|
515
|
-
getTurnstileToken?: (siteKey: string, opts: {
|
|
516
|
-
signal: AbortSignal;
|
|
517
|
-
}) => Promise<string>;
|
|
518
|
-
/** Capture-engine seams forwarded to {@link createLivenessCaptureInternal}. */
|
|
519
|
-
capture?: LivenessCaptureInternals;
|
|
520
|
-
sleep?: (ms: number) => Promise<void>;
|
|
521
|
-
uuid?: () => string;
|
|
522
|
-
}
|
|
523
|
-
/** `crypto.randomUUID()` with a v4 fallback for hosts that lack it. */
|
|
524
|
-
declare function randomUuid(): string;
|
|
525
|
-
/**
|
|
526
|
-
* Create a verification bound to one session (spec §3.1):
|
|
527
|
-
* `consent()` → `startRegistry()` → `liveness({video})` → `on('result')`.
|
|
528
|
-
*/
|
|
529
|
-
declare function createVerification(options: VerificationOptions): Verification;
|
|
530
|
-
/** {@link createVerification} with construction seams (tests / Sekyro AI-internal hosts). */
|
|
531
|
-
declare function createVerificationInternal(options: VerificationOptions, internals: VerificationInternals): Verification;
|
|
532
|
-
|
|
533
|
-
export { mapEngineState as $, AttestationError as A, type LivenessCaptureInternalHandle as B, type CameraFacing as C, DEFAULT_API_ORIGIN as D, type LivenessCaptureInternals as E, type LivenessFlowDeps as F, type GateHint as G, type HostedClientLike as H, INFERENCE_RETRY_ATTEMPTS as I, type LivenessFlowOutcome as J, PRELOAD_BLAZE_INIT_TIMEOUT_MS as K, type LivenessAssetsStatus as L, PRELOAD_BUDGET_MS as M, PROCESSING_POLL_DELAY_MS as N, PROCESSING_POLL_MAX as O, type PreloadLivenessAssetsOptions as P, REGISTRY_RETRY_DELAY_MS as Q, type ReasonCode as R, type SdkFailureReason as S, type SubmitExecutor as T, type SubmitRuntime as U, type Verification as V, TRANSPORT_REPLAY_ATTEMPTS as W, TRANSPORT_REPLAY_DELAY_MS as X, type VerificationInternals as Y, createLivenessCaptureInternal as Z, createVerificationInternal as _, type CaptureChannel as a, mapErrorKind as a0, mapGuidanceHint as a1, preloadedDetectorFactory as a2, randomUuid as a3, resetLivenessAssetsForTests as a4, runLivenessFlow as a5, runSubmission as a6, setPreloadLoaderForTests as a7, type CaptureEngineId as b, type CaptureError as c, type CaptureErrorKind as d, type CaptureState as e, type CapturedArtifacts as f, type GateUpdate as g, type LivenessCaptureEvents as h, type LivenessCaptureHandle as i, type LivenessCaptureOptions as j, type LivenessStartOptions as k, type VerificationBusy as l, type VerificationEvents as m, type VerificationLocale as n, type VerificationOptions as o, type VerificationResult as p, type VerificationStatus as q, createLivenessCapture as r, createVerification as s, getLivenessAssetsStatus as t, preloadLivenessAssets as u, releaseLivenessAssets as v, subscribeLivenessAssets as w, CLIP_MIME_ALLOWLIST as x, type CaptureEngine as y, INFERENCE_RETRY_DEFAULT_S as z };
|