@moveris/shared 3.8.6 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -56,6 +56,8 @@ const client = new LivenessClient(config: LivenessClientConfig);
56
56
  | `enableRetry` | `boolean` | `true` | Enable automatic retry with exponential backoff |
57
57
  | `customFetch` | `typeof fetch` | `fetch` | Custom fetch implementation (for React Native) |
58
58
  | `deviceIntelligenceOverrides` | `DeviceIntelligenceOverrides` | - | Static overrides merged into every `device_intelligence` payload (e.g. `{ vpn_detected: true }`) |
59
+ | `consumer` | `ConsumerContext` | - | Consumer app context — traces which app and environment submitted each transaction |
60
+ | `trackClientTime` | `boolean` | `false` | When true, fires a fire-and-forget PATCH after each verdict to record end-to-end client duration |
59
61
 
60
62
  #### Methods
61
63
 
@@ -152,6 +154,17 @@ const result = await client.hybrid50(frames, { fps: 30 });
152
154
  const result = await client.hybrid150(frames, { fps: 30 });
153
155
  ```
154
156
 
157
+ ##### `postClientTime(sessionId, clientTime)`
158
+
159
+ Fire-and-forget PATCH to record end-to-end client duration for a completed verification session. No-op when `trackClientTime` is `false`. Swallows all errors silently.
160
+
161
+ ```typescript
162
+ // Called automatically by useLiveness / CognitoCheckWidget after the verdict.
163
+ // Approach B consumers can call it manually after onComplete resolves:
164
+ const elapsed = Math.round(performance.now() - startTime);
165
+ void client.postClientTime(result.sessionId, elapsed);
166
+ ```
167
+
155
168
  ##### `updateDeviceIntelligenceOverrides(overrides)`
156
169
 
157
170
  Merge additional fields into the cached device intelligence payload. Call this after construction to inject data only available at runtime (e.g. camera specs, VPN detection results). Merges shallowly — later calls are merged on top of earlier ones.
@@ -254,6 +267,27 @@ Deprecated models (v1 — sunset 2026-09-01):
254
267
  | `'mixed-150'` | 150 | — |
255
268
  | `'mixed-250'` | 250 | — |
256
269
 
270
+ #### ConsumerContext
271
+
272
+ Consumer app context attached to every verification request for transaction tracing.
273
+
274
+ ```typescript
275
+ interface ConsumerContext {
276
+ url: string; // The consumer app's URL
277
+ env: 'development' | 'staging' | 'production'; // Consumer app environment
278
+ }
279
+ ```
280
+
281
+ Pass it at client construction — it is included in every subsequent request automatically:
282
+
283
+ ```typescript
284
+ const client = new LivenessClient({
285
+ apiKey: 'mv_your_api_key',
286
+ consumer: { url: 'https://app.example.com', env: 'production' },
287
+ trackClientTime: true, // optional — fires postClientTime after each verdict
288
+ });
289
+ ```
290
+
257
291
  #### FrameSource
258
292
 
259
293
  Source of the captured frames.
@@ -308,6 +342,7 @@ interface LivenessResult {
308
342
  processingMs: number; // Server processing time
309
343
  framesProcessed: number; // Number of frames analyzed
310
344
  deprecation?: DeprecationInfo; // Present when X-Moveris-Model-Resolved header is returned
345
+ clientTime?: number; // End-to-end client duration in ms (start() to verdict received)
311
346
  }
312
347
  ```
313
348
 
@@ -856,6 +891,7 @@ import type {
856
891
  Verdict,
857
892
  CapturedFrame,
858
893
  CropData,
894
+ ConsumerContext,
859
895
  LivenessClientConfig,
860
896
  DetectionResult,
861
897
  DetectionSummary,
package/dist/index.d.mts CHANGED
@@ -26,6 +26,13 @@ type DeviceIntelligenceOverrides = {
26
26
  };
27
27
 
28
28
  type Verdict = 'live' | 'fake' | 'inconclusive';
29
+ type MetadataScalar = string | number | boolean | null;
30
+ type ExtraMetadataValue = MetadataScalar | Record<string, MetadataScalar>;
31
+ type ExtraMetadata = Record<string, ExtraMetadataValue>;
32
+ interface ConsumerContext {
33
+ url: string;
34
+ env: 'development' | 'staging' | 'production';
35
+ }
29
36
  interface ModelEntry {
30
37
  id: string;
31
38
  label: string;
@@ -68,6 +75,9 @@ interface FastCheckRequest {
68
75
  frame_count?: number;
69
76
  warnings?: string[];
70
77
  device_intelligence?: DeviceIntelligence;
78
+ metadata?: {
79
+ consumer?: ConsumerContext;
80
+ } | null;
71
81
  }
72
82
  interface FastCheckCropsRequest {
73
83
  session_id: string;
@@ -76,6 +86,9 @@ interface FastCheckCropsRequest {
76
86
  crops: CropData[];
77
87
  frame_count?: number;
78
88
  device_intelligence?: DeviceIntelligence;
89
+ metadata?: {
90
+ consumer?: ConsumerContext;
91
+ } | null;
79
92
  }
80
93
  interface VerifyRequest {
81
94
  session_id: string;
@@ -108,6 +121,9 @@ interface FastCheckStreamRequest {
108
121
  frame_count?: number;
109
122
  warnings?: string[];
110
123
  device_intelligence?: DeviceIntelligence;
124
+ metadata?: {
125
+ consumer?: ConsumerContext;
126
+ } | null;
111
127
  }
112
128
  interface FastCheckResponse {
113
129
  verdict: Verdict | null;
@@ -208,6 +224,7 @@ interface LivenessResult {
208
224
  framesProcessed: number;
209
225
  warnings?: string[];
210
226
  deprecation?: DeprecationInfo;
227
+ clientTime?: number;
211
228
  }
212
229
  type LivenessState = 'idle' | 'capturing' | 'uploading' | 'processing' | 'complete' | 'error';
213
230
  interface LivenessConfig {
@@ -567,6 +584,9 @@ interface LivenessClientConfig {
567
584
  enableRetry?: boolean;
568
585
  customFetch?: typeof fetch;
569
586
  deviceIntelligenceOverrides?: DeviceIntelligenceOverrides;
587
+ consumer?: ConsumerContext;
588
+ trackClientTime?: boolean;
589
+ extraMetadata?: ExtraMetadata;
570
590
  }
571
591
  declare class LivenessApiError extends Error {
572
592
  readonly code: string;
@@ -587,12 +607,16 @@ declare class LivenessClient {
587
607
  private readonly timeout;
588
608
  private readonly enableRetry;
589
609
  private readonly fetchFn;
610
+ private readonly consumer;
611
+ private readonly trackClientTime;
612
+ private readonly extraMetadata;
590
613
  private diCollected;
591
614
  private diCollecting;
592
615
  private diOverrides;
593
616
  constructor(config: LivenessClientConfig);
594
617
  updateDeviceIntelligenceOverrides(partial: DeviceIntelligenceOverrides): void;
595
618
  private getDeviceIntelligence;
619
+ private buildMetadata;
596
620
  private applyDiOverrides;
597
621
  private request;
598
622
  private requestRaw;
@@ -607,6 +631,7 @@ declare class LivenessClient {
607
631
  health(): Promise<HealthResponse>;
608
632
  getModels(): Promise<ModelEntry[]>;
609
633
  queueStats(): Promise<QueueStatsResponse>;
634
+ postClientTime(sessionId: string, clientTime: number): Promise<void>;
610
635
  fastCheck(frames: CapturedFrame[], options?: {
611
636
  sessionId?: string;
612
637
  model?: FastCheckModel;
@@ -728,6 +753,7 @@ declare const API_PATHS: {
728
753
  readonly hybrid150: "/api/v1/hybrid-150";
729
754
  readonly jobResult: "/api/v1/result";
730
755
  readonly queueStats: "/api/v1/queue/stats";
756
+ readonly sessions: "/api/v1/sessions";
731
757
  };
732
758
  declare const RETRY_CONFIG: {
733
759
  readonly maxAttempts: 3;
@@ -942,4 +968,4 @@ declare function collectDeviceIntelligence(opts?: {
942
968
  platformVersion?: string;
943
969
  }): Promise<DeviceIntelligence | null>;
944
970
 
945
- export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, CAMERA_ANGLE_HIGH_RATIO, CAMERA_ANGLE_LOW_RATIO, type CameraAngleResult, type CameraCapabilities, type CameraRequirements, type CameraValidationResult, type CaptureQualityState, type CapturedFrame, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_CAMERA_REQUIREMENTS, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, DYNAMIC_RANGE_WARNING_THRESHOLD, type DeprecationInfo, type DetectionResult, type DetectionSummary, type DetectorConfig, type DeviceIntelligence, type DeviceIntelligenceCamera, type DeviceIntelligenceGeo, type DeviceIntelligenceOverrides, type DynamicRangeAnalysis, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CROP_FRAME_MARGIN, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceRollResult, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MAX_FACE_ROLL_DEGREES, MAX_IDEAL_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_FACE_AREA_RATIO, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_IDEAL_FACE_RATIO, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelVersion, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, SHARED_SDK_PLATFORM, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, VALID_FRAME_COUNTS, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeDynamicRange, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, collectDeviceIntelligence, decodeBase64, detectCameraAngle, detectFaceRoll, detectFaceRollFromMatrix, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, linearRgbToLabL, retryWithBackoff, rgbaToGrayscale, sleep, srgbToLinear, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
971
+ export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, CAMERA_ANGLE_HIGH_RATIO, CAMERA_ANGLE_LOW_RATIO, type CameraAngleResult, type CameraCapabilities, type CameraRequirements, type CameraValidationResult, type CaptureQualityState, type CapturedFrame, type ConsumerContext, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_CAMERA_REQUIREMENTS, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, DYNAMIC_RANGE_WARNING_THRESHOLD, type DeprecationInfo, type DetectionResult, type DetectionSummary, type DetectorConfig, type DeviceIntelligence, type DeviceIntelligenceCamera, type DeviceIntelligenceGeo, type DeviceIntelligenceOverrides, type DynamicRangeAnalysis, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type ExtraMetadata, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CROP_FRAME_MARGIN, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceRollResult, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MAX_FACE_ROLL_DEGREES, MAX_IDEAL_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_FACE_AREA_RATIO, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_IDEAL_FACE_RATIO, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelVersion, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, SHARED_SDK_PLATFORM, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, VALID_FRAME_COUNTS, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeDynamicRange, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, collectDeviceIntelligence, decodeBase64, detectCameraAngle, detectFaceRoll, detectFaceRollFromMatrix, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, linearRgbToLabL, retryWithBackoff, rgbaToGrayscale, sleep, srgbToLinear, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
package/dist/index.d.ts CHANGED
@@ -26,6 +26,13 @@ type DeviceIntelligenceOverrides = {
26
26
  };
27
27
 
28
28
  type Verdict = 'live' | 'fake' | 'inconclusive';
29
+ type MetadataScalar = string | number | boolean | null;
30
+ type ExtraMetadataValue = MetadataScalar | Record<string, MetadataScalar>;
31
+ type ExtraMetadata = Record<string, ExtraMetadataValue>;
32
+ interface ConsumerContext {
33
+ url: string;
34
+ env: 'development' | 'staging' | 'production';
35
+ }
29
36
  interface ModelEntry {
30
37
  id: string;
31
38
  label: string;
@@ -68,6 +75,9 @@ interface FastCheckRequest {
68
75
  frame_count?: number;
69
76
  warnings?: string[];
70
77
  device_intelligence?: DeviceIntelligence;
78
+ metadata?: {
79
+ consumer?: ConsumerContext;
80
+ } | null;
71
81
  }
72
82
  interface FastCheckCropsRequest {
73
83
  session_id: string;
@@ -76,6 +86,9 @@ interface FastCheckCropsRequest {
76
86
  crops: CropData[];
77
87
  frame_count?: number;
78
88
  device_intelligence?: DeviceIntelligence;
89
+ metadata?: {
90
+ consumer?: ConsumerContext;
91
+ } | null;
79
92
  }
80
93
  interface VerifyRequest {
81
94
  session_id: string;
@@ -108,6 +121,9 @@ interface FastCheckStreamRequest {
108
121
  frame_count?: number;
109
122
  warnings?: string[];
110
123
  device_intelligence?: DeviceIntelligence;
124
+ metadata?: {
125
+ consumer?: ConsumerContext;
126
+ } | null;
111
127
  }
112
128
  interface FastCheckResponse {
113
129
  verdict: Verdict | null;
@@ -208,6 +224,7 @@ interface LivenessResult {
208
224
  framesProcessed: number;
209
225
  warnings?: string[];
210
226
  deprecation?: DeprecationInfo;
227
+ clientTime?: number;
211
228
  }
212
229
  type LivenessState = 'idle' | 'capturing' | 'uploading' | 'processing' | 'complete' | 'error';
213
230
  interface LivenessConfig {
@@ -567,6 +584,9 @@ interface LivenessClientConfig {
567
584
  enableRetry?: boolean;
568
585
  customFetch?: typeof fetch;
569
586
  deviceIntelligenceOverrides?: DeviceIntelligenceOverrides;
587
+ consumer?: ConsumerContext;
588
+ trackClientTime?: boolean;
589
+ extraMetadata?: ExtraMetadata;
570
590
  }
571
591
  declare class LivenessApiError extends Error {
572
592
  readonly code: string;
@@ -587,12 +607,16 @@ declare class LivenessClient {
587
607
  private readonly timeout;
588
608
  private readonly enableRetry;
589
609
  private readonly fetchFn;
610
+ private readonly consumer;
611
+ private readonly trackClientTime;
612
+ private readonly extraMetadata;
590
613
  private diCollected;
591
614
  private diCollecting;
592
615
  private diOverrides;
593
616
  constructor(config: LivenessClientConfig);
594
617
  updateDeviceIntelligenceOverrides(partial: DeviceIntelligenceOverrides): void;
595
618
  private getDeviceIntelligence;
619
+ private buildMetadata;
596
620
  private applyDiOverrides;
597
621
  private request;
598
622
  private requestRaw;
@@ -607,6 +631,7 @@ declare class LivenessClient {
607
631
  health(): Promise<HealthResponse>;
608
632
  getModels(): Promise<ModelEntry[]>;
609
633
  queueStats(): Promise<QueueStatsResponse>;
634
+ postClientTime(sessionId: string, clientTime: number): Promise<void>;
610
635
  fastCheck(frames: CapturedFrame[], options?: {
611
636
  sessionId?: string;
612
637
  model?: FastCheckModel;
@@ -728,6 +753,7 @@ declare const API_PATHS: {
728
753
  readonly hybrid150: "/api/v1/hybrid-150";
729
754
  readonly jobResult: "/api/v1/result";
730
755
  readonly queueStats: "/api/v1/queue/stats";
756
+ readonly sessions: "/api/v1/sessions";
731
757
  };
732
758
  declare const RETRY_CONFIG: {
733
759
  readonly maxAttempts: 3;
@@ -942,4 +968,4 @@ declare function collectDeviceIntelligence(opts?: {
942
968
  platformVersion?: string;
943
969
  }): Promise<DeviceIntelligence | null>;
944
970
 
945
- export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, CAMERA_ANGLE_HIGH_RATIO, CAMERA_ANGLE_LOW_RATIO, type CameraAngleResult, type CameraCapabilities, type CameraRequirements, type CameraValidationResult, type CaptureQualityState, type CapturedFrame, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_CAMERA_REQUIREMENTS, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, DYNAMIC_RANGE_WARNING_THRESHOLD, type DeprecationInfo, type DetectionResult, type DetectionSummary, type DetectorConfig, type DeviceIntelligence, type DeviceIntelligenceCamera, type DeviceIntelligenceGeo, type DeviceIntelligenceOverrides, type DynamicRangeAnalysis, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CROP_FRAME_MARGIN, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceRollResult, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MAX_FACE_ROLL_DEGREES, MAX_IDEAL_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_FACE_AREA_RATIO, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_IDEAL_FACE_RATIO, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelVersion, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, SHARED_SDK_PLATFORM, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, VALID_FRAME_COUNTS, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeDynamicRange, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, collectDeviceIntelligence, decodeBase64, detectCameraAngle, detectFaceRoll, detectFaceRollFromMatrix, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, linearRgbToLabL, retryWithBackoff, rgbaToGrayscale, sleep, srgbToLinear, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
971
+ export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, CAMERA_ANGLE_HIGH_RATIO, CAMERA_ANGLE_LOW_RATIO, type CameraAngleResult, type CameraCapabilities, type CameraRequirements, type CameraValidationResult, type CaptureQualityState, type CapturedFrame, type ConsumerContext, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_CAMERA_REQUIREMENTS, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, DYNAMIC_RANGE_WARNING_THRESHOLD, type DeprecationInfo, type DetectionResult, type DetectionSummary, type DetectorConfig, type DeviceIntelligence, type DeviceIntelligenceCamera, type DeviceIntelligenceGeo, type DeviceIntelligenceOverrides, type DynamicRangeAnalysis, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type ExtraMetadata, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CROP_FRAME_MARGIN, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceRollResult, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MAX_FACE_ROLL_DEGREES, MAX_IDEAL_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_FACE_AREA_RATIO, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_IDEAL_FACE_RATIO, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelVersion, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, SHARED_SDK_PLATFORM, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, VALID_FRAME_COUNTS, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeDynamicRange, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, collectDeviceIntelligence, decodeBase64, detectCameraAngle, detectFaceRoll, detectFaceRollFromMatrix, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, linearRgbToLabL, retryWithBackoff, rgbaToGrayscale, sleep, srgbToLinear, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
package/dist/index.js CHANGED
@@ -158,7 +158,8 @@ var API_PATHS = {
158
158
  hybrid50: "/api/v1/hybrid-50",
159
159
  hybrid150: "/api/v1/hybrid-150",
160
160
  jobResult: "/api/v1/result",
161
- queueStats: "/api/v1/queue/stats"
161
+ queueStats: "/api/v1/queue/stats",
162
+ sessions: "/api/v1/sessions"
162
163
  };
163
164
  var RETRY_CONFIG = {
164
165
  maxAttempts: 3,
@@ -238,7 +239,7 @@ async function sleep(ms) {
238
239
  }
239
240
 
240
241
  // package.json
241
- var version = "3.8.6";
242
+ var version = "3.10.0";
242
243
 
243
244
  // src/utils/deviceIntelligence.ts
244
245
  var IPINFO_URL = "https://ipinfo.io/json";
@@ -386,6 +387,9 @@ var LivenessClient = class _LivenessClient {
386
387
  this.enableRetry = config.enableRetry ?? true;
387
388
  this.fetchFn = config.customFetch ?? (typeof window !== "undefined" ? fetch.bind(window) : fetch);
388
389
  this.diOverrides = { ...config.deviceIntelligenceOverrides };
390
+ this.consumer = config.consumer;
391
+ this.trackClientTime = config.trackClientTime ?? false;
392
+ this.extraMetadata = config.extraMetadata;
389
393
  }
390
394
  /**
391
395
  * Merge additional device intelligence overrides into the existing set.
@@ -419,6 +423,13 @@ var LivenessClient = class _LivenessClient {
419
423
  await this.diCollecting;
420
424
  return this.diCollected ? this.applyDiOverrides(this.diCollected) : null;
421
425
  }
426
+ buildMetadata() {
427
+ const meta = {
428
+ ...this.consumer ? { consumer: this.consumer } : {},
429
+ ...this.extraMetadata
430
+ };
431
+ return Object.keys(meta).length > 0 ? meta : void 0;
432
+ }
422
433
  applyDiOverrides(collected) {
423
434
  const ov = this.diOverrides;
424
435
  return {
@@ -634,6 +645,25 @@ var LivenessClient = class _LivenessClient {
634
645
  async queueStats() {
635
646
  return this.request(API_PATHS.queueStats);
636
647
  }
648
+ /**
649
+ * Post end-to-end client duration for a completed verification session.
650
+ * Fire-and-forget — swallows all errors, no retry.
651
+ * No-op when `trackClientTime` is false (default).
652
+ */
653
+ async postClientTime(sessionId, clientTime) {
654
+ if (!this.trackClientTime) return;
655
+ try {
656
+ await this.fetchFn(`${this.baseUrl}${API_PATHS.sessions}/${sessionId}/client-time`, {
657
+ method: "PATCH",
658
+ headers: {
659
+ "Content-Type": "application/json",
660
+ [AUTH_CONFIG.apiKeyHeader]: this.apiKey
661
+ },
662
+ body: JSON.stringify({ client_time: clientTime })
663
+ });
664
+ } catch {
665
+ }
666
+ }
637
667
  // ===========================================================================
638
668
  // Fast Check Endpoints
639
669
  // ===========================================================================
@@ -654,7 +684,8 @@ var LivenessClient = class _LivenessClient {
654
684
  frames: toFrameData(frames),
655
685
  ...options.frameCount != null ? { frame_count: options.frameCount } : {},
656
686
  ...options.warnings?.length ? { warnings: options.warnings } : {},
657
- ...di ? { device_intelligence: di } : {}
687
+ ...di ? { device_intelligence: di } : {},
688
+ ...this.buildMetadata() ? { metadata: this.buildMetadata() } : {}
658
689
  };
659
690
  const { data: response, headers } = await this.requestWithRetryRaw(
660
691
  API_PATHS.fastCheck,
@@ -691,7 +722,8 @@ var LivenessClient = class _LivenessClient {
691
722
  ...options.frameCount != null ? { frame_count: options.frameCount } : {},
692
723
  ...options.warnings?.length ? { warnings: options.warnings } : {},
693
724
  ...options.bgSegmentation !== void 0 ? { bg_segmentation: options.bgSegmentation } : {},
694
- ...di ? { device_intelligence: di } : {}
725
+ ...di ? { device_intelligence: di } : {},
726
+ ...this.buildMetadata() ? { metadata: this.buildMetadata() } : {}
695
727
  };
696
728
  const { data: response, headers } = await this.requestWithRetryRaw(
697
729
  API_PATHS.fastCheckCrops,
@@ -755,7 +787,8 @@ var LivenessClient = class _LivenessClient {
755
787
  frame: frameData,
756
788
  ...options.frameCount != null ? { frame_count: options.frameCount } : {},
757
789
  ...options.warnings?.length ? { warnings: options.warnings } : {},
758
- ...di ? { device_intelligence: di } : {}
790
+ ...di ? { device_intelligence: di } : {},
791
+ ...this.buildMetadata() ? { metadata: this.buildMetadata() } : {}
759
792
  };
760
793
  return this.requestWithRetry(API_PATHS.fastCheckStream, {
761
794
  method: "POST",
package/dist/index.mjs CHANGED
@@ -16,7 +16,8 @@ var API_PATHS = {
16
16
  hybrid50: "/api/v1/hybrid-50",
17
17
  hybrid150: "/api/v1/hybrid-150",
18
18
  jobResult: "/api/v1/result",
19
- queueStats: "/api/v1/queue/stats"
19
+ queueStats: "/api/v1/queue/stats",
20
+ sessions: "/api/v1/sessions"
20
21
  };
21
22
  var RETRY_CONFIG = {
22
23
  maxAttempts: 3,
@@ -96,7 +97,7 @@ async function sleep(ms) {
96
97
  }
97
98
 
98
99
  // package.json
99
- var version = "3.8.6";
100
+ var version = "3.10.0";
100
101
 
101
102
  // src/utils/deviceIntelligence.ts
102
103
  var IPINFO_URL = "https://ipinfo.io/json";
@@ -244,6 +245,9 @@ var LivenessClient = class _LivenessClient {
244
245
  this.enableRetry = config.enableRetry ?? true;
245
246
  this.fetchFn = config.customFetch ?? (typeof window !== "undefined" ? fetch.bind(window) : fetch);
246
247
  this.diOverrides = { ...config.deviceIntelligenceOverrides };
248
+ this.consumer = config.consumer;
249
+ this.trackClientTime = config.trackClientTime ?? false;
250
+ this.extraMetadata = config.extraMetadata;
247
251
  }
248
252
  /**
249
253
  * Merge additional device intelligence overrides into the existing set.
@@ -277,6 +281,13 @@ var LivenessClient = class _LivenessClient {
277
281
  await this.diCollecting;
278
282
  return this.diCollected ? this.applyDiOverrides(this.diCollected) : null;
279
283
  }
284
+ buildMetadata() {
285
+ const meta = {
286
+ ...this.consumer ? { consumer: this.consumer } : {},
287
+ ...this.extraMetadata
288
+ };
289
+ return Object.keys(meta).length > 0 ? meta : void 0;
290
+ }
280
291
  applyDiOverrides(collected) {
281
292
  const ov = this.diOverrides;
282
293
  return {
@@ -492,6 +503,25 @@ var LivenessClient = class _LivenessClient {
492
503
  async queueStats() {
493
504
  return this.request(API_PATHS.queueStats);
494
505
  }
506
+ /**
507
+ * Post end-to-end client duration for a completed verification session.
508
+ * Fire-and-forget — swallows all errors, no retry.
509
+ * No-op when `trackClientTime` is false (default).
510
+ */
511
+ async postClientTime(sessionId, clientTime) {
512
+ if (!this.trackClientTime) return;
513
+ try {
514
+ await this.fetchFn(`${this.baseUrl}${API_PATHS.sessions}/${sessionId}/client-time`, {
515
+ method: "PATCH",
516
+ headers: {
517
+ "Content-Type": "application/json",
518
+ [AUTH_CONFIG.apiKeyHeader]: this.apiKey
519
+ },
520
+ body: JSON.stringify({ client_time: clientTime })
521
+ });
522
+ } catch {
523
+ }
524
+ }
495
525
  // ===========================================================================
496
526
  // Fast Check Endpoints
497
527
  // ===========================================================================
@@ -512,7 +542,8 @@ var LivenessClient = class _LivenessClient {
512
542
  frames: toFrameData(frames),
513
543
  ...options.frameCount != null ? { frame_count: options.frameCount } : {},
514
544
  ...options.warnings?.length ? { warnings: options.warnings } : {},
515
- ...di ? { device_intelligence: di } : {}
545
+ ...di ? { device_intelligence: di } : {},
546
+ ...this.buildMetadata() ? { metadata: this.buildMetadata() } : {}
516
547
  };
517
548
  const { data: response, headers } = await this.requestWithRetryRaw(
518
549
  API_PATHS.fastCheck,
@@ -549,7 +580,8 @@ var LivenessClient = class _LivenessClient {
549
580
  ...options.frameCount != null ? { frame_count: options.frameCount } : {},
550
581
  ...options.warnings?.length ? { warnings: options.warnings } : {},
551
582
  ...options.bgSegmentation !== void 0 ? { bg_segmentation: options.bgSegmentation } : {},
552
- ...di ? { device_intelligence: di } : {}
583
+ ...di ? { device_intelligence: di } : {},
584
+ ...this.buildMetadata() ? { metadata: this.buildMetadata() } : {}
553
585
  };
554
586
  const { data: response, headers } = await this.requestWithRetryRaw(
555
587
  API_PATHS.fastCheckCrops,
@@ -613,7 +645,8 @@ var LivenessClient = class _LivenessClient {
613
645
  frame: frameData,
614
646
  ...options.frameCount != null ? { frame_count: options.frameCount } : {},
615
647
  ...options.warnings?.length ? { warnings: options.warnings } : {},
616
- ...di ? { device_intelligence: di } : {}
648
+ ...di ? { device_intelligence: di } : {},
649
+ ...this.buildMetadata() ? { metadata: this.buildMetadata() } : {}
617
650
  };
618
651
  return this.requestWithRetry(API_PATHS.fastCheckStream, {
619
652
  method: "POST",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moveris/shared",
3
- "version": "3.8.6",
3
+ "version": "3.10.0",
4
4
  "description": "Core business logic for Moveris Live SDK",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",