@hexar/biometric-identity-sdk-core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/BiometricIdentitySDK.d.ts +111 -0
  2. package/dist/BiometricIdentitySDK.js +395 -0
  3. package/dist/ai-models/FaceDetector.d.ts +59 -0
  4. package/dist/ai-models/FaceDetector.js +167 -0
  5. package/dist/ai-models/LivenessDetector.d.ts +61 -0
  6. package/dist/ai-models/LivenessDetector.js +218 -0
  7. package/dist/api/BackendClient.d.ts +178 -0
  8. package/dist/api/BackendClient.js +199 -0
  9. package/dist/api/index.d.ts +5 -0
  10. package/dist/api/index.js +8 -0
  11. package/dist/encryption/index.d.ts +38 -0
  12. package/dist/encryption/index.js +99 -0
  13. package/dist/i18n/index.d.ts +6 -0
  14. package/dist/i18n/index.js +47 -0
  15. package/dist/i18n/languages/en.d.ts +2 -0
  16. package/dist/i18n/languages/en.js +112 -0
  17. package/dist/i18n/languages/es-AR.d.ts +2 -0
  18. package/dist/i18n/languages/es-AR.js +112 -0
  19. package/dist/i18n/languages/es.d.ts +2 -0
  20. package/dist/i18n/languages/es.js +112 -0
  21. package/dist/i18n/languages/pt-BR.d.ts +2 -0
  22. package/dist/i18n/languages/pt-BR.js +112 -0
  23. package/dist/i18n/types.d.ts +110 -0
  24. package/dist/i18n/types.js +2 -0
  25. package/dist/index.d.ts +20 -0
  26. package/dist/index.js +64 -0
  27. package/dist/services/BackendValidationService.d.ts +84 -0
  28. package/dist/services/BackendValidationService.js +174 -0
  29. package/dist/services/IValidationService.d.ts +132 -0
  30. package/dist/services/IValidationService.js +8 -0
  31. package/dist/services/index.d.ts +8 -0
  32. package/dist/services/index.js +10 -0
  33. package/dist/types/index.d.ts +288 -0
  34. package/dist/types/index.js +34 -0
  35. package/dist/validation/DocumentValidator.d.ts +84 -0
  36. package/dist/validation/DocumentValidator.js +295 -0
  37. package/dist/validation/OCREngine.d.ts +75 -0
  38. package/dist/validation/OCREngine.js +225 -0
  39. package/package.json +24 -0
  40. package/src/BiometricIdentitySDK.ts +493 -0
  41. package/src/ai-models/FaceDetector.ts +200 -0
  42. package/src/ai-models/LivenessDetector.ts +274 -0
  43. package/src/api/BackendClient.ts +395 -0
  44. package/src/api/index.ts +15 -0
  45. package/src/encryption/index.ts +108 -0
  46. package/src/i18n/index.ts +35 -0
  47. package/src/i18n/languages/en.ts +121 -0
  48. package/src/i18n/languages/es-AR.ts +121 -0
  49. package/src/i18n/languages/es.ts +121 -0
  50. package/src/i18n/languages/pt-BR.ts +121 -0
  51. package/src/i18n/types.ts +121 -0
  52. package/src/index.ts +54 -0
  53. package/src/services/BackendValidationService.ts +228 -0
  54. package/src/services/IValidationService.ts +158 -0
  55. package/src/services/index.ts +17 -0
  56. package/src/types/index.ts +380 -0
  57. package/src/validation/DocumentValidator.ts +353 -0
  58. package/src/validation/OCREngine.ts +265 -0
  59. package/tsconfig.json +20 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Main Biometric Identity SDK Class
3
+ * Initialize once at app start with your API key
4
+ */
5
+ import { ValidationResult, VideoResult, SDKState } from './types';
6
+ import { ChallengeResponse, ChallengeAction } from './api/BackendClient';
7
+ import { SupportedLanguage } from './i18n';
8
+ export declare class BiometricIdentitySDK {
9
+ private static instance;
10
+ private config;
11
+ private state;
12
+ private backendClient;
13
+ private isBackendAvailable;
14
+ private constructor();
15
+ /**
16
+ * Initialize SDK (call once at app start)
17
+ */
18
+ static configure(apiKey: string, options?: {
19
+ language?: SupportedLanguage;
20
+ }): void;
21
+ /**
22
+ * Get SDK instance
23
+ */
24
+ static getInstance(): BiometricIdentitySDK;
25
+ /**
26
+ * Create a new session (for per-user flows)
27
+ */
28
+ static createSession(): BiometricIdentitySDK;
29
+ /**
30
+ * Initialize SDK and check backend availability
31
+ */
32
+ initialize(): Promise<void>;
33
+ /**
34
+ * Generate liveness challenge from backend
35
+ * Returns challenge actions for the user to perform
36
+ */
37
+ generateLivenessChallenge(challengeType?: 'active' | 'passive'): Promise<ChallengeResponse>;
38
+ /**
39
+ * Get default challenges for offline mode
40
+ */
41
+ getDefaultChallenges(): ChallengeAction[];
42
+ /**
43
+ * Get current session ID (from backend)
44
+ */
45
+ getSessionId(): string | null;
46
+ /**
47
+ * Upload front ID image
48
+ */
49
+ uploadFrontID(image: File | Blob | string): Promise<void>;
50
+ /**
51
+ * Upload back ID image
52
+ */
53
+ uploadBackID(image: File | Blob | string): Promise<void>;
54
+ /**
55
+ * Store video recording for liveness detection
56
+ */
57
+ storeVideoRecording(videoResult: VideoResult): Promise<void>;
58
+ /**
59
+ * Record video for liveness detection (legacy method)
60
+ */
61
+ recordVideoLiveness(options?: {
62
+ duration?: number;
63
+ instructions?: string[];
64
+ }): Promise<VideoResult>;
65
+ /**
66
+ * Validate identity using all collected data
67
+ * Uses backend AI for validation
68
+ */
69
+ validateIdentity(): Promise<ValidationResult>;
70
+ /**
71
+ * Validate using backend API
72
+ */
73
+ private validateWithBackend;
74
+ /**
75
+ * Process image (convert File/Blob to ImageData)
76
+ */
77
+ private processImage;
78
+ /**
79
+ * Convert Blob to base64
80
+ */
81
+ private blobToBase64;
82
+ /**
83
+ * Get current SDK state
84
+ */
85
+ getState(): SDKState;
86
+ /**
87
+ * Check if backend is available
88
+ */
89
+ isUsingBackend(): boolean;
90
+ /**
91
+ * Update SDK state
92
+ */
93
+ private updateState;
94
+ /**
95
+ * Create typed error
96
+ */
97
+ private createError;
98
+ /**
99
+ * Handle errors
100
+ */
101
+ private handleError;
102
+ /**
103
+ * Reset SDK state
104
+ */
105
+ reset(): void;
106
+ /**
107
+ * Clean up resources
108
+ */
109
+ dispose(): void;
110
+ }
111
+ export default BiometricIdentitySDK;
@@ -0,0 +1,395 @@
1
+ "use strict";
2
+ /**
3
+ * Main Biometric Identity SDK Class
4
+ * Initialize once at app start with your API key
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.BiometricIdentitySDK = void 0;
8
+ const types_1 = require("./types");
9
+ const BackendClient_1 = require("./api/BackendClient");
10
+ const i18n_1 = require("./i18n");
11
+ const API_ENDPOINT = 'https://api.hexar.biometry.com/v1';
12
+ class BiometricIdentitySDK {
13
+ constructor(config) {
14
+ this.isBackendAvailable = false;
15
+ if (!config.apiKey) {
16
+ throw new Error('BiometricIdentitySDK requires an API key');
17
+ }
18
+ this.config = {
19
+ apiEndpoint: API_ENDPOINT,
20
+ apiKey: config.apiKey,
21
+ language: config.language || 'en',
22
+ enableBackendValidation: true,
23
+ enableLocalStorage: config.enableLocalStorage || false,
24
+ encryptionKey: config.encryptionKey || '',
25
+ minMatchScore: config.minMatchScore || 85,
26
+ minLivenessScore: config.minLivenessScore || 80,
27
+ validationTimeout: config.validationTimeout || 60000,
28
+ modelPaths: {},
29
+ };
30
+ this.state = {
31
+ currentStep: types_1.SDKStep.INIT,
32
+ isLoading: false,
33
+ progress: 0,
34
+ };
35
+ this.backendClient = new BackendClient_1.BackendClient({
36
+ apiEndpoint: API_ENDPOINT,
37
+ apiKey: this.config.apiKey,
38
+ timeout: this.config.validationTimeout,
39
+ });
40
+ }
41
+ /**
42
+ * Initialize SDK (call once at app start)
43
+ */
44
+ static configure(apiKey, options) {
45
+ if (BiometricIdentitySDK.instance) {
46
+ console.warn('SDK already initialized');
47
+ return;
48
+ }
49
+ const language = options?.language || 'en';
50
+ (0, i18n_1.setLanguage)(language);
51
+ BiometricIdentitySDK.instance = new BiometricIdentitySDK({
52
+ apiKey,
53
+ language,
54
+ });
55
+ }
56
+ /**
57
+ * Get SDK instance
58
+ */
59
+ static getInstance() {
60
+ if (!BiometricIdentitySDK.instance) {
61
+ throw new Error('SDK not initialized. Call BiometricIdentitySDK.configure() first');
62
+ }
63
+ return BiometricIdentitySDK.instance;
64
+ }
65
+ /**
66
+ * Create a new session (for per-user flows)
67
+ */
68
+ static createSession() {
69
+ const config = BiometricIdentitySDK.getInstance().config;
70
+ return new BiometricIdentitySDK(config);
71
+ }
72
+ /**
73
+ * Initialize SDK and check backend availability
74
+ */
75
+ async initialize() {
76
+ try {
77
+ console.log('Initializing Biometric Identity SDK...');
78
+ this.updateState({ isLoading: true, progress: 0 });
79
+ // Check backend availability
80
+ console.log('Checking backend availability...');
81
+ this.isBackendAvailable = await this.backendClient.healthCheck();
82
+ if (!this.isBackendAvailable) {
83
+ throw this.createError(types_1.BiometricErrorCode.NETWORK_ERROR, 'Backend server is not available. Please check your API endpoint configuration and try again.');
84
+ }
85
+ console.log('✓ Backend is available - ready for validation');
86
+ this.updateState({
87
+ isLoading: false,
88
+ progress: 0,
89
+ currentStep: types_1.SDKStep.CAPTURE_FRONT_ID
90
+ });
91
+ console.log('SDK initialized successfully');
92
+ }
93
+ catch (error) {
94
+ throw this.createError(types_1.BiometricErrorCode.MODEL_LOAD_FAILED, 'Failed to initialize SDK: Backend not available', error);
95
+ }
96
+ }
97
+ /**
98
+ * Generate liveness challenge from backend
99
+ * Returns challenge actions for the user to perform
100
+ */
101
+ async generateLivenessChallenge(challengeType = 'active') {
102
+ if (!this.isBackendAvailable) {
103
+ throw this.createError(types_1.BiometricErrorCode.NETWORK_ERROR, 'Backend not available. Cannot generate challenge.');
104
+ }
105
+ try {
106
+ const challenge = await this.backendClient.generateChallenge(challengeType);
107
+ console.log(`Generated challenge with ${challenge.challenges.length} actions`);
108
+ return challenge;
109
+ }
110
+ catch (error) {
111
+ throw this.createError(types_1.BiometricErrorCode.NETWORK_ERROR, 'Failed to generate liveness challenge', error);
112
+ }
113
+ }
114
+ /**
115
+ * Get default challenges for offline mode
116
+ */
117
+ getDefaultChallenges() {
118
+ return [
119
+ {
120
+ action: 'look_left',
121
+ instruction: 'Slowly turn your head to the LEFT',
122
+ duration_ms: 2500,
123
+ order: 1,
124
+ },
125
+ {
126
+ action: 'look_right',
127
+ instruction: 'Slowly turn your head to the RIGHT',
128
+ duration_ms: 2500,
129
+ order: 2,
130
+ },
131
+ {
132
+ action: 'blink',
133
+ instruction: 'Blink your eyes naturally',
134
+ duration_ms: 2000,
135
+ order: 3,
136
+ },
137
+ ];
138
+ }
139
+ /**
140
+ * Get current session ID (from backend)
141
+ */
142
+ getSessionId() {
143
+ return this.backendClient?.getSessionId() || null;
144
+ }
145
+ /**
146
+ * Upload front ID image
147
+ */
148
+ async uploadFrontID(image) {
149
+ try {
150
+ this.updateState({ isLoading: true, currentStep: types_1.SDKStep.CAPTURE_FRONT_ID });
151
+ const imageData = await this.processImage(image);
152
+ // Store the image - validation happens at the end
153
+ this.updateState({
154
+ frontID: imageData,
155
+ progress: 25,
156
+ isLoading: false,
157
+ currentStep: types_1.SDKStep.CAPTURE_BACK_ID
158
+ });
159
+ console.log('Front ID uploaded successfully');
160
+ }
161
+ catch (error) {
162
+ this.handleError(error);
163
+ throw error;
164
+ }
165
+ }
166
+ /**
167
+ * Upload back ID image
168
+ */
169
+ async uploadBackID(image) {
170
+ try {
171
+ this.updateState({ isLoading: true, currentStep: types_1.SDKStep.CAPTURE_BACK_ID });
172
+ const imageData = await this.processImage(image);
173
+ // Store the image - validation happens at the end
174
+ this.updateState({
175
+ backID: imageData,
176
+ progress: 50,
177
+ isLoading: false,
178
+ currentStep: types_1.SDKStep.RECORD_LIVENESS
179
+ });
180
+ console.log('Back ID uploaded successfully');
181
+ }
182
+ catch (error) {
183
+ this.handleError(error);
184
+ throw error;
185
+ }
186
+ }
187
+ /**
188
+ * Store video recording for liveness detection
189
+ */
190
+ async storeVideoRecording(videoResult) {
191
+ try {
192
+ this.updateState({ isLoading: true, currentStep: types_1.SDKStep.RECORD_LIVENESS });
193
+ this.updateState({
194
+ videoData: videoResult,
195
+ progress: 75,
196
+ isLoading: false,
197
+ });
198
+ console.log('Video recording stored successfully');
199
+ }
200
+ catch (error) {
201
+ this.handleError(error);
202
+ throw error;
203
+ }
204
+ }
205
+ /**
206
+ * Record video for liveness detection (legacy method)
207
+ */
208
+ async recordVideoLiveness(options) {
209
+ try {
210
+ this.updateState({ isLoading: true, currentStep: types_1.SDKStep.RECORD_LIVENESS });
211
+ // This would be implemented by the platform-specific wrappers
212
+ // For now, return a mock result
213
+ const videoResult = {
214
+ frames: [],
215
+ duration: options?.duration || 8000,
216
+ instructionsFollowed: true,
217
+ qualityScore: 85,
218
+ };
219
+ this.updateState({
220
+ videoData: videoResult,
221
+ progress: 75,
222
+ isLoading: false,
223
+ });
224
+ console.log('Video liveness recorded successfully');
225
+ return videoResult;
226
+ }
227
+ catch (error) {
228
+ this.handleError(error);
229
+ throw error;
230
+ }
231
+ }
232
+ /**
233
+ * Validate identity using all collected data
234
+ * Uses backend AI for validation
235
+ */
236
+ async validateIdentity() {
237
+ try {
238
+ if (!this.state.frontID || !this.state.videoData) {
239
+ throw this.createError(types_1.BiometricErrorCode.UNKNOWN_ERROR, 'Missing required data for validation. Need front ID and video.');
240
+ }
241
+ if (!this.isBackendAvailable) {
242
+ throw this.createError(types_1.BiometricErrorCode.NETWORK_ERROR, 'Backend not available. Cannot perform validation.');
243
+ }
244
+ this.updateState({
245
+ isLoading: true,
246
+ currentStep: types_1.SDKStep.VALIDATING,
247
+ progress: 75
248
+ });
249
+ // Perform backend validation
250
+ const validationResult = await this.validateWithBackend();
251
+ this.updateState({
252
+ validationResult,
253
+ progress: 100,
254
+ isLoading: false,
255
+ currentStep: types_1.SDKStep.RESULT
256
+ });
257
+ console.log('Validation completed successfully');
258
+ return validationResult;
259
+ }
260
+ catch (error) {
261
+ this.handleError(error);
262
+ throw error;
263
+ }
264
+ }
265
+ /**
266
+ * Validate using backend API
267
+ */
268
+ async validateWithBackend() {
269
+ if (!this.state.frontID || !this.state.videoData) {
270
+ throw new Error('Required data not available');
271
+ }
272
+ console.log('Validating with backend API...');
273
+ this.updateState({ progress: 80 });
274
+ try {
275
+ const response = await this.backendClient.fullValidation({
276
+ frontIdImage: this.state.frontID.data,
277
+ backIdImage: this.state.backID?.data,
278
+ videoFrames: this.state.videoData.frames,
279
+ videoDurationMs: this.state.videoData.duration,
280
+ challengesCompleted: this.state.videoData.challengesCompleted || [],
281
+ });
282
+ this.updateState({ progress: 95 });
283
+ // Convert backend response to SDK format
284
+ return this.backendClient.convertToValidationResult(response);
285
+ }
286
+ catch (error) {
287
+ throw this.createError(types_1.BiometricErrorCode.NETWORK_ERROR, 'Backend validation failed', error);
288
+ }
289
+ }
290
+ /**
291
+ * Process image (convert File/Blob to ImageData)
292
+ */
293
+ async processImage(image) {
294
+ try {
295
+ if (typeof image === 'string') {
296
+ // Already base64
297
+ return {
298
+ data: image,
299
+ width: 0,
300
+ height: 0,
301
+ mimeType: 'image/jpeg',
302
+ size: image.length,
303
+ };
304
+ }
305
+ // Convert Blob/File to base64
306
+ const base64 = await this.blobToBase64(image);
307
+ return {
308
+ data: base64,
309
+ width: 0, // Would be set after image analysis
310
+ height: 0,
311
+ mimeType: image.type,
312
+ size: image.size,
313
+ };
314
+ }
315
+ catch (error) {
316
+ throw this.createError(types_1.BiometricErrorCode.UNKNOWN_ERROR, 'Failed to process image', error);
317
+ }
318
+ }
319
+ /**
320
+ * Convert Blob to base64
321
+ */
322
+ blobToBase64(blob) {
323
+ return new Promise((resolve, reject) => {
324
+ const reader = new FileReader();
325
+ reader.onloadend = () => {
326
+ const base64 = reader.result;
327
+ resolve(base64.split(',')[1] || base64);
328
+ };
329
+ reader.onerror = reject;
330
+ reader.readAsDataURL(blob);
331
+ });
332
+ }
333
+ /**
334
+ * Get current SDK state
335
+ */
336
+ getState() {
337
+ return { ...this.state };
338
+ }
339
+ /**
340
+ * Check if backend is available
341
+ */
342
+ isUsingBackend() {
343
+ return this.isBackendAvailable;
344
+ }
345
+ /**
346
+ * Update SDK state
347
+ */
348
+ updateState(updates) {
349
+ this.state = {
350
+ ...this.state,
351
+ ...updates,
352
+ };
353
+ }
354
+ /**
355
+ * Create typed error
356
+ */
357
+ createError(code, message, details) {
358
+ const error = new Error(message);
359
+ error.code = code;
360
+ error.details = details;
361
+ return error;
362
+ }
363
+ /**
364
+ * Handle errors
365
+ */
366
+ handleError(error) {
367
+ this.updateState({
368
+ error: error,
369
+ isLoading: false,
370
+ currentStep: types_1.SDKStep.ERROR,
371
+ });
372
+ }
373
+ /**
374
+ * Reset SDK state
375
+ */
376
+ reset() {
377
+ this.state = {
378
+ currentStep: types_1.SDKStep.INIT,
379
+ isLoading: false,
380
+ progress: 0,
381
+ };
382
+ // Reset backend session
383
+ this.backendClient?.resetSession();
384
+ }
385
+ /**
386
+ * Clean up resources
387
+ */
388
+ dispose() {
389
+ // No local resources to clean up
390
+ console.log('SDK disposed');
391
+ }
392
+ }
393
+ exports.BiometricIdentitySDK = BiometricIdentitySDK;
394
+ BiometricIdentitySDK.instance = null;
395
+ exports.default = BiometricIdentitySDK;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Face Detection using AI models
3
+ * Uses BlazeFace model for lightweight, fast face detection
4
+ */
5
+ import { FaceEmbedding, BoundingBox } from '../types';
6
+ export interface FaceDetectionResult {
7
+ faces: FaceEmbedding[];
8
+ processingTime: number;
9
+ }
10
+ export declare class FaceDetector {
11
+ private modelPath?;
12
+ private model;
13
+ private isModelLoaded;
14
+ constructor(modelPath?: string | undefined);
15
+ /**
16
+ * Load the face detection model
17
+ */
18
+ loadModel(): Promise<void>;
19
+ /**
20
+ * Detect faces in an image
21
+ */
22
+ detectFaces(imageData: string | Buffer): Promise<FaceDetectionResult>;
23
+ /**
24
+ * Preprocess image for model input
25
+ */
26
+ private preprocessImage;
27
+ /**
28
+ * Run model inference
29
+ */
30
+ private runInference;
31
+ /**
32
+ * Post-process detection results
33
+ */
34
+ private postprocessDetections;
35
+ /**
36
+ * Extract face feature vector
37
+ */
38
+ private extractFeatureVector;
39
+ /**
40
+ * Check if image contains exactly one face
41
+ */
42
+ validateSingleFace(imageData: string | Buffer): Promise<boolean>;
43
+ /**
44
+ * Get face bounding box from image
45
+ */
46
+ getFaceBoundingBox(imageData: string | Buffer): Promise<BoundingBox | null>;
47
+ /**
48
+ * Clean up resources
49
+ */
50
+ dispose(): void;
51
+ }
52
+ /**
53
+ * Calculate Euclidean distance between two face embeddings
54
+ */
55
+ export declare function calculateFaceDistance(embedding1: number[], embedding2: number[]): number;
56
+ /**
57
+ * Calculate face similarity score (0-100)
58
+ */
59
+ export declare function calculateFaceSimilarity(embedding1: number[], embedding2: number[]): number;