@trustchex/react-native-sdk 1.472.0 → 1.475.1

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 (30) hide show
  1. package/android/build.gradle +3 -3
  2. package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +147 -9
  3. package/ios/Camera/TrustchexCameraView.swift +92 -19
  4. package/lib/module/Screens/Debug/MRZTestScreen.js +121 -147
  5. package/lib/module/Screens/Static/ResultScreen.js +5 -0
  6. package/lib/module/Shared/Components/IdentityDocumentCamera.js +38 -4
  7. package/lib/module/Shared/Libs/MRZ_KNOWN_ISSUES.md +112 -0
  8. package/lib/module/Shared/Libs/mrz.utils.js +639 -16
  9. package/lib/module/Shared/Libs/mrzFrameAggregator.js +301 -0
  10. package/lib/module/Shared/Libs/mrzOcrIntegration.js +109 -0
  11. package/lib/module/version.js +1 -1
  12. package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts.map +1 -1
  13. package/lib/typescript/src/Screens/Static/ResultScreen.d.ts.map +1 -1
  14. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
  15. package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts +8 -0
  16. package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
  17. package/lib/typescript/src/Shared/Libs/mrzFrameAggregator.d.ts +76 -0
  18. package/lib/typescript/src/Shared/Libs/mrzFrameAggregator.d.ts.map +1 -0
  19. package/lib/typescript/src/Shared/Libs/mrzOcrIntegration.d.ts +73 -0
  20. package/lib/typescript/src/Shared/Libs/mrzOcrIntegration.d.ts.map +1 -0
  21. package/lib/typescript/src/version.d.ts +1 -1
  22. package/package.json +15 -10
  23. package/src/Screens/Debug/MRZTestScreen.tsx +137 -166
  24. package/src/Screens/Static/ResultScreen.tsx +5 -0
  25. package/src/Shared/Components/IdentityDocumentCamera.tsx +46 -6
  26. package/src/Shared/Libs/MRZ_KNOWN_ISSUES.md +112 -0
  27. package/src/Shared/Libs/mrz.utils.ts +704 -11
  28. package/src/Shared/Libs/mrzFrameAggregator.ts +370 -0
  29. package/src/Shared/Libs/mrzOcrIntegration.ts +175 -0
  30. package/src/version.ts +1 -1
@@ -0,0 +1,112 @@
1
+ # MRZ Reading & Correction — Known Issues & Limitations
2
+
3
+ This documents the **inherent limitations** and **deliberate trade-offs** of the
4
+ MRZ camera scanner (`mrz.utils.ts`, `mrzFrameAggregator.ts`, and the native
5
+ `TrustchexCameraView` scan-frame OCR). These are not bugs — they are constraints
6
+ of the ICAO 9303 standard and OCR, and the design decisions made around them.
7
+
8
+ For the camera/OCR pipeline overview, see the doc comments in
9
+ `mrzFrameAggregator.ts` and `mrz.utils.ts`.
10
+
11
+ ---
12
+
13
+ ## 1. Check-digit MOD-10 collisions: `1↔L` and `6↔G` are indistinguishable
14
+
15
+ **Issue.** ICAO's 7-3-1 check digit weights letters by value (`A`=10 … `Z`=35),
16
+ then takes the result mod 10. Some OCR look-alikes are **mod-10 equal** to the
17
+ digit they resemble:
18
+
19
+ | Look-alike | Letter value | Digit | mod 10 |
20
+ | --- | --- | --- | --- |
21
+ | `L` ↔ `1` | 21 | 1 | both ≡ **1** |
22
+ | `G` ↔ `6` | 16 | 6 | both ≡ **6** |
23
+
24
+ So a document number read as `SPECL2345` produces the **exact same check digit**
25
+ as the correct `SPEC12345`. The MRZ **validates either way** — the check digit
26
+ cannot tell them apart.
27
+
28
+ **Impact.** If OCR reads a `1` as `L` (or `6` as `G`) in a *numeric* position of a
29
+ field that also accepts letters (e.g. an alphanumeric document number), the MRZ
30
+ will validate but may carry the letter form.
31
+
32
+ **Mitigation.**
33
+
34
+ - **Multi-frame voting** (`mrzFrameAggregator`) usually resolves it: across frames
35
+ the correct glyph wins the per-character vote.
36
+ - **NFC chip read (eID)** is authoritative — when available it overrides the
37
+ camera reading.
38
+ - Other digit↔letter confusions (`0↔O/Q/D`, `2↔Z`, `5↔S`, `8↔B`, `4↔A`, `1↔I`) are
39
+ **not** mod-10 collisions and *are* recovered to the correct digit.
40
+
41
+ Covered by `mrz.ambiguous.test.ts` ("documents the … MOD-10 collision").
42
+
43
+ ---
44
+
45
+ ## 2. Unprotected fields (TD1 optional / national-ID) can't be self-corrected
46
+
47
+ **Issue.** TD1's optional-data field (which on Turkish IDs holds the 11-digit
48
+ national ID / TC number) has **no per-field check digit** — it is only covered by
49
+ the composite check digit. If OCR corrupts the optional field **and** the
50
+ composite digit is also dropped/misread (common on glossy cards), there is no
51
+ independent anchor to detect the error.
52
+
53
+ **Mitigation.** High-confidence numeric normalisation (`B→8`, `S→5`, `O→0`, …) is
54
+ applied to the all-digit optional field, and **multi-frame voting** is the
55
+ primary safeguard. A single noisy frame is not trusted; the consensus is.
56
+
57
+ ---
58
+
59
+ ## 3. Filler-letter normalisation is conservative in name fields (by design)
60
+
61
+ **Issue.** The `<` filler is frequently OCR'd as a letter (`K`, and under glare
62
+ `C`/`E`/`G`). We normalise these back to `<` **only** in structurally
63
+ unambiguous positions — the trailing filler run, the TD1 issuing-state field, and
64
+ the document-code filler.
65
+
66
+ **Deliberate trade-off.** A `K`/`C`/`E`/`G` **inside the name field** is *not*
67
+ normalised, because it cannot be distinguished from a real name letter (surnames
68
+ like `AKTAS`, `KAYA`, `CETIN`, or a 2-letter `AK` start with these). Corrupting a
69
+ real name is worse than a cosmetic filler glyph, so:
70
+
71
+ - Names are **preserved verbatim** — `AKTAS` stays `AKTAS`.
72
+ - A genuine filler misread *in the middle of a name region* may remain as a
73
+ letter (cosmetic only; the name field has no check digit, so validity is
74
+ unaffected, and the document number / dates — the identity-critical fields —
75
+ are always cleaned).
76
+
77
+ Covered by the "real letters in names are not eaten" tests in `mrz.utils.test.ts`.
78
+
79
+ ---
80
+
81
+ ## 4. OCR throughput / image-quality dependence
82
+
83
+ - **Resolution.** ML Kit needs ~16 px per character. A full-frame capture leaves a
84
+ 30–44-char MRZ line below that floor, so the native pipeline **crops to the
85
+ on-screen scan frame and upscales + grayscale/contrast-enhances** before OCR.
86
+ The MRZ band must be reasonably filled within the on-screen guide.
87
+ - **Glare / lamination.** Heavy glare on a glossy laminated card still degrades
88
+ OCR; the enhancement helps but does not eliminate it. Steadying the card and
89
+ reducing direct glare improves convergence.
90
+ - **Throughput.** OCR runs at a few frames/sec; the JS handler is throttled
91
+ (~400 ms) and the recovery search is time-bounded so the UI stays responsive.
92
+ A pathological/garbage frame fails fast (recovery budget) rather than blocking.
93
+
94
+ ---
95
+
96
+ ## 5. Structurally broken frames are (correctly) rejected
97
+
98
+ Truncated or wrong-length line-sets that cannot be repaired by ambiguous-char
99
+ swaps or ±1 indel are reported **invalid** — the flow will not advance on a
100
+ guess. This is intentional: a wrong-but-plausible reconstruction must never leak
101
+ through. Multi-frame scanning accumulates until a check-digit-valid consensus is
102
+ reached.
103
+
104
+ ---
105
+
106
+ ## 6. Platform parity
107
+
108
+ The scan-frame ROI crop + grayscale/contrast enhancement exists on **both Android
109
+ (Kotlin) and iOS (Swift / Core Image)**. The JS recovery, voting, and field
110
+ mapping are shared, so behaviour is consistent across platforms. Debug builds
111
+ require Metro to be reachable; build a **Release** variant for untethered device
112
+ testing.