@sekyro/web 0.1.0-rc.2 → 0.1.0-rc.4
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 +19 -0
- package/dist/{capture-session-v3-CAoWM8iT.d.cts → capture-session-v3-DEInCOUg.d.cts} +37 -7
- package/dist/{capture-session-v3-BJ8ciaWl.d.ts → capture-session-v3-uXJr1Wlm.d.ts} +37 -7
- package/dist/{chunk-LOTAJDRE.js → chunk-EWRNPKTR.js} +38 -9
- package/dist/chunk-EWRNPKTR.js.map +1 -0
- package/dist/{chunk-BPYVZUJA.js → chunk-TBANUT3X.js} +39 -6
- package/dist/chunk-TBANUT3X.js.map +1 -0
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/core/index.cjs +37 -8
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -1
- package/dist/{create-verification-EnZ13uY4.d.cts → create-verification-Ce1y5kJR.d.ts} +26 -3
- package/dist/{create-verification-CjLnJ0w6.d.ts → create-verification-Dkb2tXuY.d.cts} +26 -3
- package/dist/{hosted-client-BpvBqu9f.d.cts → hosted-client-DWzCRYJK.d.cts} +14 -1
- package/dist/{hosted-client-BpvBqu9f.d.ts → hosted-client-DWzCRYJK.d.ts} +14 -1
- package/dist/index.cjs +74 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/internal/index.cjs +74 -12
- package/dist/internal/index.cjs.map +1 -1
- package/dist/internal/index.d.cts +4 -4
- package/dist/internal/index.d.ts +4 -4
- package/dist/internal/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-BPYVZUJA.js.map +0 -1
- package/dist/chunk-LOTAJDRE.js.map +0 -1
package/dist/core/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CameraErrorKind } from '../capture-session-v3-
|
|
2
|
-
export { a as CLIP_MS, b as CaptureArtifacts, c as CaptureErrorKind, d as CaptureSessionEvents, e as CaptureSessionV3, f as CaptureSessionV3Events, g as CaptureSessionV3Options, h as CaptureState, i as
|
|
1
|
+
import { C as CameraErrorKind } from '../capture-session-v3-DEInCOUg.cjs';
|
|
2
|
+
export { a as CLIP_MS, b as CaptureArtifacts, c as CaptureErrorKind, d as CaptureSessionEvents, e as CaptureSessionV3, f as CaptureSessionV3Events, g as CaptureSessionV3Options, h as CaptureState, i as CaptureTiming, j as ClipError, k as ClipErrorKind, l as ClipRecorder, m as ClipResult, D as DEFAULT_CLIP_MIME, n as DEVICE_PROFILES, o as DeviceClass, p as DeviceProbe, q as DeviceProfile, r as DeviceProfiler, E as EscalationClipArtifact, s as EscalationHook, F as FaceGateV3, G as GateChecks, K as KEYFRAME_CANDIDATES, t as KEYFRAME_WINDOW_MS, M as MAX_CLIP_BYTES, u as MIME_CANDIDATES, S as STOP_GRACE_MS, T as TIMESLICE_MS, V as V3ChecksPayload, v as V3GateFactor, w as V3GateQuality, x as V3GateThresholds, y as V3GateTick, z as V3GateTickInput, A as V3TelemetryEvent, B as V3_GATE_DEFAULTS, H as VIDEO_BPS, I as buildLivenessV2FormData, J as cameraPreflight, L as classifyDevice, N as extForMime, O as isClipTooLarge, P as isMediaRecorderSupported, Q as mapGetUserMediaError, R as pickMimeType, U as probeDevice } from '../capture-session-v3-DEInCOUg.cjs';
|
|
3
3
|
export { C as CENTERED_FACTOR, a as CIRCLE_RADIUS_FACTOR, I as IN_CIRCLE_FACTOR, b as buildCaptureConstraints, d as detectIsMobile } from '../capture-constraints-BujkZcfb.cjs';
|
|
4
4
|
export { C as CreateDetectorOptions, D as DEFAULT_TIER_ORDER, a as DEFAULT_V3_ASSET_BASE_URL, b as Detector, c as DetectorLadderError, F as FaceObservation, d as createDetector, i as intrinsicSize, t as toStreamPixels } from '../detect-worker-CKXHlXx9.cjs';
|
|
5
5
|
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CameraErrorKind } from '../capture-session-v3-
|
|
2
|
-
export { a as CLIP_MS, b as CaptureArtifacts, c as CaptureErrorKind, d as CaptureSessionEvents, e as CaptureSessionV3, f as CaptureSessionV3Events, g as CaptureSessionV3Options, h as CaptureState, i as
|
|
1
|
+
import { C as CameraErrorKind } from '../capture-session-v3-uXJr1Wlm.js';
|
|
2
|
+
export { a as CLIP_MS, b as CaptureArtifacts, c as CaptureErrorKind, d as CaptureSessionEvents, e as CaptureSessionV3, f as CaptureSessionV3Events, g as CaptureSessionV3Options, h as CaptureState, i as CaptureTiming, j as ClipError, k as ClipErrorKind, l as ClipRecorder, m as ClipResult, D as DEFAULT_CLIP_MIME, n as DEVICE_PROFILES, o as DeviceClass, p as DeviceProbe, q as DeviceProfile, r as DeviceProfiler, E as EscalationClipArtifact, s as EscalationHook, F as FaceGateV3, G as GateChecks, K as KEYFRAME_CANDIDATES, t as KEYFRAME_WINDOW_MS, M as MAX_CLIP_BYTES, u as MIME_CANDIDATES, S as STOP_GRACE_MS, T as TIMESLICE_MS, V as V3ChecksPayload, v as V3GateFactor, w as V3GateQuality, x as V3GateThresholds, y as V3GateTick, z as V3GateTickInput, A as V3TelemetryEvent, B as V3_GATE_DEFAULTS, H as VIDEO_BPS, I as buildLivenessV2FormData, J as cameraPreflight, L as classifyDevice, N as extForMime, O as isClipTooLarge, P as isMediaRecorderSupported, Q as mapGetUserMediaError, R as pickMimeType, U as probeDevice } from '../capture-session-v3-uXJr1Wlm.js';
|
|
3
3
|
export { C as CENTERED_FACTOR, a as CIRCLE_RADIUS_FACTOR, I as IN_CIRCLE_FACTOR, b as buildCaptureConstraints, d as detectIsMobile } from '../capture-constraints-BujkZcfb.js';
|
|
4
4
|
export { C as CreateDetectorOptions, D as DEFAULT_TIER_ORDER, a as DEFAULT_V3_ASSET_BASE_URL, b as Detector, c as DetectorLadderError, F as FaceObservation, d as createDetector, i as intrinsicSize, t as toStreamPixels } from '../detect-worker-CKXHlXx9.js';
|
|
5
5
|
|
package/dist/core/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { h as CaptureState$1, f as CaptureSessionV3Events, g as CaptureSessionV3Options, c as CaptureErrorKind$1 } from './capture-session-v3-
|
|
2
|
-
import { C as CheckReason, c as HostedSessionView, g as HostedClient, A as AttestationInput, h as SessionView, b as CheckType } from './hosted-client-
|
|
1
|
+
import { h as CaptureState$1, f as CaptureSessionV3Events, g as CaptureSessionV3Options, c as CaptureErrorKind$1 } from './capture-session-v3-uXJr1Wlm.js';
|
|
2
|
+
import { C as CheckReason, c as HostedSessionView, g as HostedClient, A as AttestationInput, h as SessionView, b as CheckType } from './hosted-client-DWzCRYJK.js';
|
|
3
3
|
|
|
4
4
|
/** Gate guidance code. `'hold'` is emitted while the clip records. */
|
|
5
5
|
type GateHint = "center" | "closer" | "farther" | "light" | "still" | "hold";
|
|
@@ -47,7 +47,30 @@ interface CapturedArtifacts {
|
|
|
47
47
|
captureChannel: CaptureChannel;
|
|
48
48
|
/** Set when the browser has no MediaRecorder: a keyframe-only capture. */
|
|
49
49
|
degraded?: "NO_RECORDER";
|
|
50
|
+
/** 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. */
|
|
51
|
+
engine?: CaptureEngineId;
|
|
52
|
+
/**
|
|
53
|
+
* Camera request (`getUserMedia`) → the preview is live, in whole
|
|
54
|
+
* milliseconds measured with `performance.now()`. Part of the face-capture
|
|
55
|
+
* timing the SDK forwards to the backend as `input.capture` on the liveness
|
|
56
|
+
* submission; absent when the phase was not observed.
|
|
57
|
+
*/
|
|
58
|
+
cameraReadyMs?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Camera ready → the first face ACCEPTED by the gate (present and with
|
|
61
|
+
* size, centering and quality good enough to make progress — not merely
|
|
62
|
+
* detected), whole ms. Absent when no face was ever accepted.
|
|
63
|
+
*/
|
|
64
|
+
faceAcquireMs?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Face-capture duration: FIRST accepted face → gate progress 100 % (capture
|
|
67
|
+
* complete, before the clip window and any upload), whole ms. A face lost
|
|
68
|
+
* and re-acquired keeps the first acceptance as its start.
|
|
69
|
+
*/
|
|
70
|
+
captureMs?: number;
|
|
50
71
|
}
|
|
72
|
+
/** Capture engine identifier carried on {@link CapturedArtifacts.engine}. */
|
|
73
|
+
type CaptureEngineId = "v1" | "v3";
|
|
51
74
|
/** Camera / engine failure kinds — collapsed to the public six. */
|
|
52
75
|
type CaptureErrorKind = "permission" | "notfound" | "inuse" | "insecure" | "unsupported" | "generic";
|
|
53
76
|
/** Camera / engine failure payload (`on('error')`). */
|
|
@@ -345,4 +368,4 @@ declare function createVerification(options: VerificationOptions): Verification;
|
|
|
345
368
|
/** {@link createVerification} with construction seams (tests / Sekyro-internal hosts). */
|
|
346
369
|
declare function createVerificationInternal(options: VerificationOptions, internals: VerificationInternals): Verification;
|
|
347
370
|
|
|
348
|
-
export { AttestationError as A,
|
|
371
|
+
export { AttestationError as A, type VerificationInternals as B, type CaptureChannel as C, DEFAULT_API_ORIGIN as D, createLivenessCaptureInternal as E, createVerificationInternal as F, type GateHint as G, type HostedClientLike as H, mapEngineState as I, mapErrorKind as J, mapGuidanceHint as K, type LivenessCaptureEvents as L, randomUuid as M, runLivenessFlow as N, runSubmission as O, PROCESSING_POLL_DELAY_MS as P, type ReasonCode as R, type SdkFailureReason as S, TRANSPORT_REPLAY_ATTEMPTS as T, type Verification as V, type CaptureEngineId as a, type CaptureError as b, type CaptureErrorKind as c, type CaptureState as d, type CapturedArtifacts as e, type GateUpdate as f, type LivenessCaptureHandle as g, type LivenessCaptureOptions as h, type VerificationEvents as i, type VerificationLocale as j, type VerificationOptions as k, type VerificationResult as l, type VerificationStatus as m, createLivenessCapture as n, createVerification as o, CLIP_MIME_ALLOWLIST as p, type CaptureEngine as q, type LivenessCaptureInternalHandle as r, type LivenessCaptureInternals as s, type LivenessFlowDeps as t, type LivenessFlowOutcome as u, PROCESSING_POLL_MAX as v, REGISTRY_RETRY_DELAY_MS as w, type SubmitExecutor as x, type SubmitRuntime as y, TRANSPORT_REPLAY_DELAY_MS as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { h as CaptureState$1, f as CaptureSessionV3Events, g as CaptureSessionV3Options, c as CaptureErrorKind$1 } from './capture-session-v3-
|
|
2
|
-
import { C as CheckReason, c as HostedSessionView, g as HostedClient, A as AttestationInput, h as SessionView, b as CheckType } from './hosted-client-
|
|
1
|
+
import { h as CaptureState$1, f as CaptureSessionV3Events, g as CaptureSessionV3Options, c as CaptureErrorKind$1 } from './capture-session-v3-DEInCOUg.cjs';
|
|
2
|
+
import { C as CheckReason, c as HostedSessionView, g as HostedClient, A as AttestationInput, h as SessionView, b as CheckType } from './hosted-client-DWzCRYJK.cjs';
|
|
3
3
|
|
|
4
4
|
/** Gate guidance code. `'hold'` is emitted while the clip records. */
|
|
5
5
|
type GateHint = "center" | "closer" | "farther" | "light" | "still" | "hold";
|
|
@@ -47,7 +47,30 @@ interface CapturedArtifacts {
|
|
|
47
47
|
captureChannel: CaptureChannel;
|
|
48
48
|
/** Set when the browser has no MediaRecorder: a keyframe-only capture. */
|
|
49
49
|
degraded?: "NO_RECORDER";
|
|
50
|
+
/** 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. */
|
|
51
|
+
engine?: CaptureEngineId;
|
|
52
|
+
/**
|
|
53
|
+
* Camera request (`getUserMedia`) → the preview is live, in whole
|
|
54
|
+
* milliseconds measured with `performance.now()`. Part of the face-capture
|
|
55
|
+
* timing the SDK forwards to the backend as `input.capture` on the liveness
|
|
56
|
+
* submission; absent when the phase was not observed.
|
|
57
|
+
*/
|
|
58
|
+
cameraReadyMs?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Camera ready → the first face ACCEPTED by the gate (present and with
|
|
61
|
+
* size, centering and quality good enough to make progress — not merely
|
|
62
|
+
* detected), whole ms. Absent when no face was ever accepted.
|
|
63
|
+
*/
|
|
64
|
+
faceAcquireMs?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Face-capture duration: FIRST accepted face → gate progress 100 % (capture
|
|
67
|
+
* complete, before the clip window and any upload), whole ms. A face lost
|
|
68
|
+
* and re-acquired keeps the first acceptance as its start.
|
|
69
|
+
*/
|
|
70
|
+
captureMs?: number;
|
|
50
71
|
}
|
|
72
|
+
/** Capture engine identifier carried on {@link CapturedArtifacts.engine}. */
|
|
73
|
+
type CaptureEngineId = "v1" | "v3";
|
|
51
74
|
/** Camera / engine failure kinds — collapsed to the public six. */
|
|
52
75
|
type CaptureErrorKind = "permission" | "notfound" | "inuse" | "insecure" | "unsupported" | "generic";
|
|
53
76
|
/** Camera / engine failure payload (`on('error')`). */
|
|
@@ -345,4 +368,4 @@ declare function createVerification(options: VerificationOptions): Verification;
|
|
|
345
368
|
/** {@link createVerification} with construction seams (tests / Sekyro-internal hosts). */
|
|
346
369
|
declare function createVerificationInternal(options: VerificationOptions, internals: VerificationInternals): Verification;
|
|
347
370
|
|
|
348
|
-
export { AttestationError as A,
|
|
371
|
+
export { AttestationError as A, type VerificationInternals as B, type CaptureChannel as C, DEFAULT_API_ORIGIN as D, createLivenessCaptureInternal as E, createVerificationInternal as F, type GateHint as G, type HostedClientLike as H, mapEngineState as I, mapErrorKind as J, mapGuidanceHint as K, type LivenessCaptureEvents as L, randomUuid as M, runLivenessFlow as N, runSubmission as O, PROCESSING_POLL_DELAY_MS as P, type ReasonCode as R, type SdkFailureReason as S, TRANSPORT_REPLAY_ATTEMPTS as T, type Verification as V, type CaptureEngineId as a, type CaptureError as b, type CaptureErrorKind as c, type CaptureState as d, type CapturedArtifacts as e, type GateUpdate as f, type LivenessCaptureHandle as g, type LivenessCaptureOptions as h, type VerificationEvents as i, type VerificationLocale as j, type VerificationOptions as k, type VerificationResult as l, type VerificationStatus as m, createLivenessCapture as n, createVerification as o, CLIP_MIME_ALLOWLIST as p, type CaptureEngine as q, type LivenessCaptureInternalHandle as r, type LivenessCaptureInternals as s, type LivenessFlowDeps as t, type LivenessFlowOutcome as u, PROCESSING_POLL_MAX as v, REGISTRY_RETRY_DELAY_MS as w, type SubmitExecutor as x, type SubmitRuntime as y, TRANSPORT_REPLAY_DELAY_MS as z };
|
|
@@ -190,6 +190,19 @@ interface LivenessInput {
|
|
|
190
190
|
* Client-declared by design (not a security boundary); absent = legacy
|
|
191
191
|
* clients, treated as mobile server-side during the rollout window. */
|
|
192
192
|
captureChannel?: 'mobile' | 'desktop';
|
|
193
|
+
/** Capture metadata (engine, dimensions, clip length, face-capture timing)
|
|
194
|
+
* — the backend's allowlisted, non-PII `capture` block (session insights). */
|
|
195
|
+
capture?: LivenessCaptureInput;
|
|
196
|
+
}
|
|
197
|
+
/** `LivenessInput.capture`: what the SDK's `captured` event measured. All ms are whole, ≥ 0. */
|
|
198
|
+
interface LivenessCaptureInput {
|
|
199
|
+
engine?: 'v1' | 'v3';
|
|
200
|
+
width?: number;
|
|
201
|
+
height?: number;
|
|
202
|
+
clipMs?: number;
|
|
203
|
+
cameraReadyMs?: number;
|
|
204
|
+
faceAcquireMs?: number;
|
|
205
|
+
captureMs?: number;
|
|
193
206
|
}
|
|
194
207
|
/**
|
|
195
208
|
* population_registry adapter input. `nni` is the 10-digit NNI for an UNBOUND
|
|
@@ -405,4 +418,4 @@ declare class HostedClient {
|
|
|
405
418
|
private api;
|
|
406
419
|
}
|
|
407
420
|
|
|
408
|
-
export { type AttestationInput as A, type CheckReason as C, type DocReason as D, type FaceMatchReason as F, type HostedOtpView as H, type LivenessReason as L, type MediaCheckType as M, type PhoneOtpReason as P, type RecordConsentResult as R, type SessionOutcome as S, type UploadMedia as U, type CheckState as a, type CheckType as b, type HostedSessionView as c, type HostedStepView as d, type PopulationReason as e, type SessionStatus as f, HostedClient as g, type SessionView as h, type CheckInputByType as i, type CompleteMediaResult as j, type ConsentLocale as k, type DocOcrInput as l, type DocSide as m, type FaceMatchInput as n, type HostedClientOptions as o, type
|
|
421
|
+
export { type AttestationInput as A, type CheckReason as C, type DocReason as D, type FaceMatchReason as F, type HostedOtpView as H, type LivenessReason as L, type MediaCheckType as M, type PhoneOtpReason as P, type RecordConsentResult as R, type SessionOutcome as S, type UploadMedia as U, type CheckState as a, type CheckType as b, type HostedSessionView as c, type HostedStepView as d, type PopulationReason as e, type SessionStatus as f, HostedClient as g, type SessionView as h, type CheckInputByType as i, type CompleteMediaResult as j, type ConsentLocale as k, type DocOcrInput as l, type DocSide as m, type FaceMatchInput as n, type HostedClientOptions as o, type LivenessCaptureInput as p, type LivenessInput as q, type MediaKind as r, type PhoneOtpInput as s, type PopulationInput as t, type PresignRequest as u, type PresignUploadResult as v, type SessionStepView as w, type SubmitCheckBody as x, type SubmitOptions as y, stripMimeParams as z };
|
|
@@ -190,6 +190,19 @@ interface LivenessInput {
|
|
|
190
190
|
* Client-declared by design (not a security boundary); absent = legacy
|
|
191
191
|
* clients, treated as mobile server-side during the rollout window. */
|
|
192
192
|
captureChannel?: 'mobile' | 'desktop';
|
|
193
|
+
/** Capture metadata (engine, dimensions, clip length, face-capture timing)
|
|
194
|
+
* — the backend's allowlisted, non-PII `capture` block (session insights). */
|
|
195
|
+
capture?: LivenessCaptureInput;
|
|
196
|
+
}
|
|
197
|
+
/** `LivenessInput.capture`: what the SDK's `captured` event measured. All ms are whole, ≥ 0. */
|
|
198
|
+
interface LivenessCaptureInput {
|
|
199
|
+
engine?: 'v1' | 'v3';
|
|
200
|
+
width?: number;
|
|
201
|
+
height?: number;
|
|
202
|
+
clipMs?: number;
|
|
203
|
+
cameraReadyMs?: number;
|
|
204
|
+
faceAcquireMs?: number;
|
|
205
|
+
captureMs?: number;
|
|
193
206
|
}
|
|
194
207
|
/**
|
|
195
208
|
* population_registry adapter input. `nni` is the 10-digit NNI for an UNBOUND
|
|
@@ -405,4 +418,4 @@ declare class HostedClient {
|
|
|
405
418
|
private api;
|
|
406
419
|
}
|
|
407
420
|
|
|
408
|
-
export { type AttestationInput as A, type CheckReason as C, type DocReason as D, type FaceMatchReason as F, type HostedOtpView as H, type LivenessReason as L, type MediaCheckType as M, type PhoneOtpReason as P, type RecordConsentResult as R, type SessionOutcome as S, type UploadMedia as U, type CheckState as a, type CheckType as b, type HostedSessionView as c, type HostedStepView as d, type PopulationReason as e, type SessionStatus as f, HostedClient as g, type SessionView as h, type CheckInputByType as i, type CompleteMediaResult as j, type ConsentLocale as k, type DocOcrInput as l, type DocSide as m, type FaceMatchInput as n, type HostedClientOptions as o, type
|
|
421
|
+
export { type AttestationInput as A, type CheckReason as C, type DocReason as D, type FaceMatchReason as F, type HostedOtpView as H, type LivenessReason as L, type MediaCheckType as M, type PhoneOtpReason as P, type RecordConsentResult as R, type SessionOutcome as S, type UploadMedia as U, type CheckState as a, type CheckType as b, type HostedSessionView as c, type HostedStepView as d, type PopulationReason as e, type SessionStatus as f, HostedClient as g, type SessionView as h, type CheckInputByType as i, type CompleteMediaResult as j, type ConsentLocale as k, type DocOcrInput as l, type DocSide as m, type FaceMatchInput as n, type HostedClientOptions as o, type LivenessCaptureInput as p, type LivenessInput as q, type MediaKind as r, type PhoneOtpInput as s, type PopulationInput as t, type PresignRequest as u, type PresignUploadResult as v, type SessionStepView as w, type SubmitCheckBody as x, type SubmitOptions as y, stripMimeParams as z };
|
package/dist/index.cjs
CHANGED
|
@@ -862,10 +862,12 @@ var V3_GATE_DEFAULTS = Object.freeze({
|
|
|
862
862
|
MOTION_TAU_S: 0.4,
|
|
863
863
|
MOTION_DEADBAND_IOD_PER_S: 0.1,
|
|
864
864
|
READY_WINDOW_MS: 500,
|
|
865
|
-
// 0.
|
|
866
|
-
//
|
|
867
|
-
//
|
|
868
|
-
|
|
865
|
+
// (READY_MEAN_Q, the former 0.75 window MEAN, is gone — 2026-10-17 field
|
|
866
|
+
// bug: a steady q anywhere in [Q_GOOD, 0.75) saturated p at 1, passed every
|
|
867
|
+
// guide ("hold still") and could never reach the mean, so the ring sat full
|
|
868
|
+
// and green with nothing recording. Readiness now checks the window against
|
|
869
|
+
// Q_GOOD, which keeps the one-flaky-tick forgiveness and the second-bad-tick
|
|
870
|
+
// block without a dead band above the rise threshold.)
|
|
869
871
|
GUIDE_SIZE: 0.6,
|
|
870
872
|
GUIDE_CENTERING: 0.6,
|
|
871
873
|
GUIDE_POSE: 0.6,
|
|
@@ -943,15 +945,15 @@ var FaceGateV3 = class {
|
|
|
943
945
|
const worstIndex = windowSamples.indexOf(worst);
|
|
944
946
|
windowSamples = windowSamples.filter((_, index) => index !== worstIndex);
|
|
945
947
|
}
|
|
946
|
-
const
|
|
947
|
-
const ready = this.p >= 1 && windowMean >= this.t.READY_MEAN_Q;
|
|
948
|
+
const ready = this.p >= 1 && windowSamples.every((sample) => sample >= this.t.Q_GOOD);
|
|
948
949
|
return {
|
|
949
950
|
at: timestampMs,
|
|
950
951
|
q,
|
|
951
952
|
p: this.p,
|
|
952
953
|
factors,
|
|
953
954
|
guidanceKey: this.guidanceOf(factors, quality, q),
|
|
954
|
-
ready
|
|
955
|
+
ready,
|
|
956
|
+
accepted: q >= this.t.Q_GOOD
|
|
955
957
|
};
|
|
956
958
|
}
|
|
957
959
|
geometryOf(observation, input) {
|
|
@@ -1069,6 +1071,11 @@ var CaptureSessionV3 = class {
|
|
|
1069
1071
|
this.profiler = null;
|
|
1070
1072
|
this.lastGuidanceKey = null;
|
|
1071
1073
|
this.positioningStartedAt = 0;
|
|
1074
|
+
// Face-capture timing marks of the CURRENT attempt (engine clock; reset per run).
|
|
1075
|
+
this.cameraRequestedAt = null;
|
|
1076
|
+
this.cameraReadyAt = null;
|
|
1077
|
+
this.faceAcquiredAt = null;
|
|
1078
|
+
this.captureCompleteAt = null;
|
|
1072
1079
|
this.fired = false;
|
|
1073
1080
|
this.carriedDegrade = 0;
|
|
1074
1081
|
this.carriedMeans = [];
|
|
@@ -1123,6 +1130,10 @@ var CaptureSessionV3 = class {
|
|
|
1123
1130
|
this.lastGuidanceKey = null;
|
|
1124
1131
|
this.carriedDegrade = 0;
|
|
1125
1132
|
this.carriedMeans = [];
|
|
1133
|
+
this.cameraRequestedAt = null;
|
|
1134
|
+
this.cameraReadyAt = null;
|
|
1135
|
+
this.faceAcquiredAt = null;
|
|
1136
|
+
this.captureCompleteAt = null;
|
|
1126
1137
|
this.setState("preflight");
|
|
1127
1138
|
const preflight = cameraPreflight();
|
|
1128
1139
|
if (preflight !== "OK") {
|
|
@@ -1132,6 +1143,7 @@ var CaptureSessionV3 = class {
|
|
|
1132
1143
|
this.setState("acquiring");
|
|
1133
1144
|
const getUserMedia = options.getUserMedia ?? ((constraints) => navigator.mediaDevices.getUserMedia(constraints));
|
|
1134
1145
|
let stream;
|
|
1146
|
+
this.cameraRequestedAt = this.now();
|
|
1135
1147
|
try {
|
|
1136
1148
|
stream = await getUserMedia(buildCaptureConstraints(detectIsMobile(), this.facing));
|
|
1137
1149
|
} catch (err) {
|
|
@@ -1147,6 +1159,7 @@ var CaptureSessionV3 = class {
|
|
|
1147
1159
|
options.video.srcObject = stream;
|
|
1148
1160
|
await options.video.play().catch(() => void 0);
|
|
1149
1161
|
if (attempt !== this.attempt) return;
|
|
1162
|
+
this.cameraReadyAt = this.now();
|
|
1150
1163
|
if (this.detector === null) {
|
|
1151
1164
|
const ladderOptions = {
|
|
1152
1165
|
...options.v3AssetBaseUrl !== void 0 ? { v3AssetBaseUrl: options.v3AssetBaseUrl } : {}
|
|
@@ -1246,6 +1259,7 @@ var CaptureSessionV3 = class {
|
|
|
1246
1259
|
frameWidth: video.videoWidth,
|
|
1247
1260
|
frameHeight: video.videoHeight
|
|
1248
1261
|
});
|
|
1262
|
+
if (tick.accepted && this.faceAcquiredAt === null) this.faceAcquiredAt = tick.at;
|
|
1249
1263
|
this.emit("checks", {
|
|
1250
1264
|
engine: "v3",
|
|
1251
1265
|
progress: tick.p,
|
|
@@ -1259,6 +1273,7 @@ var CaptureSessionV3 = class {
|
|
|
1259
1273
|
}
|
|
1260
1274
|
if (tick.ready && this.stateValue === "positioning") {
|
|
1261
1275
|
this.fired = true;
|
|
1276
|
+
this.captureCompleteAt = tick.at;
|
|
1262
1277
|
void this.fire(attempt);
|
|
1263
1278
|
}
|
|
1264
1279
|
}
|
|
@@ -1353,7 +1368,21 @@ var CaptureSessionV3 = class {
|
|
|
1353
1368
|
finishCapture(artifacts) {
|
|
1354
1369
|
this.stopTracks();
|
|
1355
1370
|
this.setState("captured");
|
|
1356
|
-
this.
|
|
1371
|
+
const timing = this.captureTiming();
|
|
1372
|
+
this.emit("artifacts", timing === void 0 ? artifacts : { ...artifacts, timing });
|
|
1373
|
+
}
|
|
1374
|
+
/** The attempt's capture-phase timing (whole ms, ≥ 0); undefined when no mark landed. */
|
|
1375
|
+
captureTiming() {
|
|
1376
|
+
const span = (from, to) => from !== null && to !== null ? Math.max(0, Math.round(to - from)) : void 0;
|
|
1377
|
+
const cameraReadyMs = span(this.cameraRequestedAt, this.cameraReadyAt);
|
|
1378
|
+
const faceAcquireMs = span(this.cameraReadyAt, this.faceAcquiredAt);
|
|
1379
|
+
const captureMs = span(this.faceAcquiredAt, this.captureCompleteAt);
|
|
1380
|
+
const timing = {
|
|
1381
|
+
...cameraReadyMs !== void 0 ? { cameraReadyMs } : {},
|
|
1382
|
+
...faceAcquireMs !== void 0 ? { faceAcquireMs } : {},
|
|
1383
|
+
...captureMs !== void 0 ? { captureMs } : {}
|
|
1384
|
+
};
|
|
1385
|
+
return Object.keys(timing).length > 0 ? timing : void 0;
|
|
1357
1386
|
}
|
|
1358
1387
|
// ── defaults for the canvas-bound seams ────────────────────────────────────
|
|
1359
1388
|
async defaultKeyframe(video) {
|
|
@@ -1562,6 +1591,14 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
1562
1591
|
let animations = "full";
|
|
1563
1592
|
let recordingStartedAt = null;
|
|
1564
1593
|
let frozenAt = null;
|
|
1594
|
+
let frameWidth = 0;
|
|
1595
|
+
let frameHeight = 0;
|
|
1596
|
+
const latchFrameSize = () => {
|
|
1597
|
+
if (options.video.videoWidth > 0 && options.video.videoHeight > 0) {
|
|
1598
|
+
frameWidth = options.video.videoWidth;
|
|
1599
|
+
frameHeight = options.video.videoHeight;
|
|
1600
|
+
}
|
|
1601
|
+
};
|
|
1565
1602
|
const setState = (next) => {
|
|
1566
1603
|
state = next;
|
|
1567
1604
|
emitter.emit("state", next);
|
|
@@ -1582,10 +1619,13 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
1582
1619
|
faceDetected = false;
|
|
1583
1620
|
recordingStartedAt = null;
|
|
1584
1621
|
frozenAt = null;
|
|
1622
|
+
frameWidth = 0;
|
|
1623
|
+
frameHeight = 0;
|
|
1585
1624
|
}
|
|
1586
1625
|
setState(next);
|
|
1587
1626
|
syncProfile();
|
|
1588
1627
|
if (next === "recording") {
|
|
1628
|
+
latchFrameSize();
|
|
1589
1629
|
recordingStartedAt = now();
|
|
1590
1630
|
hint = "hold";
|
|
1591
1631
|
progress = 1;
|
|
@@ -1593,6 +1633,7 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
1593
1633
|
}
|
|
1594
1634
|
}),
|
|
1595
1635
|
engine.on("checks", (payload) => {
|
|
1636
|
+
latchFrameSize();
|
|
1596
1637
|
progress = payload.progress;
|
|
1597
1638
|
faceDetected = payload.factors.presence > 0;
|
|
1598
1639
|
emitGate();
|
|
@@ -1612,11 +1653,16 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
1612
1653
|
keyframe: artifacts.keyframe,
|
|
1613
1654
|
...artifacts.clip !== void 0 ? { clip: artifacts.clip } : {},
|
|
1614
1655
|
...artifacts.clipMimeType !== void 0 ? { clipMime: artifacts.clipMimeType } : {},
|
|
1615
|
-
width: options.video.videoWidth,
|
|
1616
|
-
height: options.video.videoHeight,
|
|
1656
|
+
width: options.video.videoWidth || frameWidth,
|
|
1657
|
+
height: options.video.videoHeight || frameHeight,
|
|
1617
1658
|
...clipMs !== void 0 ? { clipMs } : {},
|
|
1618
1659
|
captureChannel: detectIsMobile() ? "mobile" : "desktop",
|
|
1619
|
-
...degraded ? { degraded: "NO_RECORDER" } : {}
|
|
1660
|
+
...degraded ? { degraded: "NO_RECORDER" } : {},
|
|
1661
|
+
engine: "v3",
|
|
1662
|
+
// Face-capture timing: the engine's marks, forwarded flat (absent → absent).
|
|
1663
|
+
...artifacts.timing?.cameraReadyMs !== void 0 ? { cameraReadyMs: artifacts.timing.cameraReadyMs } : {},
|
|
1664
|
+
...artifacts.timing?.faceAcquireMs !== void 0 ? { faceAcquireMs: artifacts.timing.faceAcquireMs } : {},
|
|
1665
|
+
...artifacts.timing?.captureMs !== void 0 ? { captureMs: artifacts.timing.captureMs } : {}
|
|
1620
1666
|
});
|
|
1621
1667
|
}),
|
|
1622
1668
|
engine.on("error", ({ kind, retryable }) => {
|
|
@@ -2191,7 +2237,12 @@ function buildLivenessSubmit(deps, clip, bareMime) {
|
|
|
2191
2237
|
deps.onPhase("checking");
|
|
2192
2238
|
return client.submitCheck(
|
|
2193
2239
|
"liveness",
|
|
2194
|
-
{
|
|
2240
|
+
{
|
|
2241
|
+
clipKey,
|
|
2242
|
+
attestation,
|
|
2243
|
+
captureChannel: deps.artifacts.captureChannel,
|
|
2244
|
+
capture: captureInputOf(deps.artifacts)
|
|
2245
|
+
},
|
|
2195
2246
|
{ idempotencyKey }
|
|
2196
2247
|
);
|
|
2197
2248
|
},
|
|
@@ -2202,6 +2253,17 @@ function buildLivenessSubmit(deps, clip, bareMime) {
|
|
|
2202
2253
|
}
|
|
2203
2254
|
);
|
|
2204
2255
|
}
|
|
2256
|
+
function captureInputOf(artifacts) {
|
|
2257
|
+
return {
|
|
2258
|
+
...artifacts.engine !== void 0 ? { engine: artifacts.engine } : {},
|
|
2259
|
+
width: artifacts.width,
|
|
2260
|
+
height: artifacts.height,
|
|
2261
|
+
...artifacts.clipMs !== void 0 ? { clipMs: artifacts.clipMs } : {},
|
|
2262
|
+
...artifacts.cameraReadyMs !== void 0 ? { cameraReadyMs: artifacts.cameraReadyMs } : {},
|
|
2263
|
+
...artifacts.faceAcquireMs !== void 0 ? { faceAcquireMs: artifacts.faceAcquireMs } : {},
|
|
2264
|
+
...artifacts.captureMs !== void 0 ? { captureMs: artifacts.captureMs } : {}
|
|
2265
|
+
};
|
|
2266
|
+
}
|
|
2205
2267
|
function buildFaceMatchSubmit(deps, keyframe) {
|
|
2206
2268
|
let imageKey = null;
|
|
2207
2269
|
return () => runSubmission(deps, async (client, idempotencyKey) => {
|