@sanctum-key/react-native-sdk 1.0.16 → 1.0.18

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.
@@ -22,50 +22,6 @@ interface ApiVerificationResponse {
22
22
  [key: string]: any;
23
23
  }
24
24
 
25
- function getDistance(p1: number[], p2: number[]): number {
26
- return Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2));
27
- }
28
-
29
- function getPolygonArea(points: number[][]): number {
30
- const n = points.length;
31
- let area = 0;
32
- for (let i = 0; i < n; i++) {
33
- const j = (i + 1) % n;
34
- area += points[i][0] * points[j][1];
35
- area -= points[j][0] * points[i][1];
36
- }
37
- return Math.abs(area) / 2;
38
- }
39
-
40
- function assertCardNotTooFar(points: number[][]): void {
41
- if (!points || points.length < 3) return;
42
-
43
- const longestCardEdge = Math.max(
44
- getDistance(points[0], points[1]),
45
- getDistance(points[1], points[2]),
46
- getDistance(points[2], points[3] ?? points[0]),
47
- );
48
-
49
- const cardArea = getPolygonArea(points);
50
-
51
- logger.log(
52
- `Card distance check – longest edge: ${Math.round(longestCardEdge)} px, ` +
53
- `OBB area: ${Math.round(cardArea)} px²`
54
- );
55
-
56
- if (longestCardEdge < 700) {
57
- logger.log(`🛑 Rejected: longest edge too short (${Math.round(longestCardEdge)} px < 700 px)`);
58
- throw new Error('TOO_FAR_AWAY');
59
- }
60
-
61
- if (cardArea < 400_000) {
62
- logger.log(`🛑 Rejected: card area too small (${Math.round(cardArea)} px² < 400 000 px²)`);
63
- throw new Error('TOO_FAR_AWAY');
64
- }
65
- }
66
-
67
- // ─── frontVerification ────────────────────────────────────────────────────────
68
-
69
25
  export async function frontVerification(
70
26
  result: {
71
27
  path?: string,
@@ -82,8 +38,8 @@ export async function frontVerification(
82
38
  console.log("Front verification START", JSON.stringify({ result }, null, 2));
83
39
  logger.log("Front verification", JSON.stringify({ result }, null, 2));
84
40
 
85
- const authMethods = Array.isArray(result.regionMapping?.authMethod)
86
- ? result.regionMapping.authMethod.map(m => String(m).toUpperCase())
41
+ const authMethods = Array.isArray(result.regionMapping?.authMethod)
42
+ ? result.regionMapping.authMethod.map(m => String(m).toUpperCase())
87
43
  : [];
88
44
  const hasMrz = authMethods.some(m => m.includes('MRZ'));
89
45
 
@@ -130,6 +86,7 @@ export async function frontVerification(
130
86
  let points: number[][] | null = null;
131
87
  let isCardInFrame = true;
132
88
  let hasCroppedSides = false;
89
+ console.log(points)
133
90
 
134
91
  if (cardData) {
135
92
  points = cardData.obb;
@@ -140,14 +97,10 @@ export async function frontVerification(
140
97
  }
141
98
 
142
99
  if (!isCardInFrame || hasCroppedSides) {
143
- logger.log(`Front Framing failed. Cropped sides detected.`);
100
+ logger.log(`Front Framing failed. Cropped sides detected by backend.`);
144
101
  throw new Error('CARD_NOT_FULLY_IN_FRAME');
145
102
  }
146
103
 
147
- if (points && points.length >= 3) {
148
- assertCardNotTooFar(points);
149
- }
150
-
151
104
  const obbConfidence = getObbConfidence(detected.card_obb);
152
105
  if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {
153
106
  throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
@@ -174,11 +127,11 @@ export async function frontVerification(
174
127
  postfix: result?.currentSide || 'front',
175
128
  token: token,
176
129
  template_path: result?.templatePath || '',
177
- mrz_type: result?.mrzType || 'TD1'
130
+ mrz_type: result?.mrzType || 'TD1'
178
131
  },
179
132
  env
180
133
  );
181
-
134
+
182
135
  mrz = typeof mrzResponse === 'string' ? JSON.parse(mrzResponse) : mrzResponse;
183
136
 
184
137
  if (mrz?.parsed_data?.status === 'FAILURE' || mrz?.success === false) {
@@ -186,7 +139,7 @@ export async function frontVerification(
186
139
  throw new Error(`MRZ illisible: ${mrz?.parsed_data?.status_message || 'Veuillez nettoyer l\'objectif et réessayer'}`);
187
140
  }
188
141
  } catch (err: any) {
189
- logger.error("MRZ Extraction Error:", err);
142
+ logger.log("MRZ Extraction Error:", err);
190
143
  throw new Error(err?.message || "Erreur lors de l'extraction MRZ. Veuillez reprendre la photo.");
191
144
  }
192
145
  }
@@ -194,12 +147,11 @@ export async function frontVerification(
194
147
  return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}) };
195
148
 
196
149
  } catch (e: any) {
197
- logger.error('Error front verification:', e?.message);
150
+ logger.log('Error front verification:', e?.message);
198
151
  throw new Error(e?.message || 'Erreur de détection du visage');
199
152
  }
200
153
  }
201
154
 
202
-
203
155
  export async function backVerification(
204
156
  result: {
205
157
  path?: string,
@@ -218,8 +170,8 @@ export async function backVerification(
218
170
  logger.log("result.regionMapping", result.regionMapping, result.currentSide, result.code);
219
171
  logger.log('result object', result)
220
172
 
221
- const authMethods = Array.isArray(result.regionMapping?.authMethod)
222
- ? result.regionMapping.authMethod.map(m => String(m).toUpperCase())
173
+ const authMethods = Array.isArray(result.regionMapping?.authMethod)
174
+ ? result.regionMapping.authMethod.map(m => String(m).toUpperCase())
223
175
  : [];
224
176
 
225
177
  const hasMrz = authMethods.some(m => m.includes('MRZ'))
@@ -285,6 +237,7 @@ export async function backVerification(
285
237
  let points: number[][] | null = null;
286
238
  let isCardInFrame = false;
287
239
  let hasCroppedSides = true;
240
+ console.log(points)
288
241
 
289
242
  if (cardData.obb) {
290
243
  points = cardData.obb;
@@ -296,25 +249,14 @@ export async function backVerification(
296
249
  points = cardData[0];
297
250
  isCardInFrame = true;
298
251
  hasCroppedSides = false;
299
- if (points && points.length === 4) {
300
- const minX = Math.min(...points.map((p: number[]) => p[0]));
301
- const minY = Math.min(...points.map((p: number[]) => p[1]));
302
- if (minX <= 15 || minY <= 15) {
303
- isCardInFrame = false;
304
- hasCroppedSides = true;
305
- }
306
- }
252
+ // 🚨 ARTIFICIAL CHECK REMOVED HERE
307
253
  }
308
254
 
309
255
  if (!isCardInFrame || hasCroppedSides) {
310
- logger.log(`Back Framing failed. Coordinates hit image boundary.`);
256
+ logger.log(`Back Framing failed. Backend reported document out of bounds.`);
311
257
  throw new Error('CARD_NOT_FULLY_IN_FRAME');
312
258
  }
313
259
 
314
- if (points && points.length >= 3) {
315
- assertCardNotTooFar(points);
316
- }
317
-
318
260
  const obbConf = getObbConfidence(templateResponse?.card_obb);
319
261
  if (obbConf !== null && obbConf < OBB_CONFIDENCE_THRESHOLD) {
320
262
  throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
@@ -354,9 +296,9 @@ export async function backVerification(
354
296
  if (mrz?.parsed_data?.status === 'FAILURE' || mrz?.success === false) {
355
297
  throw new Error(mrz?.parsed_data?.status_message || 'Lecture MRZ échouée');
356
298
  }
357
-
299
+
358
300
  extractionResult.mrz = mrz; // Attaching securely to result object
359
-
301
+
360
302
  } catch (mrzError: any) {
361
303
  logger.log(`MRZ échoué: ${mrzError?.message}`);
362
304
  // If MRZ fails, we MUST throw an error so the user is forced to retake it!
@@ -394,7 +336,7 @@ export async function backVerification(
394
336
  };
395
337
 
396
338
  } catch (e: any) {
397
- if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message === 'TOO_FAR_AWAY') throw e;
339
+ if (e?.message === 'CARD_NOT_FULLY_IN_FRAME') throw e;
398
340
  throw new Error(e?.message || 'Erreur de détection des données');
399
341
  }
400
342
  }
@@ -439,6 +381,7 @@ export async function checkTemplateType(
439
381
  let points: number[][] | null = null;
440
382
  let isCardInFrame = false;
441
383
  let hasCroppedSides = true;
384
+ console.log(points)
442
385
 
443
386
  if (cardData.obb) {
444
387
  points = cardData.obb;
@@ -450,25 +393,14 @@ export async function checkTemplateType(
450
393
  points = cardData[0];
451
394
  isCardInFrame = true;
452
395
  hasCroppedSides = false;
453
- if (points && points.length === 4) {
454
- const minX = Math.min(...points.map((p: number[]) => p[0]));
455
- const minY = Math.min(...points.map((p: number[]) => p[1]));
456
- if (minX <= 15 || minY <= 15) {
457
- isCardInFrame = false;
458
- hasCroppedSides = true;
459
- }
460
- }
396
+ // 🚨 ARTIFICIAL CHECK REMOVED HERE
461
397
  }
462
398
 
463
399
  if (!isCardInFrame || hasCroppedSides) {
464
- logger.log(`Template Framing failed.`);
400
+ logger.log(`Template Framing failed by backend check.`);
465
401
  throw new Error('CARD_NOT_FULLY_IN_FRAME');
466
402
  }
467
403
 
468
- if (points && points.length >= 3) {
469
- assertCardNotTooFar(points);
470
- }
471
-
472
404
  const LPIPS_THRESHOLD = 0.75;
473
405
  if (templateType.lpips_score !== undefined && templateType.lpips_score > LPIPS_THRESHOLD) {
474
406
  logger.log(`🛑 Country Mismatch! LPIPS: ${templateType.lpips_score}`);
@@ -478,8 +410,8 @@ export async function checkTemplateType(
478
410
  logger.log("templateType result", JSON.stringify(truncateFields(templateType), null, 2));
479
411
  return templateType;
480
412
  } catch (e: any) {
481
- logger.error('Errorrr checking template type:', JSON.stringify(errorMessage(e), null, 2));
482
- if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message === 'TOO_FAR_AWAY' || e?.message?.includes('ne correspond pas')) throw e;
413
+ logger.log('Errorrr checking template type:', JSON.stringify(errorMessage(e), null, 2));
414
+ if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message?.includes('ne correspond pas')) throw e;
483
415
  throw new Error(e?.message || 'Erreur de vérification du template');
484
416
  }
485
417
  }
@@ -4,15 +4,9 @@ import * as ImageManipulator from "expo-image-manipulator";
4
4
 
5
5
  type Point = [number, number];
6
6
 
7
- /** OBB confidence below this = card not fully in frame; don't crop, give user feedback. */
8
7
  export const OBB_CONFIDENCE_THRESHOLD = 0.85;
9
8
 
10
- /**
11
- * card_obb format from API:
12
- * - Legacy: [ [ [p1,p2,p3,p4], confidence ] ]
13
- * - New: [ { obb: [p1,p2,p3,p4], confidence, card_in_frame?, cropped_sides? } ]
14
- * Returns confidence in [0,1] or null if not present.
15
- */
9
+
16
10
  export function getObbConfidence(cardObb: any): number | null {
17
11
  if (!cardObb || !Array.isArray(cardObb) || cardObb.length === 0) return null;
18
12
  const first = cardObb[0];
@@ -90,7 +84,6 @@ function computeAabb(points: Point[]) {
90
84
  return { minX, minY, maxX, maxY, width: maxX - minX, height: maxY - minY };
91
85
  }
92
86
 
93
- // Web-only crop using Canvas; returns dataURL (base64)
94
87
  async function cropWeb(uri: string, points: Point[]): Promise<string> {
95
88
  return new Promise((resolve, reject) => {
96
89
  const img = new Image();