@transfergratis/react-native-sdk 0.1.29 → 0.1.30

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.
@@ -43,14 +43,34 @@ export async function frontVerification(result, env = 'PRODUCTION') {
43
43
  const cardData = detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0
44
44
  ? detected.card_obb[0]
45
45
  : null;
46
- // --- STRICT FRAMING CHECK ---
47
- if (cardData && typeof cardData.card_in_frame !== 'undefined') {
48
- const isCardInFrame = cardData.card_in_frame === true;
49
- const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
50
- // If it is NOT in the frame, OR if any side is cropped, block progression
51
- if (!isCardInFrame || hasCroppedSides) {
52
- logger.log(`Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);
53
- throw new Error('CARD_NOT_FULLY_IN_FRAME');
46
+ let points = null;
47
+ let isCardInFrame = true;
48
+ let hasCroppedSides = false;
49
+ // Extract data safely
50
+ if (cardData) {
51
+ points = cardData.obb;
52
+ if (typeof cardData.card_in_frame !== 'undefined') {
53
+ isCardInFrame = cardData.card_in_frame === true;
54
+ hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
55
+ }
56
+ }
57
+ // --- 1. STRICT FRAMING CHECK (MUST HAPPEN FIRST) ---
58
+ if (!isCardInFrame || hasCroppedSides) {
59
+ logger.log(`Front Framing failed. Cropped sides detected.`);
60
+ throw new Error('CARD_NOT_FULLY_IN_FRAME');
61
+ }
62
+ // --- 2. STRICT DISTANCE CHECK (ONLY RUNS IF FULLY IN FRAME) ---
63
+ if (points && points.length === 4) {
64
+ const getDistance = (p1, p2) => Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2));
65
+ const longestCardEdge = Math.max(getDistance(points[0], points[1]), getDistance(points[1], points[2]));
66
+ const maxX = Math.max(points[0][0], points[1][0], points[2][0], points[3][0]);
67
+ const maxY = Math.max(points[0][1], points[1][1], points[2][1], points[3][1]);
68
+ const estimatedImageScale = Math.max(maxX, maxY);
69
+ const fillPercentage = longestCardEdge / estimatedImageScale;
70
+ logger.log(`Front Card Fill Percentage: ${(fillPercentage * 100).toFixed(1)}%`);
71
+ if (fillPercentage < 0.50) {
72
+ logger.log("🛑 Front Image rejected: Document is too far away.");
73
+ throw new Error("TOO_FAR_AWAY");
54
74
  }
55
75
  }
56
76
  // Check Confidence Threshold
@@ -70,7 +90,7 @@ export async function frontVerification(result, env = 'PRODUCTION') {
70
90
  catch { }
71
91
  // MRZ Extraction
72
92
  if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ')) {
73
- mrz = await kycService.extractMrzText({
93
+ const mrzResponse = await kycService.extractMrzText({
74
94
  fileUri: result.path || '',
75
95
  docType: result?.selectedDocumentType || '',
76
96
  docRegion: result?.code || "",
@@ -79,11 +99,18 @@ export async function frontVerification(result, env = 'PRODUCTION') {
79
99
  template_path: result?.templatePath || '',
80
100
  mrz_type: result?.mrzType || ''
81
101
  }, env);
102
+ // Safety check: parse if it was returned as a raw string
103
+ mrz = typeof mrzResponse === 'string' ? JSON.parse(mrzResponse) : mrzResponse;
104
+ if (mrz && (!mrz.success || mrz.parsed_data?.status === 'FAILURE')) {
105
+ logger.log("🛑 Front MRZ Extraction Failed:", mrz.parsed_data?.status_message);
106
+ throw new Error(`MRZ illisible: ${mrz.parsed_data?.status_message || 'Veuillez nettoyer l\'objectif et réessayer'}`);
107
+ }
82
108
  }
83
109
  return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}) };
84
110
  }
85
111
  catch (e) {
86
- logger.error('Error front verification:', JSON.stringify(errorMessage(e), null, 2));
112
+ logger.error('Error front verification:', e?.message);
113
+ // Do not use LogBox for background silent errors
87
114
  throw new Error(e?.message || 'Erreur de détection du visage');
88
115
  }
89
116
  }
@@ -208,10 +235,13 @@ export async function backVerification(result, env = 'PRODUCTION') {
208
235
  if (result.regionMapping?.authMethod?.includes('MRZ')) {
209
236
  return {
210
237
  success: true,
211
- parsed_data: {
212
- status: 'success',
213
- document_type: result.selectedDocumentType,
214
- mrz_type: result.mrzType || 'TD1'
238
+ mrz: {
239
+ success: true,
240
+ parsed_data: {
241
+ status: 'SUCCESS',
242
+ document_type: result.selectedDocumentType,
243
+ mrz_type: result.mrzType || 'TD1'
244
+ }
215
245
  },
216
246
  bbox: mockBbox,
217
247
  card_obb: mockCardObb
@@ -219,12 +249,13 @@ export async function backVerification(result, env = 'PRODUCTION') {
219
249
  }
220
250
  else if (result.regionMapping?.authMethod?.includes('2D_barcode')) {
221
251
  return {
222
- barcode_data: 'SANDBOX_MOCK_BARCODE',
252
+ success: true,
253
+ barcode: { barcode_data: 'SANDBOX_MOCK_BARCODE' },
223
254
  bbox: mockBbox,
224
255
  card_obb: mockCardObb
225
256
  };
226
257
  }
227
- return { bbox: mockBbox };
258
+ return { success: true, bbox: mockBbox, card_obb: mockCardObb };
228
259
  }
229
260
  const token = await authentification();
230
261
  logger.log("1. Checking template and framing for back document...");
@@ -235,16 +266,57 @@ export async function backVerification(result, env = 'PRODUCTION') {
235
266
  postfix: 'back',
236
267
  token: token
237
268
  }, env);
238
- // STRICT FRAMING CHECK
269
+ if (templateResponse.success === false || templateResponse.Error) {
270
+ logger.log("Backend returned an error:", templateResponse.Error);
271
+ throw new Error('Impossible de lire le document. Veuillez vous rapprocher et stabiliser la caméra.');
272
+ }
239
273
  const cardData = templateResponse?.card_obb && Array.isArray(templateResponse.card_obb) && templateResponse.card_obb.length > 0
240
274
  ? templateResponse.card_obb[0]
241
275
  : null;
242
- if (cardData && typeof cardData.card_in_frame !== 'undefined') {
243
- const isCardInFrame = cardData.card_in_frame === true;
244
- const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
245
- if (!isCardInFrame || hasCroppedSides) {
246
- logger.log(`Back Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);
247
- throw new Error('CARD_NOT_FULLY_IN_FRAME');
276
+ if (!cardData) {
277
+ throw new Error('CARD_NOT_FULLY_IN_FRAME');
278
+ }
279
+ let points = null;
280
+ let isCardInFrame = false;
281
+ let hasCroppedSides = true;
282
+ // Safely extract coordinates and frame status
283
+ if (cardData.obb) {
284
+ points = cardData.obb;
285
+ if (typeof cardData.card_in_frame !== 'undefined') {
286
+ isCardInFrame = cardData.card_in_frame === true;
287
+ hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
288
+ }
289
+ }
290
+ else if (Array.isArray(cardData) && Array.isArray(cardData[0])) {
291
+ points = cardData[0];
292
+ isCardInFrame = true;
293
+ hasCroppedSides = false;
294
+ if (points && points.length === 4) {
295
+ const minX = Math.min(...points.map((p) => p[0]));
296
+ const minY = Math.min(...points.map((p) => p[1]));
297
+ if (minX <= 15 || minY <= 15) {
298
+ isCardInFrame = false;
299
+ hasCroppedSides = true;
300
+ }
301
+ }
302
+ }
303
+ // --- 2. STRICT FRAMING CHECK (MUST HAPPEN FIRST) ---
304
+ if (!isCardInFrame || hasCroppedSides) {
305
+ logger.log(`Back Framing failed. Coordinates hit image boundary.`);
306
+ throw new Error('CARD_NOT_FULLY_IN_FRAME');
307
+ }
308
+ // --- 3. STRICT DISTANCE CHECK (ONLY RUNS IF FULLY IN FRAME) ---
309
+ if (points && points.length === 4) {
310
+ const getDistance = (p1, p2) => Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2));
311
+ const longestCardEdge = Math.max(getDistance(points[0], points[1]), getDistance(points[1], points[2]));
312
+ const maxX = Math.max(points[0][0], points[1][0], points[2][0], points[3][0]);
313
+ const maxY = Math.max(points[0][1], points[1][1], points[2][1], points[3][1]);
314
+ const estimatedImageScale = Math.max(maxX, maxY);
315
+ const fillPercentage = longestCardEdge / estimatedImageScale;
316
+ logger.log(`Back Card Fill Percentage: ${(fillPercentage * 100).toFixed(1)}%`);
317
+ if (fillPercentage < 0.50) {
318
+ logger.log("🛑 Back Image rejected: Document is too far away.");
319
+ throw new Error("TOO_FAR_AWAY");
248
320
  }
249
321
  }
250
322
  const obbConf = getObbConfidence(templateResponse?.card_obb);
@@ -262,88 +334,76 @@ export async function backVerification(result, env = 'PRODUCTION') {
262
334
  }
263
335
  }
264
336
  logger.log("Framing and Country Template verified successfully. Proceeding to Data Extraction.");
265
- const tryMrzWithBarcodeFallback = async () => {
337
+ const hasMrz = result.regionMapping?.authMethod?.includes('MRZ') || !result.regionMapping?.authMethod?.length;
338
+ const hasBarcode = result.regionMapping?.authMethod?.includes('2D_barcode');
339
+ let extractionResult = {};
340
+ // --- 4. Try MRZ First (If required or default) ---
341
+ if (hasMrz) {
266
342
  try {
267
343
  logger.log("Tentative d'extraction MRZ");
268
- const mrz = await kycService.extractMrzText({
344
+ const mrzResponse = await kycService.extractMrzText({
269
345
  fileUri: result.path,
270
346
  docType: result?.selectedDocumentType || '',
271
347
  docRegion: result?.code || '',
272
348
  postfix: 'back',
273
349
  token: token,
274
- template_path: activeTemplatePath, // Use the verified template
275
- mrz_type: result?.mrzType || ''
350
+ template_path: activeTemplatePath,
351
+ mrz_type: result?.mrzType || '' // Safe to send empty string
276
352
  }, env);
277
- let bbox;
278
- let croppedBase64;
279
- try {
280
- // We use the OBB from our template check to ensure clean cropping
281
- const crop = await cropByObb(result?.path || '', templateResponse.card_obb);
282
- bbox = crop.bbox;
283
- croppedBase64 = crop.base64;
353
+ const mrz = typeof mrzResponse === 'string' ? JSON.parse(mrzResponse) : mrzResponse;
354
+ if (!mrz || !mrz.success || mrz.parsed_data?.status === 'FAILURE') {
355
+ throw new Error(mrz?.parsed_data?.status_message || 'Lecture MRZ échouée');
284
356
  }
285
- catch { }
286
- return { ...mrz, bbox, croppedBase64 };
357
+ extractionResult = { mrz };
287
358
  }
288
359
  catch (mrzError) {
289
- logger.log("MRZ échoué, tentative d'extraction barcode");
290
- try {
291
- const barcode = await kycService.extractBarcode({ fileUri: result.path, token: token }, env);
292
- return barcode;
360
+ if (hasBarcode) {
361
+ logger.log(`MRZ échoué (${mrzError?.message}), tentative d'extraction barcode...`);
362
+ try {
363
+ const barcode = await kycService.extractBarcode({ fileUri: result.path, token: token }, env);
364
+ extractionResult = { barcode };
365
+ }
366
+ catch (barcodeError) {
367
+ throw new Error(`MRZ et Barcode ont échoué. Veuillez stabiliser la carte.`);
368
+ }
293
369
  }
294
- catch (barcodeError) {
295
- throw new Error(`MRZ et barcode ont échoué. MRZ: ${mrzError?.message}, Barcode: ${barcodeError?.message}`);
370
+ else {
371
+ throw new Error(`Lecture MRZ invalide: ${mrzError?.message}`);
296
372
  }
297
373
  }
298
- };
299
- if (result.regionMapping?.authMethod?.length > 2 && (!result?.mrzType || result?.mrzType.length === 0)) {
300
- return await tryMrzWithBarcodeFallback();
301
374
  }
302
- if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ') && result?.mrzType && result?.mrzType.length > 0) {
375
+ // --- 5. Try Barcode Only ---
376
+ else if (hasBarcode) {
303
377
  try {
304
- const mrz = await kycService.extractMrzText({
305
- fileUri: result.path,
306
- docType: result?.selectedDocumentType || '',
307
- docRegion: result?.code || '',
308
- postfix: 'back',
309
- token: token,
310
- template_path: activeTemplatePath,
311
- mrz_type: result?.mrzType || ''
312
- }, env);
313
- let bbox;
314
- try {
315
- const crop = await cropByObb(result?.path || '', templateResponse.card_obb);
316
- bbox = crop.bbox;
317
- }
318
- catch { }
319
- return { ...mrz, bbox };
320
- }
321
- catch (mrzError) {
322
- throw new Error(`MRZ et barcode ont échoué. MRZ: ${mrzError?.message}, Barcode: ${mrzError?.message}`);
323
- }
324
- }
325
- if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('2D_barcode')) {
326
- try {
327
- logger.log("Tentative d'extraction barcode");
378
+ logger.log("Tentative d'extraction barcode seule");
328
379
  const barcode = await kycService.extractBarcode({ fileUri: result.path, token: token }, env);
329
- let bbox;
330
- try {
331
- const crop = await cropByObb(result?.path || '', templateResponse.card_obb);
332
- bbox = crop.bbox;
333
- }
334
- catch { }
335
- return { ...barcode, bbox };
380
+ extractionResult = { barcode };
336
381
  }
337
- catch (barcodeError) {
338
- throw new Error(`Barcode et MRZ ont échoué. Barcode: ${barcodeError?.message}, MRZ: ${barcodeError?.message}`);
382
+ catch (e) {
383
+ throw new Error(`Lecture Barcode échouée: ${e?.message}`);
339
384
  }
340
385
  }
341
- return null;
386
+ let bbox;
387
+ let croppedBase64;
388
+ try {
389
+ const crop = await cropByObb(result?.path || '', templateResponse.card_obb);
390
+ bbox = crop.bbox;
391
+ croppedBase64 = crop.base64;
392
+ }
393
+ catch { }
394
+ return {
395
+ success: true,
396
+ ...extractionResult,
397
+ bbox,
398
+ croppedBase64,
399
+ card_obb: templateResponse.card_obb
400
+ };
342
401
  }
343
402
  catch (e) {
344
- if (e?.message === 'CARD_NOT_FULLY_IN_FRAME')
345
- throw e; // Bubble the strict framing error specifically
346
- throw new Error(e?.message || 'Erreur de détection du MRZ ou barcode');
403
+ if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message === 'TOO_FAR_AWAY') {
404
+ throw e;
405
+ }
406
+ throw new Error(e?.message || 'Erreur de détection des données');
347
407
  }
348
408
  }
349
409
  /**
@@ -366,17 +426,48 @@ export async function checkTemplateType(result, env = 'PRODUCTION') {
366
426
  }
367
427
  const token = await authentification();
368
428
  const templateType = await kycService.checkTemplateType({ fileUri: result.path || '', docType: result?.docType, docRegion: result?.docRegion || "", postfix: result?.postfix, token: token }, env);
429
+ if (templateType.success === false || templateType.Error) {
430
+ logger.log("Backend returned an error:", templateType.Error);
431
+ throw new Error('Impossible de lire le document. Veuillez vous rapprocher et stabiliser la caméra.');
432
+ }
369
433
  const cardData = templateType.card_obb && Array.isArray(templateType.card_obb) && templateType.card_obb.length > 0
370
434
  ? templateType.card_obb[0]
371
435
  : null;
372
- if (cardData && typeof cardData.card_in_frame !== 'undefined') {
373
- const isCardInFrame = cardData.card_in_frame === true;
374
- const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
375
- if (!isCardInFrame || hasCroppedSides) {
376
- logger.log(`Template Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);
377
- throw new Error('CARD_NOT_FULLY_IN_FRAME');
436
+ if (!cardData) {
437
+ throw new Error('CARD_NOT_FULLY_IN_FRAME');
438
+ }
439
+ // Default to FALSE so it must prove it is in the frame
440
+ let points = null;
441
+ let isCardInFrame = false;
442
+ let hasCroppedSides = true;
443
+ // Extract data safely based on API response format
444
+ if (cardData.obb) {
445
+ points = cardData.obb;
446
+ if (typeof cardData.card_in_frame !== 'undefined') {
447
+ isCardInFrame = cardData.card_in_frame === true;
448
+ hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
449
+ }
450
+ }
451
+ else if (Array.isArray(cardData) && Array.isArray(cardData[0])) {
452
+ points = cardData[0];
453
+ isCardInFrame = true; // Passed initial existence check
454
+ hasCroppedSides = false;
455
+ // MATH FALLBACK: Check if the coordinates are touching the absolute edge of the photo.
456
+ if (points && points.length === 4) {
457
+ const minX = Math.min(...points.map((p) => p[0]));
458
+ const minY = Math.min(...points.map((p) => p[1]));
459
+ // If any corner is within 15 pixels of the edge, it is physically cut off!
460
+ if (minX <= 15 || minY <= 15) {
461
+ isCardInFrame = false;
462
+ hasCroppedSides = true;
463
+ }
378
464
  }
379
465
  }
466
+ // --- 3. STRICT FRAMING CHECK (MUST HAPPEN FIRST) ---
467
+ if (!isCardInFrame || hasCroppedSides) {
468
+ logger.log(`Template Framing failed. Coordinates hit image boundary.`);
469
+ throw new Error('CARD_NOT_FULLY_IN_FRAME');
470
+ }
380
471
  const LPIPS_THRESHOLD = 0.75;
381
472
  if (templateType.lpips_score !== undefined && templateType.lpips_score > LPIPS_THRESHOLD) {
382
473
  logger.log(`🛑 Country Mismatch! LPIPS Score too high: ${templateType.lpips_score}`);
@@ -1 +1 @@
1
- {"version":3,"file":"CardAuthentification.js","sourceRoot":"","sources":["../../../src/modules/api/CardAuthentification.ts"],"names":[],"mappings":"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","sourcesContent":["import kycService, { authentification, errorMessage, truncateFields } from \"./KYCService\";\nimport { cropByObb, getObbConfidence, OBB_CONFIDENCE_THRESHOLD } from \"../../utils/cropByObb\";\nimport { GovernmentDocumentType, IBbox } from \"../../types/KYC.types\";\nimport { KycEnvironment } from \"../../types/env.types\";\nimport { logger } from \"../../utils/logger\";\nimport { countryData } from \"../../config/countriesData\";\n\n// 1. Add this interface to tell TypeScript what the AI response actually looks like\ninterface CardObbData {\n obb: number[][];\n confidence: number;\n card_in_frame?: boolean;\n cropped_sides?: string[];\n}\n\ninterface ApiVerificationResponse {\n result?: boolean;\n detail?: any[];\n card_obb?: CardObbData[] | any; \n [key: string]: any; \n}\n\nexport async function frontVerification(\n result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, \n env: KycEnvironment = 'PRODUCTION'\n) {\n try {\n console.log(\"Front verification START\", JSON.stringify({ result }, null, 2));\n logger.log(\"Front verification\", JSON.stringify({ result }, null, 2));\n \n // SANDBOX mode\n if (env === 'SANDBOX') {\n console.log(\"SANDBOX mode: Skipping AI verification for front document\");\n logger.log(\"SANDBOX mode: Returning mock front verification response\");\n const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };\n \n const mockResponse = {\n result: true,\n detail: [{ confidence: 0.95 }],\n card_obb: [{\n obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n confidence: 0.95,\n card_in_frame: true,\n cropped_sides: []\n }],\n bbox: mockBbox,\n ...(result.regionMapping?.authMethod?.includes('MRZ') ? {\n mrz: {\n success: true,\n parsed_data: {\n status: 'success',\n document_type: result.selectedDocumentType,\n mrz_type: result.mrzType || 'TD1'\n }\n }\n } : {})\n };\n return mockResponse;\n }\n \n const token = await authentification();\n \n // Cast the response so TypeScript knows about card_obb\n const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '', env) as ApiVerificationResponse;\n\n if (!detected.result) {\n throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');\n }\n\n const cardData = detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0 \n ? detected.card_obb[0] \n : null;\n\n // --- STRICT FRAMING CHECK ---\n if (cardData && typeof cardData.card_in_frame !== 'undefined') {\n const isCardInFrame = cardData.card_in_frame === true;\n const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n\n // If it is NOT in the frame, OR if any side is cropped, block progression\n if (!isCardInFrame || hasCroppedSides) {\n logger.log(`Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n }\n\n // Check Confidence Threshold\n const obbConfidence = getObbConfidence(detected.card_obb);\n if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n\n // Optional: crop image using card_obb for better MRZ/barcode extraction\n let croppedBase64: string | undefined;\n let bbox: IBbox | undefined;\n let mrz: any | undefined;\n try {\n const crop = await cropByObb(result?.path || '', detected.card_obb);\n croppedBase64 = crop.base64;\n bbox = crop.bbox;\n } catch { }\n\n // MRZ Extraction\n if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ')) {\n mrz = await kycService.extractMrzText(\n {\n fileUri: result.path || '',\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || \"\",\n postfix: result?.currentSide,\n token: token,\n template_path: result?.templatePath || '',\n mrz_type: result?.mrzType || ''\n },\n env\n );\n }\n\n return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}) };\n } catch (e: any) {\n logger.error('Error front verification:', JSON.stringify(errorMessage(e), null, 2));\n throw new Error(e?.message || 'Erreur de détection du visage');\n }\n}\n\n// export async function frontVerification(\n// result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, \n// env: KycEnvironment = 'PRODUCTION'\n// ) {\n// try {\n// console.log(\"Front verification START\", JSON.stringify({ result }, null, 2));\n// logger.log(\"Front verification\", JSON.stringify({ result }, null, 2));\n \n// // SANDBOX mode\n// if (env === 'SANDBOX') {\n// console.log(\"SANDBOX mode: Skipping AI verification for front document\");\n// logger.log(\"SANDBOX mode: Returning mock front verification response\");\n// const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };\n \n// // ==========================================\n// // 🧪 TEST OVERRIDE (SANDBOX) 🧪\n// // Immediately throw the error to test the UI\n// // ==========================================\n// throw new Error('CARD_NOT_FULLY_IN_FRAME'); \n\n// const mockResponse = {\n// result: true,\n// detail: [{ confidence: 0.95 }],\n// card_obb: [{\n// obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n// confidence: 0.95,\n// card_in_frame: false, // Hardcoded to false\n// cropped_sides: ['left', 'top'] // Hardcoded cropped sides\n// }],\n// bbox: mockBbox,\n// ...(result.regionMapping?.authMethod?.includes('MRZ') ? {\n// mrz: {\n// success: true,\n// parsed_data: {\n// status: 'success',\n// document_type: result.selectedDocumentType,\n// mrz_type: result.mrzType || 'TD1'\n// }\n// }\n// } : {})\n// };\n// return mockResponse;\n// }\n \n// const token = await authentification();\n \n// // Cast the response so TypeScript knows about card_obb\n// const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '', env) as ApiVerificationResponse;\n\n// // ==========================================\n// // 🧪 TEST OVERRIDE (PRODUCTION) 🧪\n// // Hijack the real API response and force it to look cropped\n// // ==========================================\n// if (detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0) {\n// detected.card_obb[0].card_in_frame = false;\n// detected.card_obb[0].cropped_sides = ['left', 'top'];\n// console.warn(\"⚠️ FORCING CROPPED ERROR FOR UI TESTING ⚠️\");\n// }\n// // ==========================================\n\n// if (!detected.result) {\n// throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');\n// }\n\n// const cardData = detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0 \n// ? detected.card_obb[0] \n// : null;\n\n// // --- STRICT FRAMING CHECK ---\n// if (cardData && typeof cardData.card_in_frame !== 'undefined') {\n// const isCardInFrame = cardData.card_in_frame === true;\n// const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n\n// // If it is NOT in the frame, OR if any side is cropped, block progression\n// if (!isCardInFrame || hasCroppedSides) {\n// logger.log(`Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);\n// throw new Error('CARD_NOT_FULLY_IN_FRAME');\n// }\n// }\n\n// // Check Confidence Threshold\n// const obbConfidence = getObbConfidence(detected.card_obb);\n// if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {\n// throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n// }\n\n// // Optional: crop image using card_obb for better MRZ/barcode extraction\n// let croppedBase64: string | undefined;\n// let bbox: IBbox | undefined;\n// let mrz: any | undefined;\n// try {\n// const crop = await cropByObb(result?.path || '', detected.card_obb);\n// croppedBase64 = crop.base64;\n// bbox = crop.bbox;\n// } catch { }\n\n// // MRZ Extraction\n// if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ')) {\n// mrz = await kycService.extractMrzText(\n// {\n// fileUri: result.path || '',\n// docType: result?.selectedDocumentType || '',\n// docRegion: result?.code || \"\",\n// postfix: result?.currentSide,\n// token: token,\n// template_path: result?.templatePath || '',\n// mrz_type: result?.mrzType || ''\n// },\n// env\n// );\n// }\n\n// return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}) };\n// } catch (e: any) {\n// logger.error('Error front verification:', JSON.stringify(errorMessage(e), null, 2));\n// throw new Error(e?.message || 'Erreur de détection du visage');\n// }\n// }\n\n\nexport async function backVerification(\n result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, \n env: KycEnvironment = 'PRODUCTION'\n) {\n try {\n if (!result.path) throw new Error('No path provided');\n logger.log(\"result.regionMapping\", result.regionMapping, result.currentSide, result.code);\n \n \n if (env === 'SANDBOX') {\n console.log(\"SANDBOX mode: Skipping AI verification for back document\");\n \n const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };\n const mockCardObb = [{\n obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n confidence: 0.95,\n card_in_frame: true,\n cropped_sides: []\n }];\n \n if (result.regionMapping?.authMethod?.includes('MRZ')) {\n return {\n success: true,\n parsed_data: {\n status: 'success',\n document_type: result.selectedDocumentType,\n mrz_type: result.mrzType || 'TD1'\n },\n bbox: mockBbox,\n card_obb: mockCardObb\n };\n } else if (result.regionMapping?.authMethod?.includes('2D_barcode')) {\n return {\n barcode_data: 'SANDBOX_MOCK_BARCODE',\n bbox: mockBbox,\n card_obb: mockCardObb\n };\n }\n return { bbox: mockBbox };\n }\n \n const token = await authentification();\n\n \n logger.log(\"1. Checking template and framing for back document...\");\n \n const templateResponse = await kycService.checkTemplateType({\n fileUri: result.path,\n docType: result.selectedDocumentType as any,\n docRegion: result.code,\n postfix: 'back',\n token: token\n }, env) as ApiVerificationResponse;\n\n // STRICT FRAMING CHECK\n const cardData = templateResponse?.card_obb && Array.isArray(templateResponse.card_obb) && templateResponse.card_obb.length > 0 \n ? templateResponse.card_obb[0] \n : null;\n\n if (cardData && typeof cardData.card_in_frame !== 'undefined') {\n const isCardInFrame = cardData.card_in_frame === true;\n const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n\n if (!isCardInFrame || hasCroppedSides) {\n logger.log(`Back Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n }\n \n const obbConf = getObbConfidence(templateResponse?.card_obb);\n if (obbConf !== null && obbConf < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n\n\n const activeTemplatePath = templateResponse.template_path || result.templatePath || '';\n \n if (activeTemplatePath) {\n const expectedCountryName = countryData[result.code]?.name_en || '';\n \n const hasCodeMatch = activeTemplatePath.includes(`_${result.code}_`);\n const hasNameMatch = expectedCountryName && activeTemplatePath.toLowerCase().includes(expectedCountryName.toLowerCase());\n\n if (!hasCodeMatch && !hasNameMatch) {\n logger.log(`Template mismatch! Expected country: ${result.code} (${expectedCountryName}), Detected: ${activeTemplatePath}`);\n throw new Error(`Le document ne correspond pas au pays sélectionné (${result.code}).`);\n }\n }\n\n logger.log(\"Framing and Country Template verified successfully. Proceeding to Data Extraction.\");\n\n \n const tryMrzWithBarcodeFallback = async () => {\n try {\n logger.log(\"Tentative d'extraction MRZ\");\n const mrz = await kycService.extractMrzText({\n fileUri: result.path!,\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || '',\n postfix: 'back',\n token: token,\n template_path: activeTemplatePath, // Use the verified template\n mrz_type: result?.mrzType || ''\n }, env);\n \n let bbox: IBbox | undefined;\n let croppedBase64: string | undefined;\n\n try {\n // We use the OBB from our template check to ensure clean cropping\n const crop = await cropByObb(result?.path || '', templateResponse.card_obb);\n bbox = crop.bbox;\n croppedBase64 = crop.base64;\n } catch { }\n return { ...mrz, bbox, croppedBase64 }\n \n } catch (mrzError: any) {\n logger.log(\"MRZ échoué, tentative d'extraction barcode\");\n try {\n const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);\n return barcode;\n } catch (barcodeError: any) {\n throw new Error(`MRZ et barcode ont échoué. MRZ: ${mrzError?.message}, Barcode: ${barcodeError?.message}`);\n }\n }\n };\n\n if (result.regionMapping?.authMethod?.length > 2 && (!result?.mrzType || result?.mrzType.length === 0)) {\n return await tryMrzWithBarcodeFallback();\n }\n\n if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ') && result?.mrzType && result?.mrzType.length > 0) {\n try {\n const mrz = await kycService.extractMrzText({\n fileUri: result.path!,\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || '',\n postfix: 'back',\n token: token,\n template_path: activeTemplatePath,\n mrz_type: result?.mrzType || ''\n }, env);\n \n let bbox: IBbox | undefined;\n try {\n const crop = await cropByObb(result?.path || '', templateResponse.card_obb);\n bbox = crop.bbox;\n } catch { }\n return { ...mrz, bbox };\n } catch (mrzError: any) {\n throw new Error(`MRZ et barcode ont échoué. MRZ: ${mrzError?.message}, Barcode: ${mrzError?.message}`);\n }\n }\n\n if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('2D_barcode')) {\n try {\n logger.log(\"Tentative d'extraction barcode\");\n const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);\n \n let bbox: IBbox | undefined;\n try {\n const crop = await cropByObb(result?.path || '', templateResponse.card_obb);\n bbox = crop.bbox;\n } catch { }\n return { ...barcode, bbox };\n } catch (barcodeError: any) {\n throw new Error(`Barcode et MRZ ont échoué. Barcode: ${barcodeError?.message}, MRZ: ${barcodeError?.message}`);\n }\n }\n return null;\n } catch (e: any) {\n if (e?.message === 'CARD_NOT_FULLY_IN_FRAME') throw e; // Bubble the strict framing error specifically\n throw new Error(e?.message || 'Erreur de détection du MRZ ou barcode');\n }\n}\n\n\n/**\n * Check template type\n * @param result \n * @returns \n */\nexport async function checkTemplateType(result: { path?: string, docType: string, docRegion: string, postfix: string }, env: KycEnvironment = 'PRODUCTION') {\n try {\n if (env === 'SANDBOX') {\n return {\n template_path: `templates/${result.docType}_${result.docRegion}_${result.postfix}.jpg`,\n card_obb: [{\n obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n confidence: 0.95,\n card_in_frame: true,\n cropped_sides: []\n }]\n };\n }\n \n const token = await authentification();\n const templateType = await kycService.checkTemplateType({ fileUri: result.path || '', docType: result?.docType as GovernmentDocumentType, docRegion: result?.docRegion || \"\", postfix: result?.postfix, token: token }, env);\n\n const cardData = templateType.card_obb && Array.isArray(templateType.card_obb) && templateType.card_obb.length > 0 \n ? templateType.card_obb[0] \n : null;\n\n if (cardData && typeof cardData.card_in_frame !== 'undefined') {\n const isCardInFrame = cardData.card_in_frame === true;\n const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n\n if (!isCardInFrame || hasCroppedSides) {\n logger.log(`Template Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n }\n\n \n const LPIPS_THRESHOLD = 0.75; \n \n if (templateType.lpips_score !== undefined && templateType.lpips_score > LPIPS_THRESHOLD) {\n logger.log(`🛑 Country Mismatch! LPIPS Score too high: ${templateType.lpips_score}`);\n throw new Error(`Le document présenté ne correspond pas au pays sélectionné (${result.docRegion}).`);\n }\n\n logger.log(\"templateType result\", JSON.stringify(truncateFields(templateType), null, 2));\n return templateType;\n } catch (e: any) {\n logger.error('Error checking template type:', JSON.stringify(errorMessage(e), null, 2));\n \n if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message?.includes('ne correspond pas')) {\n throw e; \n }\n \n throw new Error(e?.message || 'Erreur de vérification du template');\n }\n}"]}
1
+ {"version":3,"file":"CardAuthentification.js","sourceRoot":"","sources":["../../../src/modules/api/CardAuthentification.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,EAAE,EAAE,gBAAgB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAG9F,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAiBzD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACnC,MAAgM,EAChM,MAAsB,YAAY;IAElC,IAAI,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7E,MAAM,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAEtE,eAAe;QACf,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;YACzE,MAAM,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;YACvE,MAAM,QAAQ,GAAU,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YAE5E,MAAM,YAAY,GAAG;gBACjB,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;gBAC9B,QAAQ,EAAE,CAAC;wBACP,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAC,IAAI,CAAC,CAAC;wBACrD,UAAU,EAAE,IAAI;wBAChB,aAAa,EAAE,IAAI;wBACnB,aAAa,EAAE,EAAE;qBACpB,CAAC;gBACF,IAAI,EAAE,QAAQ;gBACd,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACpD,GAAG,EAAE;wBACD,OAAO,EAAE,IAAI;wBACb,WAAW,EAAE;4BACT,MAAM,EAAE,SAAS;4BACjB,aAAa,EAAE,MAAM,CAAC,oBAAoB;4BAC1C,QAAQ,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;yBACpC;qBACJ;iBACJ,CAAC,CAAC,CAAC,EAAE,CAAC;aACV,CAAC;YACF,OAAO,YAAY,CAAC;QACxB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,gBAAgB,EAAE,CAAC;QAEvC,uDAAuD;QACvD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,IAAI,EAAE,EAAE,GAAG,CAA4B,CAAC;QAEhJ,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAClG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;YACtB,CAAC,CAAC,IAAI,CAAC;QAEX,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,IAAI,aAAa,GAAG,IAAI,CAAC;QACzB,IAAI,eAAe,GAAG,KAAK,CAAC;QAE5B,sBAAsB;QACtB,IAAI,QAAQ,EAAE,CAAC;YACX,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC;YACtB,IAAI,OAAO,QAAQ,CAAC,aAAa,KAAK,WAAW,EAAE,CAAC;gBAChD,aAAa,GAAG,QAAQ,CAAC,aAAa,KAAK,IAAI,CAAC;gBAChD,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,QAAQ,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;YACjG,CAAC;QACL,CAAC;QAED,sDAAsD;QACtD,IAAI,CAAC,aAAa,IAAI,eAAe,EAAE,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;YAC5D,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC/C,CAAC;QAED,iEAAiE;QACjE,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,WAAW,GAAG,CAAC,EAAY,EAAE,EAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACvH,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEvG,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9E,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9E,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAEjD,MAAM,cAAc,GAAG,eAAe,GAAG,mBAAmB,CAAC;YAC7D,MAAM,CAAC,GAAG,CAAC,+BAA+B,CAAC,cAAc,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAEhF,IAAI,cAAc,GAAG,IAAI,EAAE,CAAC;gBACxB,MAAM,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;gBACjE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;YACpC,CAAC;QACL,CAAC;QAMD,6BAA6B;QAC7B,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC1D,IAAI,aAAa,KAAK,IAAI,IAAI,aAAa,GAAG,wBAAwB,EAAE,CAAC;YACrE,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAChG,CAAC;QAED,wEAAwE;QACxE,IAAI,aAAiC,CAAC;QACtC,IAAI,IAAuB,CAAC;QAC5B,IAAI,GAAoB,CAAC;QACzB,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACpE,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC;YAC5B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC,CAAC,CAAC;QAEX,iBAAiB;QACjB,IAAI,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAClG,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,cAAc,CAC/C;gBACI,OAAO,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;gBAC1B,OAAO,EAAE,MAAM,EAAE,oBAAoB,IAAI,EAAE;gBAC3C,SAAS,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE;gBAC7B,OAAO,EAAE,MAAM,EAAE,WAAW;gBAC5B,KAAK,EAAE,KAAK;gBACZ,aAAa,EAAE,MAAM,EAAE,YAAY,IAAI,EAAE;gBACzC,QAAQ,EAAE,MAAM,EAAE,OAAO,IAAI,EAAE;aAClC,EACD,GAAG,CACN,CAAC;YAEF,yDAAyD;YACzD,GAAG,GAAG,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;YAE9E,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC;gBACjE,MAAM,CAAC,GAAG,CAAC,iCAAiC,EAAE,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;gBAC/E,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,WAAW,EAAE,cAAc,IAAI,4CAA4C,EAAE,CAAC,CAAC;YACzH,CAAC;QACL,CAAC;QAED,OAAO,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzE,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QACd,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;QACtD,iDAAiD;QACjD,MAAM,IAAI,KAAK,CAAC,CAAC,EAAE,OAAO,IAAI,+BAA+B,CAAC,CAAC;IACnE,CAAC;AACL,CAAC;AAED,2CAA2C;AAC3C,yMAAyM;AACzM,yCAAyC;AACzC,MAAM;AACN,YAAY;AACZ,wFAAwF;AACxF,iFAAiF;AAEjF,0BAA0B;AAC1B,mCAAmC;AACnC,wFAAwF;AACxF,sFAAsF;AACtF,2FAA2F;AAE3F,4DAA4D;AAC5D,+CAA+C;AAC/C,4DAA4D;AAC5D,4DAA4D;AAC5D,2DAA2D;AAE3D,qCAAqC;AACrC,gCAAgC;AAChC,kDAAkD;AAClD,+BAA+B;AAC/B,6EAA6E;AAC7E,wCAAwC;AACxC,kEAAkE;AAClE,gFAAgF;AAChF,sBAAsB;AACtB,kCAAkC;AAClC,4EAA4E;AAC5E,6BAA6B;AAC7B,yCAAyC;AACzC,yCAAyC;AACzC,iDAAiD;AACjD,0EAA0E;AAC1E,gEAAgE;AAChE,4BAA4B;AAC5B,wBAAwB;AACxB,0BAA0B;AAC1B,iBAAiB;AACjB,mCAAmC;AACnC,YAAY;AAEZ,kDAAkD;AAElD,kEAAkE;AAClE,2JAA2J;AAE3J,wDAAwD;AACxD,8CAA8C;AAC9C,uEAAuE;AACvE,wDAAwD;AACxD,uGAAuG;AACvG,0DAA0D;AAC1D,oEAAoE;AACpE,0EAA0E;AAC1E,YAAY;AACZ,wDAAwD;AAExD,kCAAkC;AAClC,yFAAyF;AACzF,YAAY;AAEZ,kHAAkH;AAClH,sCAAsC;AACtC,sBAAsB;AAEtB,0CAA0C;AAC1C,2EAA2E;AAC3E,qEAAqE;AACrE,kHAAkH;AAElH,yFAAyF;AACzF,uDAAuD;AACvD,iIAAiI;AACjI,8DAA8D;AAC9D,gBAAgB;AAChB,YAAY;AAEZ,wCAAwC;AACxC,qEAAqE;AACrE,oFAAoF;AACpF,2GAA2G;AAC3G,YAAY;AAEZ,mFAAmF;AACnF,iDAAiD;AACjD,uCAAuC;AACvC,oCAAoC;AACpC,gBAAgB;AAChB,mFAAmF;AACnF,2CAA2C;AAC3C,gCAAgC;AAChC,sBAAsB;AAEtB,4BAA4B;AAC5B,iHAAiH;AACjH,qDAAqD;AACrD,oBAAoB;AACpB,kDAAkD;AAClD,mEAAmE;AACnE,qDAAqD;AACrD,oDAAoD;AACpD,oCAAoC;AACpC,iEAAiE;AACjE,sDAAsD;AACtD,qBAAqB;AACrB,sBAAsB;AACtB,iBAAiB;AACjB,YAAY;AAEZ,gFAAgF;AAChF,yBAAyB;AACzB,+FAA+F;AAC/F,0EAA0E;AAC1E,QAAQ;AACR,IAAI;AAGJ,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,MAAgM,EAChM,MAAsB,YAAY;IAElC,IAAI,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAE1F,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;YAExE,MAAM,QAAQ,GAAU,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YAC5E,MAAM,WAAW,GAAG,CAAC;oBACjB,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAC,IAAI,CAAC,CAAC;oBACrD,UAAU,EAAE,IAAI;oBAChB,aAAa,EAAE,IAAI;oBACnB,aAAa,EAAE,EAAE;iBACpB,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpD,OAAO;oBACH,OAAO,EAAE,IAAI;oBACb,GAAG,EAAE;wBACD,OAAO,EAAE,IAAI;wBACb,WAAW,EAAE;4BACT,MAAM,EAAE,SAAS;4BACjB,aAAa,EAAE,MAAM,CAAC,oBAAoB;4BAC1C,QAAQ,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;yBACpC;qBACJ;oBACD,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,WAAW;iBACxB,CAAC;YACN,CAAC;iBAAM,IAAI,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBAClE,OAAO;oBACH,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,EAAE,YAAY,EAAE,sBAAsB,EAAE;oBACjD,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,WAAW;iBACxB,CAAC;YACN,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;QACpE,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,gBAAgB,EAAE,CAAC;QAEvC,MAAM,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;QAEpE,MAAM,gBAAgB,GAAG,MAAM,UAAU,CAAC,iBAAiB,CAAC;YACxD,OAAO,EAAE,MAAM,CAAC,IAAI;YACpB,OAAO,EAAE,MAAM,CAAC,oBAA2B;YAC3C,SAAS,EAAE,MAAM,CAAC,IAAI;YACtB,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,KAAK;SACf,EAAE,GAAG,CAA4B,CAAC;QAEnC,IAAI,gBAAgB,CAAC,OAAO,KAAK,KAAK,IAAI,gBAAgB,CAAC,KAAK,EAAE,CAAC;YAC/D,MAAM,CAAC,GAAG,CAAC,4BAA4B,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;YACjE,MAAM,IAAI,KAAK,CAAC,mFAAmF,CAAC,CAAC;QACzG,CAAC;QAED,MAAM,QAAQ,GAAG,gBAAgB,EAAE,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAC3H,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC9B,CAAC,CAAC,IAAI,CAAC;QAEX,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,IAAI,eAAe,GAAG,IAAI,CAAC;QAE3B,8CAA8C;QAC9C,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;YACf,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC;YACtB,IAAI,OAAO,QAAQ,CAAC,aAAa,KAAK,WAAW,EAAE,CAAC;gBAChD,aAAa,GAAG,QAAQ,CAAC,aAAa,KAAK,IAAI,CAAC;gBAChD,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,QAAQ,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;YACjG,CAAC;QACL,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACrB,aAAa,GAAG,IAAI,CAAC;YACrB,eAAe,GAAG,KAAK,CAAC;YAExB,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAChC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5D,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;oBAC3B,aAAa,GAAG,KAAK,CAAC;oBACtB,eAAe,GAAG,IAAI,CAAC;gBAC3B,CAAC;YACL,CAAC;QACL,CAAC;QAED,sDAAsD;QACtD,IAAI,CAAC,aAAa,IAAI,eAAe,EAAE,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;YACnE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC/C,CAAC;QAED,iEAAiE;QACjE,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,WAAW,GAAG,CAAC,EAAY,EAAE,EAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACvH,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEvG,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9E,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9E,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAEjD,MAAM,cAAc,GAAG,eAAe,GAAG,mBAAmB,CAAC;YAC7D,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC,cAAc,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAE/E,IAAI,cAAc,GAAG,IAAI,EAAE,CAAC;gBACxB,MAAM,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;gBAChE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;YACpC,CAAC;QACL,CAAC;QAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;QAC7D,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,GAAG,wBAAwB,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAChG,CAAC;QAED,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,aAAa,IAAI,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;QAEvF,IAAI,kBAAkB,EAAE,CAAC;YACrB,MAAM,mBAAmB,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,IAAI,EAAE,CAAC;YACpE,MAAM,YAAY,GAAG,kBAAkB,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;YACrE,MAAM,YAAY,GAAG,mBAAmB,IAAI,kBAAkB,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,CAAC,CAAC;YAEzH,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,EAAE,CAAC;gBACjC,MAAM,CAAC,GAAG,CAAC,wCAAwC,MAAM,CAAC,IAAI,KAAK,mBAAmB,gBAAgB,kBAAkB,EAAE,CAAC,CAAC;gBAC5H,MAAM,IAAI,KAAK,CAAC,sDAAsD,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;YAC3F,CAAC;QACL,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,oFAAoF,CAAC,CAAC;QAEjG,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,MAAM,CAAC;QAC9G,MAAM,UAAU,GAAG,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;QAE5E,IAAI,gBAAgB,GAAQ,EAAE,CAAC;QAE/B,oDAAoD;QACpD,IAAI,MAAM,EAAE,CAAC;YACT,IAAI,CAAC;gBACD,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;gBACzC,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC;oBAChD,OAAO,EAAE,MAAM,CAAC,IAAK;oBACrB,OAAO,EAAE,MAAM,EAAE,oBAAoB,IAAI,EAAE;oBAC3C,SAAS,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE;oBAC7B,OAAO,EAAE,MAAM;oBACf,KAAK,EAAE,KAAK;oBACZ,aAAa,EAAE,kBAAkB;oBACjC,QAAQ,EAAE,MAAM,EAAE,OAAO,IAAI,EAAE,CAAC,4BAA4B;iBAC/D,EAAE,GAAG,CAAC,CAAC;gBAER,MAAM,GAAG,GAAG,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;gBAEpF,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;oBAChE,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,cAAc,IAAI,qBAAqB,CAAC,CAAC;gBAC/E,CAAC;gBAED,gBAAgB,GAAG,EAAE,GAAG,EAAE,CAAC;YAE/B,CAAC;YAAC,OAAO,QAAa,EAAE,CAAC;gBACrB,IAAI,UAAU,EAAE,CAAC;oBACb,MAAM,CAAC,GAAG,CAAC,eAAe,QAAQ,EAAE,OAAO,sCAAsC,CAAC,CAAC;oBACnF,IAAI,CAAC;wBACD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,IAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;wBAC9F,gBAAgB,GAAG,EAAE,OAAO,EAAE,CAAC;oBACnC,CAAC;oBAAC,OAAO,YAAiB,EAAE,CAAC;wBACzB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;oBAChF,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACJ,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;gBAClE,CAAC;YACL,CAAC;QACL,CAAC;QACD,8BAA8B;aACzB,IAAI,UAAU,EAAE,CAAC;YACjB,IAAI,CAAC;gBACF,MAAM,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;gBACnD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,IAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;gBAC9F,gBAAgB,GAAG,EAAE,OAAO,EAAE,CAAC;YAClC,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;YAC9D,CAAC;QACN,CAAC;QAED,IAAI,IAAuB,CAAC;QAC5B,IAAI,aAAiC,CAAC;QAEtC,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAC5E,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACjB,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC,CAAC,CAAC;QAEX,OAAO;YACH,OAAO,EAAE,IAAI;YACb,GAAG,gBAAgB;YACnB,IAAI;YACJ,aAAa;YACb,QAAQ,EAAE,gBAAgB,CAAC,QAAQ;SACtC,CAAC;IAEN,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QACd,IAAI,CAAC,EAAE,OAAO,KAAK,yBAAyB,IAAI,CAAC,EAAE,OAAO,KAAK,cAAc,EAAE,CAAC;YAC5E,MAAM,CAAC,CAAC;QACZ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,CAAC,EAAE,OAAO,IAAI,iCAAiC,CAAC,CAAC;IACrE,CAAC;AACL,CAAC;AAGD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAA8E,EAAE,MAAsB,YAAY;IACtJ,IAAI,CAAC;QACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpB,OAAO;gBACH,aAAa,EAAE,aAAa,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,MAAM;gBACtF,QAAQ,EAAE,CAAC;wBACP,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAC,IAAI,CAAC,CAAC;wBACrD,UAAU,EAAE,IAAI;wBAChB,aAAa,EAAE,IAAI;wBACnB,aAAa,EAAE,EAAE;qBACpB,CAAC;aACL,CAAC;QACN,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,gBAAgB,EAAE,CAAC;QACvC,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,iBAAiB,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAiC,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;QAE7N,IAAI,YAAY,CAAC,OAAO,KAAK,KAAK,IAAI,YAAY,CAAC,KAAK,EAAE,CAAC;YACvD,MAAM,CAAC,GAAG,CAAC,4BAA4B,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,mFAAmF,CAAC,CAAC;QACzG,CAAC;QAED,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAC9G,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC1B,CAAC,CAAC,IAAI,CAAC;QAEX,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC/C,CAAC;QAED,uDAAuD;QACvD,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,IAAI,eAAe,GAAG,IAAI,CAAC;QAE3B,mDAAmD;QACnD,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;YACf,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC;YACtB,IAAI,OAAO,QAAQ,CAAC,aAAa,KAAK,WAAW,EAAE,CAAC;gBAChD,aAAa,GAAG,QAAQ,CAAC,aAAa,KAAK,IAAI,CAAC;gBAChD,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,QAAQ,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;YACjG,CAAC;QACL,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACrB,aAAa,GAAG,IAAI,CAAC,CAAC,iCAAiC;YACvD,eAAe,GAAG,KAAK,CAAC;YAExB,uFAAuF;YACvF,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAChC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5D,2EAA2E;gBAC3E,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;oBAC3B,aAAa,GAAG,KAAK,CAAC;oBACtB,eAAe,GAAG,IAAI,CAAC;gBAC3B,CAAC;YACL,CAAC;QACL,CAAC;QAED,sDAAsD;QACtD,IAAI,CAAC,aAAa,IAAI,eAAe,EAAE,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC/C,CAAC;QAGD,MAAM,eAAe,GAAG,IAAI,CAAC;QAE7B,IAAI,YAAY,CAAC,WAAW,KAAK,SAAS,IAAI,YAAY,CAAC,WAAW,GAAG,eAAe,EAAE,CAAC;YACvF,MAAM,CAAC,GAAG,CAAC,8CAA8C,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC;YACrF,MAAM,IAAI,KAAK,CAAC,+DAA+D,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;QACzG,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACzF,OAAO,YAAY,CAAC;IACxB,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QACd,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAExF,IAAI,CAAC,EAAE,OAAO,KAAK,yBAAyB,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACxF,MAAM,CAAC,CAAC;QACZ,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,CAAC,EAAE,OAAO,IAAI,oCAAoC,CAAC,CAAC;IACxE,CAAC;AACL,CAAC","sourcesContent":["import kycService, { authentification, errorMessage, truncateFields } from \"./KYCService\";\nimport { cropByObb, getObbConfidence, OBB_CONFIDENCE_THRESHOLD } from \"../../utils/cropByObb\";\nimport { GovernmentDocumentType, IBbox } from \"../../types/KYC.types\";\nimport { KycEnvironment } from \"../../types/env.types\";\nimport { logger } from \"../../utils/logger\";\nimport { countryData } from \"../../config/countriesData\";\n\n// 1. Add this interface to tell TypeScript what the AI response actually looks like\ninterface CardObbData {\n obb: number[][];\n confidence: number;\n card_in_frame?: boolean;\n cropped_sides?: string[];\n}\n\ninterface ApiVerificationResponse {\n result?: boolean;\n detail?: any[];\n card_obb?: CardObbData[] | any; \n [key: string]: any; \n}\n\nexport async function frontVerification(\n result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, \n env: KycEnvironment = 'PRODUCTION'\n) {\n try {\n console.log(\"Front verification START\", JSON.stringify({ result }, null, 2));\n logger.log(\"Front verification\", JSON.stringify({ result }, null, 2));\n \n // SANDBOX mode\n if (env === 'SANDBOX') {\n console.log(\"SANDBOX mode: Skipping AI verification for front document\");\n logger.log(\"SANDBOX mode: Returning mock front verification response\");\n const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };\n \n const mockResponse = {\n result: true,\n detail: [{ confidence: 0.95 }],\n card_obb: [{\n obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n confidence: 0.95,\n card_in_frame: true,\n cropped_sides: []\n }],\n bbox: mockBbox,\n ...(result.regionMapping?.authMethod?.includes('MRZ') ? {\n mrz: {\n success: true,\n parsed_data: {\n status: 'success',\n document_type: result.selectedDocumentType,\n mrz_type: result.mrzType || 'TD1'\n }\n }\n } : {})\n };\n return mockResponse;\n }\n \n const token = await authentification();\n \n // Cast the response so TypeScript knows about card_obb\n const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '', env) as ApiVerificationResponse;\n\n if (!detected.result) {\n throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');\n }\n\n const cardData = detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0 \n ? detected.card_obb[0] \n : null;\n\n let points = null;\n let isCardInFrame = true;\n let hasCroppedSides = false;\n\n // Extract data safely\n if (cardData) {\n points = cardData.obb;\n if (typeof cardData.card_in_frame !== 'undefined') {\n isCardInFrame = cardData.card_in_frame === true;\n hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n }\n }\n\n // --- 1. STRICT FRAMING CHECK (MUST HAPPEN FIRST) ---\n if (!isCardInFrame || hasCroppedSides) {\n logger.log(`Front Framing failed. Cropped sides detected.`);\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n\n // --- 2. STRICT DISTANCE CHECK (ONLY RUNS IF FULLY IN FRAME) ---\n if (points && points.length === 4) {\n const getDistance = (p1: number[], p2: number[]) => Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2));\n const longestCardEdge = Math.max(getDistance(points[0], points[1]), getDistance(points[1], points[2]));\n\n const maxX = Math.max(points[0][0], points[1][0], points[2][0], points[3][0]);\n const maxY = Math.max(points[0][1], points[1][1], points[2][1], points[3][1]);\n const estimatedImageScale = Math.max(maxX, maxY);\n\n const fillPercentage = longestCardEdge / estimatedImageScale;\n logger.log(`Front Card Fill Percentage: ${(fillPercentage * 100).toFixed(1)}%`);\n\n if (fillPercentage < 0.50) { \n logger.log(\"🛑 Front Image rejected: Document is too far away.\");\n throw new Error(\"TOO_FAR_AWAY\"); \n }\n }\n\n \n\n \n\n // Check Confidence Threshold\n const obbConfidence = getObbConfidence(detected.card_obb);\n if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n\n // Optional: crop image using card_obb for better MRZ/barcode extraction\n let croppedBase64: string | undefined;\n let bbox: IBbox | undefined;\n let mrz: any | undefined;\n try {\n const crop = await cropByObb(result?.path || '', detected.card_obb);\n croppedBase64 = crop.base64;\n bbox = crop.bbox;\n } catch { }\n\n // MRZ Extraction\n if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ')) {\n const mrzResponse = await kycService.extractMrzText(\n {\n fileUri: result.path || '',\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || \"\",\n postfix: result?.currentSide,\n token: token,\n template_path: result?.templatePath || '',\n mrz_type: result?.mrzType || ''\n },\n env\n );\n\n // Safety check: parse if it was returned as a raw string\n mrz = typeof mrzResponse === 'string' ? JSON.parse(mrzResponse) : mrzResponse;\n\n if (mrz && (!mrz.success || mrz.parsed_data?.status === 'FAILURE')) {\n logger.log(\"🛑 Front MRZ Extraction Failed:\", mrz.parsed_data?.status_message);\n throw new Error(`MRZ illisible: ${mrz.parsed_data?.status_message || 'Veuillez nettoyer l\\'objectif et réessayer'}`);\n }\n }\n\n return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}) };\n } catch (e: any) {\n logger.error('Error front verification:', e?.message);\n // Do not use LogBox for background silent errors\n throw new Error(e?.message || 'Erreur de détection du visage');\n }\n}\n\n// export async function frontVerification(\n// result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, \n// env: KycEnvironment = 'PRODUCTION'\n// ) {\n// try {\n// console.log(\"Front verification START\", JSON.stringify({ result }, null, 2));\n// logger.log(\"Front verification\", JSON.stringify({ result }, null, 2));\n \n// // SANDBOX mode\n// if (env === 'SANDBOX') {\n// console.log(\"SANDBOX mode: Skipping AI verification for front document\");\n// logger.log(\"SANDBOX mode: Returning mock front verification response\");\n// const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };\n \n// // ==========================================\n// // 🧪 TEST OVERRIDE (SANDBOX) 🧪\n// // Immediately throw the error to test the UI\n// // ==========================================\n// throw new Error('CARD_NOT_FULLY_IN_FRAME'); \n\n// const mockResponse = {\n// result: true,\n// detail: [{ confidence: 0.95 }],\n// card_obb: [{\n// obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n// confidence: 0.95,\n// card_in_frame: false, // Hardcoded to false\n// cropped_sides: ['left', 'top'] // Hardcoded cropped sides\n// }],\n// bbox: mockBbox,\n// ...(result.regionMapping?.authMethod?.includes('MRZ') ? {\n// mrz: {\n// success: true,\n// parsed_data: {\n// status: 'success',\n// document_type: result.selectedDocumentType,\n// mrz_type: result.mrzType || 'TD1'\n// }\n// }\n// } : {})\n// };\n// return mockResponse;\n// }\n \n// const token = await authentification();\n \n// // Cast the response so TypeScript knows about card_obb\n// const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '', env) as ApiVerificationResponse;\n\n// // ==========================================\n// // 🧪 TEST OVERRIDE (PRODUCTION) 🧪\n// // Hijack the real API response and force it to look cropped\n// // ==========================================\n// if (detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0) {\n// detected.card_obb[0].card_in_frame = false;\n// detected.card_obb[0].cropped_sides = ['left', 'top'];\n// console.warn(\"⚠️ FORCING CROPPED ERROR FOR UI TESTING ⚠️\");\n// }\n// // ==========================================\n\n// if (!detected.result) {\n// throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');\n// }\n\n// const cardData = detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0 \n// ? detected.card_obb[0] \n// : null;\n\n// // --- STRICT FRAMING CHECK ---\n// if (cardData && typeof cardData.card_in_frame !== 'undefined') {\n// const isCardInFrame = cardData.card_in_frame === true;\n// const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n\n// // If it is NOT in the frame, OR if any side is cropped, block progression\n// if (!isCardInFrame || hasCroppedSides) {\n// logger.log(`Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);\n// throw new Error('CARD_NOT_FULLY_IN_FRAME');\n// }\n// }\n\n// // Check Confidence Threshold\n// const obbConfidence = getObbConfidence(detected.card_obb);\n// if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {\n// throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n// }\n\n// // Optional: crop image using card_obb for better MRZ/barcode extraction\n// let croppedBase64: string | undefined;\n// let bbox: IBbox | undefined;\n// let mrz: any | undefined;\n// try {\n// const crop = await cropByObb(result?.path || '', detected.card_obb);\n// croppedBase64 = crop.base64;\n// bbox = crop.bbox;\n// } catch { }\n\n// // MRZ Extraction\n// if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ')) {\n// mrz = await kycService.extractMrzText(\n// {\n// fileUri: result.path || '',\n// docType: result?.selectedDocumentType || '',\n// docRegion: result?.code || \"\",\n// postfix: result?.currentSide,\n// token: token,\n// template_path: result?.templatePath || '',\n// mrz_type: result?.mrzType || ''\n// },\n// env\n// );\n// }\n\n// return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}) };\n// } catch (e: any) {\n// logger.error('Error front verification:', JSON.stringify(errorMessage(e), null, 2));\n// throw new Error(e?.message || 'Erreur de détection du visage');\n// }\n// }\n\n\nexport async function backVerification(\n result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, \n env: KycEnvironment = 'PRODUCTION'\n) {\n try {\n if (!result.path) throw new Error('No path provided');\n logger.log(\"result.regionMapping\", result.regionMapping, result.currentSide, result.code);\n \n if (env === 'SANDBOX') {\n console.log(\"SANDBOX mode: Skipping AI verification for back document\");\n \n const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };\n const mockCardObb = [{\n obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n confidence: 0.95,\n card_in_frame: true,\n cropped_sides: []\n }];\n \n if (result.regionMapping?.authMethod?.includes('MRZ')) {\n return {\n success: true,\n mrz: { \n success: true,\n parsed_data: {\n status: 'SUCCESS', \n document_type: result.selectedDocumentType,\n mrz_type: result.mrzType || 'TD1'\n }\n },\n bbox: mockBbox,\n card_obb: mockCardObb\n };\n } else if (result.regionMapping?.authMethod?.includes('2D_barcode')) {\n return {\n success: true,\n barcode: { barcode_data: 'SANDBOX_MOCK_BARCODE' },\n bbox: mockBbox,\n card_obb: mockCardObb\n };\n }\n return { success: true, bbox: mockBbox, card_obb: mockCardObb };\n }\n \n const token = await authentification();\n\n logger.log(\"1. Checking template and framing for back document...\");\n \n const templateResponse = await kycService.checkTemplateType({\n fileUri: result.path,\n docType: result.selectedDocumentType as any,\n docRegion: result.code,\n postfix: 'back',\n token: token\n }, env) as ApiVerificationResponse;\n\n if (templateResponse.success === false || templateResponse.Error) {\n logger.log(\"Backend returned an error:\", templateResponse.Error);\n throw new Error('Impossible de lire le document. Veuillez vous rapprocher et stabiliser la caméra.');\n }\n\n const cardData = templateResponse?.card_obb && Array.isArray(templateResponse.card_obb) && templateResponse.card_obb.length > 0 \n ? templateResponse.card_obb[0] \n : null;\n\n if (!cardData) {\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n\n let points = null;\n let isCardInFrame = false; \n let hasCroppedSides = true; \n\n // Safely extract coordinates and frame status\n if (cardData.obb) { \n points = cardData.obb;\n if (typeof cardData.card_in_frame !== 'undefined') {\n isCardInFrame = cardData.card_in_frame === true;\n hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n }\n } else if (Array.isArray(cardData) && Array.isArray(cardData[0])) { \n points = cardData[0];\n isCardInFrame = true; \n hasCroppedSides = false;\n \n if (points && points.length === 4) {\n const minX = Math.min(...points.map((p: number[]) => p[0]));\n const minY = Math.min(...points.map((p: number[]) => p[1]));\n if (minX <= 15 || minY <= 15) {\n isCardInFrame = false;\n hasCroppedSides = true;\n }\n }\n }\n\n // --- 2. STRICT FRAMING CHECK (MUST HAPPEN FIRST) ---\n if (!isCardInFrame || hasCroppedSides) {\n logger.log(`Back Framing failed. Coordinates hit image boundary.`);\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n\n // --- 3. STRICT DISTANCE CHECK (ONLY RUNS IF FULLY IN FRAME) ---\n if (points && points.length === 4) {\n const getDistance = (p1: number[], p2: number[]) => Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2));\n const longestCardEdge = Math.max(getDistance(points[0], points[1]), getDistance(points[1], points[2]));\n\n const maxX = Math.max(points[0][0], points[1][0], points[2][0], points[3][0]);\n const maxY = Math.max(points[0][1], points[1][1], points[2][1], points[3][1]);\n const estimatedImageScale = Math.max(maxX, maxY);\n\n const fillPercentage = longestCardEdge / estimatedImageScale;\n logger.log(`Back Card Fill Percentage: ${(fillPercentage * 100).toFixed(1)}%`);\n\n if (fillPercentage < 0.50) { \n logger.log(\"🛑 Back Image rejected: Document is too far away.\");\n throw new Error(\"TOO_FAR_AWAY\"); \n }\n }\n \n const obbConf = getObbConfidence(templateResponse?.card_obb);\n if (obbConf !== null && obbConf < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n\n const activeTemplatePath = templateResponse.template_path || result.templatePath || '';\n \n if (activeTemplatePath) {\n const expectedCountryName = countryData[result.code]?.name_en || '';\n const hasCodeMatch = activeTemplatePath.includes(`_${result.code}_`);\n const hasNameMatch = expectedCountryName && activeTemplatePath.toLowerCase().includes(expectedCountryName.toLowerCase());\n\n if (!hasCodeMatch && !hasNameMatch) {\n logger.log(`Template mismatch! Expected country: ${result.code} (${expectedCountryName}), Detected: ${activeTemplatePath}`);\n throw new Error(`Le document ne correspond pas au pays sélectionné (${result.code}).`);\n }\n }\n\n logger.log(\"Framing and Country Template verified successfully. Proceeding to Data Extraction.\");\n\n const hasMrz = result.regionMapping?.authMethod?.includes('MRZ') || !result.regionMapping?.authMethod?.length;\n const hasBarcode = result.regionMapping?.authMethod?.includes('2D_barcode');\n\n let extractionResult: any = {};\n\n // --- 4. Try MRZ First (If required or default) ---\n if (hasMrz) {\n try {\n logger.log(\"Tentative d'extraction MRZ\");\n const mrzResponse = await kycService.extractMrzText({\n fileUri: result.path!,\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || '',\n postfix: 'back',\n token: token,\n template_path: activeTemplatePath, \n mrz_type: result?.mrzType || '' // Safe to send empty string\n }, env);\n \n const mrz = typeof mrzResponse === 'string' ? JSON.parse(mrzResponse) : mrzResponse;\n \n if (!mrz || !mrz.success || mrz.parsed_data?.status === 'FAILURE') {\n throw new Error(mrz?.parsed_data?.status_message || 'Lecture MRZ échouée');\n }\n \n extractionResult = { mrz };\n\n } catch (mrzError: any) {\n if (hasBarcode) {\n logger.log(`MRZ échoué (${mrzError?.message}), tentative d'extraction barcode...`);\n try {\n const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);\n extractionResult = { barcode };\n } catch (barcodeError: any) {\n throw new Error(`MRZ et Barcode ont échoué. Veuillez stabiliser la carte.`);\n }\n } else {\n throw new Error(`Lecture MRZ invalide: ${mrzError?.message}`);\n }\n }\n } \n // --- 5. Try Barcode Only ---\n else if (hasBarcode) {\n try {\n logger.log(\"Tentative d'extraction barcode seule\");\n const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);\n extractionResult = { barcode };\n } catch (e: any) {\n throw new Error(`Lecture Barcode échouée: ${e?.message}`);\n }\n }\n\n let bbox: IBbox | undefined;\n let croppedBase64: string | undefined;\n\n try {\n const crop = await cropByObb(result?.path || '', templateResponse.card_obb);\n bbox = crop.bbox;\n croppedBase64 = crop.base64;\n } catch { }\n\n return { \n success: true,\n ...extractionResult, \n bbox, \n croppedBase64, \n card_obb: templateResponse.card_obb \n };\n\n } catch (e: any) {\n if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message === 'TOO_FAR_AWAY') {\n throw e; \n }\n throw new Error(e?.message || 'Erreur de détection des données');\n }\n}\n\n\n/**\n * Check template type\n * @param result \n * @returns \n */\nexport async function checkTemplateType(result: { path?: string, docType: string, docRegion: string, postfix: string }, env: KycEnvironment = 'PRODUCTION') {\n try {\n if (env === 'SANDBOX') {\n return {\n template_path: `templates/${result.docType}_${result.docRegion}_${result.postfix}.jpg`,\n card_obb: [{\n obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n confidence: 0.95,\n card_in_frame: true,\n cropped_sides: []\n }]\n };\n }\n \n const token = await authentification();\n const templateType = await kycService.checkTemplateType({ fileUri: result.path || '', docType: result?.docType as GovernmentDocumentType, docRegion: result?.docRegion || \"\", postfix: result?.postfix, token: token }, env);\n\n if (templateType.success === false || templateType.Error) {\n logger.log(\"Backend returned an error:\", templateType.Error);\n throw new Error('Impossible de lire le document. Veuillez vous rapprocher et stabiliser la caméra.');\n }\n\n const cardData = templateType.card_obb && Array.isArray(templateType.card_obb) && templateType.card_obb.length > 0 \n ? templateType.card_obb[0] \n : null;\n\n if (!cardData) {\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n\n // Default to FALSE so it must prove it is in the frame\n let points = null;\n let isCardInFrame = false; \n let hasCroppedSides = true; \n\n // Extract data safely based on API response format\n if (cardData.obb) { \n points = cardData.obb;\n if (typeof cardData.card_in_frame !== 'undefined') {\n isCardInFrame = cardData.card_in_frame === true;\n hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n }\n } else if (Array.isArray(cardData) && Array.isArray(cardData[0])) { \n points = cardData[0];\n isCardInFrame = true; // Passed initial existence check\n hasCroppedSides = false;\n \n // MATH FALLBACK: Check if the coordinates are touching the absolute edge of the photo.\n if (points && points.length === 4) {\n const minX = Math.min(...points.map((p: number[]) => p[0]));\n const minY = Math.min(...points.map((p: number[]) => p[1]));\n // If any corner is within 15 pixels of the edge, it is physically cut off!\n if (minX <= 15 || minY <= 15) {\n isCardInFrame = false;\n hasCroppedSides = true;\n }\n }\n }\n\n // --- 3. STRICT FRAMING CHECK (MUST HAPPEN FIRST) ---\n if (!isCardInFrame || hasCroppedSides) {\n logger.log(`Template Framing failed. Coordinates hit image boundary.`);\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n\n \n const LPIPS_THRESHOLD = 0.75; \n \n if (templateType.lpips_score !== undefined && templateType.lpips_score > LPIPS_THRESHOLD) {\n logger.log(`🛑 Country Mismatch! LPIPS Score too high: ${templateType.lpips_score}`);\n throw new Error(`Le document présenté ne correspond pas au pays sélectionné (${result.docRegion}).`);\n }\n\n logger.log(\"templateType result\", JSON.stringify(truncateFields(templateType), null, 2));\n return templateType;\n } catch (e: any) {\n logger.error('Error checking template type:', JSON.stringify(errorMessage(e), null, 2));\n \n if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message?.includes('ne correspond pas')) {\n throw e; \n }\n \n throw new Error(e?.message || 'Erreur de vérification du template');\n }\n}"]}
@@ -76,7 +76,7 @@ export declare class KYCService {
76
76
  postfix?: string;
77
77
  token: string;
78
78
  template_path: string;
79
- mrz_type: string;
79
+ mrz_type?: string;
80
80
  }, env?: KycEnvironment): Promise<any>;
81
81
  recognizeFace(params: {
82
82
  idPhotoUri: string;
@@ -1 +1 @@
1
- {"version":3,"file":"KYCService.d.ts","sourceRoot":"","sources":["../../../src/modules/api/KYCService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"KYCService.d.ts","sourceRoot":"","sources":["../../../src/modules/api/KYCService.ts"],"names":[],"mappings":"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"}