@incodetech/core 2.0.0 → 2.0.1-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/dist/Actor-CI32dTbG.d.ts +2 -0
  2. package/dist/BaseWasmProvider-C_DLEI40.esm.js +1118 -0
  3. package/dist/BrowserStorageProvider-CuOW1Er2.esm.js +55 -0
  4. package/dist/BrowserTimerProvider-DhNc_x02.esm.js +22 -0
  5. package/dist/ITimerCapability-C67ZRskg.esm.js +7 -0
  6. package/dist/IpifyProvider-D7jx52AL.esm.js +139 -0
  7. package/dist/Manager-C8PrhBOx.d.ts +19 -0
  8. package/dist/MotionSensorProvider-4v7xkqAp.esm.js +254 -0
  9. package/dist/OpenViduRecordingProvider-CMu6XVdc.esm.js +87 -0
  10. package/dist/StateMachine-BCQrZJhf.d.ts +2 -0
  11. package/dist/WasmUtilProvider-j98OJf-S.esm.js +114 -0
  12. package/dist/addressSearch-BpTbTWCa.esm.js +430 -0
  13. package/dist/ae-signature-DDDZmWXj.esm.js +12 -0
  14. package/dist/ae-signature.d.ts +25 -0
  15. package/dist/ae-signature.esm.js +8 -0
  16. package/dist/antifraud.d.ts +57 -0
  17. package/dist/antifraud.esm.js +45 -0
  18. package/dist/antifraudStateMachine-O0TMf6yc.esm.js +39 -0
  19. package/dist/api-CESGtpbH.esm.js +53 -0
  20. package/dist/authentication.d.ts +12 -0
  21. package/dist/authentication.esm.js +25 -0
  22. package/dist/authenticationManager-5M-fKzXx.esm.js +67 -0
  23. package/dist/authenticationManager-C83GNIhl.d.ts +66 -0
  24. package/dist/authenticationStateMachine-BMZqatiF.esm.js +139 -0
  25. package/dist/backCameraStream-DMdMeGk2.esm.js +346 -0
  26. package/dist/browserSimulation-gxD8cSpM.esm.js +20 -0
  27. package/dist/camera-DBSxa6ML.d.ts +4 -0
  28. package/dist/camera-PA2Ljri3.esm.js +22 -0
  29. package/dist/camera.d.ts +15 -0
  30. package/dist/camera.esm.js +5 -0
  31. package/dist/chunk-CRF6K_H_.esm.js +49 -0
  32. package/dist/consent.d.ts +398 -0
  33. package/dist/consent.esm.js +79 -0
  34. package/dist/consentStateMachine-CCT-B60O.esm.js +151 -0
  35. package/dist/cpf-PPz2Njto.esm.js +38 -0
  36. package/dist/cpf-ocr.d.ts +204 -0
  37. package/dist/cpf-ocr.esm.js +177 -0
  38. package/dist/cross-document-data-match.d.ts +34 -0
  39. package/dist/cross-document-data-match.esm.js +71 -0
  40. package/dist/curp-validation.d.ts +188 -0
  41. package/dist/curp-validation.esm.js +110 -0
  42. package/dist/curpValidationStateMachine-CitWLr2c.esm.js +595 -0
  43. package/dist/custom-fields.d.ts +115 -0
  44. package/dist/custom-fields.esm.js +177 -0
  45. package/dist/custom-watchlist.d.ts +66 -0
  46. package/dist/custom-watchlist.esm.js +86 -0
  47. package/dist/dateUtils-UoN5xswP.esm.js +23 -0
  48. package/dist/deepsightLoader-Cm4JIT_z.esm.js +52 -0
  49. package/dist/deepsightService-CEVxzehb.d.ts +412 -0
  50. package/dist/deepsightService-O74l4Y__.esm.js +489 -0
  51. package/dist/device.d.ts +46 -0
  52. package/dist/device.esm.js +106 -0
  53. package/dist/displayErrors-DqJ_IbsG.d.ts +39 -0
  54. package/dist/document-capture.d.ts +906 -0
  55. package/dist/document-capture.esm.js +156 -0
  56. package/dist/document-upload.d.ts +331 -0
  57. package/dist/document-upload.esm.js +203 -0
  58. package/dist/documentCaptureStateMachine-BqzTDy9k.esm.js +394 -0
  59. package/dist/dynamic-forms.d.ts +178 -0
  60. package/dist/dynamic-forms.esm.js +323 -0
  61. package/dist/ekyb.d.ts +148 -0
  62. package/dist/ekyb.esm.js +127 -0
  63. package/dist/ekybStateMachine-BR2let5f.esm.js +674 -0
  64. package/dist/ekyc.d.ts +164 -0
  65. package/dist/ekyc.esm.js +104 -0
  66. package/dist/ekycStateMachine-oeO0Iekd.esm.js +10626 -0
  67. package/dist/electronic-signature.d.ts +4 -0
  68. package/dist/electronic-signature.esm.js +7 -0
  69. package/dist/electronicSignatureManager-D9OHzTpG.esm.js +428 -0
  70. package/dist/email.d.ts +4 -0
  71. package/dist/email.esm.js +9 -0
  72. package/dist/emailManager-DIfnS5g1.d.ts +352 -0
  73. package/dist/emailManager-wAV0LE-H.esm.js +238 -0
  74. package/dist/emailStateMachine-DOf4j58N.esm.js +292 -0
  75. package/dist/endpoints-CnN3SyDa.esm.js +87 -0
  76. package/dist/events-D6-e4vok.esm.js +596 -0
  77. package/dist/events.d.ts +265 -0
  78. package/dist/events.esm.js +4 -0
  79. package/dist/extensibility.d.ts +122 -0
  80. package/dist/extensibility.esm.js +43 -0
  81. package/dist/face-match.d.ts +228 -0
  82. package/dist/face-match.esm.js +173 -0
  83. package/dist/faceCaptureManagerFactory-Dh2PdGlF.esm.js +290 -0
  84. package/dist/faceCaptureManagerFactory-yqtpxjnN.d.ts +690 -0
  85. package/dist/faceCaptureSetup-B3faSpYA.esm.js +873 -0
  86. package/dist/faceMatchStateMachine-DNFrxTFS.esm.js +127 -0
  87. package/dist/flow-events.d.ts +6 -0
  88. package/dist/flow-events.esm.js +0 -0
  89. package/dist/flow.d.ts +358 -0
  90. package/dist/flow.esm.js +825 -0
  91. package/dist/flowCompletionService-DhkT4SRY.d.ts +10 -0
  92. package/dist/flowCompletionService-P54yzGvA.esm.js +13 -0
  93. package/dist/flowServices-DG3IdWw6.esm.js +188 -0
  94. package/dist/geolocation.d.ts +127 -0
  95. package/dist/geolocation.esm.js +89 -0
  96. package/dist/geolocationStateMachine-asasuHY2.esm.js +105 -0
  97. package/dist/getBrowser-BSXUTWXw.esm.js +41 -0
  98. package/dist/getDeviceClass-BSntT9_j.esm.js +14 -0
  99. package/dist/government-validation.d.ts +67 -0
  100. package/dist/government-validation.esm.js +81 -0
  101. package/dist/governmentValidationStateMachine-BDDYrJTo.esm.js +271 -0
  102. package/dist/home.d.ts +99 -0
  103. package/dist/home.esm.js +61 -0
  104. package/dist/http.d.ts +68 -0
  105. package/dist/http.esm.js +3 -0
  106. package/dist/id-ocr.d.ts +635 -0
  107. package/dist/id-ocr.esm.js +86 -0
  108. package/dist/id-verification.d.ts +190 -0
  109. package/dist/id-verification.esm.js +43 -0
  110. package/dist/id.d.ts +24 -0
  111. package/dist/id.esm.js +164 -0
  112. package/dist/idCaptureManager-Fyd0eam-.d.ts +958 -0
  113. package/dist/idCaptureManager-ZPkD7Gjk.esm.js +581 -0
  114. package/dist/idCaptureStateMachine-BK0bPHoc.esm.js +2963 -0
  115. package/dist/idOcrStateMachine-YbjjC_Gg.esm.js +388 -0
  116. package/dist/idVerificationStateMachine-xbw9HP1Z.esm.js +71 -0
  117. package/dist/identity-reuse.d.ts +530 -0
  118. package/dist/identity-reuse.esm.js +274 -0
  119. package/dist/index-BcRG8rtJ.d.ts +97 -0
  120. package/dist/index-DZoqeAo9.d.ts +1177 -0
  121. package/dist/index.d.ts +3 -0
  122. package/dist/index.esm.js +12 -0
  123. package/dist/invokeOnCaptureCallback-rc6kBHo5.esm.js +30 -0
  124. package/dist/lib-BB0B_qQX.esm.js +12499 -0
  125. package/dist/mandatory-consent.d.ts +412 -0
  126. package/dist/mandatory-consent.esm.js +78 -0
  127. package/dist/mandatoryConsentStateMachine-Cnco1jvn.esm.js +126 -0
  128. package/dist/openviduLazy-Cm0XFh_v.esm.js +3 -0
  129. package/dist/openviduLazy-Cok70ZSg.esm.js +12 -0
  130. package/dist/permissionServices-D_i6nzEw.esm.js +50 -0
  131. package/dist/phone.d.ts +4 -0
  132. package/dist/phone.esm.js +9 -0
  133. package/dist/phoneManager-B6M30hKE.d.ts +397 -0
  134. package/dist/phoneManager-DAJbGhlY.esm.js +256 -0
  135. package/dist/phoneStateMachine-CuPARRaT.esm.js +351 -0
  136. package/dist/platform-CfrjKhmi.esm.js +83 -0
  137. package/dist/qe-signature-DFo_Cc-I.esm.js +12 -0
  138. package/dist/qe-signature.d.ts +25 -0
  139. package/dist/qe-signature.esm.js +8 -0
  140. package/dist/recordingService-Ig2UgbLv.esm.js +1003 -0
  141. package/dist/redirect-to-mobile.d.ts +107 -0
  142. package/dist/redirect-to-mobile.esm.js +102 -0
  143. package/dist/redirectToMobileStateMachine-BOEqe46A.esm.js +249 -0
  144. package/dist/runChildModule-CqqwqAkW.esm.js +219 -0
  145. package/dist/selfie.d.ts +26 -0
  146. package/dist/selfie.esm.js +146 -0
  147. package/dist/selfieManager-D0lSgd-J.d.ts +68 -0
  148. package/dist/selfieManager-Duisl7qN.esm.js +60 -0
  149. package/dist/selfieStateMachine-D76whWEf.esm.js +68 -0
  150. package/dist/session-CGtQJJzB.esm.js +3206 -0
  151. package/dist/session.d.ts +217 -0
  152. package/dist/session.esm.js +9 -0
  153. package/dist/setup-C5AITV8m.d.ts +254 -0
  154. package/dist/setup-DsM8IG7k.esm.js +887 -0
  155. package/dist/signature.d.ts +94 -0
  156. package/dist/signature.esm.js +66 -0
  157. package/dist/signatureStateMachine-B5-QVUve.esm.js +132 -0
  158. package/dist/stats-CIfiPzb1.esm.js +16 -0
  159. package/dist/stats.d.ts +16 -0
  160. package/dist/stats.esm.js +4 -0
  161. package/dist/trust-graph.d.ts +54 -0
  162. package/dist/trust-graph.esm.js +56 -0
  163. package/dist/types-B06Ypu2F.d.ts +49 -0
  164. package/dist/types-BP1m8VRw.d.ts +340 -0
  165. package/dist/types-CAD4va6a.d.ts +5 -0
  166. package/dist/types-CFV9G_7j.d.ts +24 -0
  167. package/dist/warmup-CEcppFiS.d.ts +63 -0
  168. package/dist/wasm.d.ts +15 -0
  169. package/dist/wasm.esm.js +12 -0
  170. package/dist/watchlist-for-business.d.ts +79 -0
  171. package/dist/watchlist-for-business.esm.js +148 -0
  172. package/dist/watchlist.d.ts +62 -0
  173. package/dist/watchlist.esm.js +86 -0
  174. package/dist/watchlistServices-DMbUhkBX.esm.js +12 -0
  175. package/dist/workflow.d.ts +907 -0
  176. package/dist/workflow.esm.js +702 -0
  177. package/dist/xstate.esm-B70JrNqo.esm.js +3404 -0
  178. package/package.json +1 -1
@@ -0,0 +1,2963 @@
1
+ import { l as WasmPipelineType, r as mlWasmJSApi_default, t as BaseWasmProvider, u as IdCaptureModelType } from "./BaseWasmProvider-C_DLEI40.esm.js";
2
+ import { t as BrowserTimerProvider } from "./BrowserTimerProvider-DhNc_x02.esm.js";
3
+ import { r as getToken, t as api } from "./api-CESGtpbH.esm.js";
4
+ import { S as revokeObjectURL } from "./events-D6-e4vok.esm.js";
5
+ import { t as endpoints } from "./endpoints-CnN3SyDa.esm.js";
6
+ import { t as getDisableIpify } from "./session-CGtQJJzB.esm.js";
7
+ import { a as fromPromise, i as fromCallback, n as sendTo, o as and, r as assign, t as setup } from "./xstate.esm-B70JrNqo.esm.js";
8
+ import { n as IncodeCanvas } from "./deepsightService-O74l4Y__.esm.js";
9
+ import { _ as stopRecording$1, a as StreamCanvasCapture, g as startRecording, h as createRecordingSession, i as flagIdManualReview, n as preloadOpenViduProvider, v as StreamCanvasProcessingSession } from "./recordingService-Ig2UgbLv.esm.js";
10
+ import { n as isDesktop } from "./platform-CfrjKhmi.esm.js";
11
+ import { t as getBackCameraStream } from "./backCameraStream-DMdMeGk2.esm.js";
12
+ import { r as getWindowDimensions } from "./getBrowser-BSXUTWXw.esm.js";
13
+ import { t as addDeviceStats } from "./stats-CIfiPzb1.esm.js";
14
+ import { t as getDeviceClass } from "./getDeviceClass-BSntT9_j.esm.js";
15
+ import { n as requestPermission, t as checkPermission } from "./permissionServices-D_i6nzEw.esm.js";
16
+
17
+ //#region src/modules/id/digitalUpload/digitalUploadErrors.ts
18
+ const TERMINAL_FAIL_REASONS = new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
19
+ function isKnownFailReason(reason) {
20
+ return reason === "DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED" || reason === "ID_TYPE_UNACCEPTABLE" || reason === "FILE_CHANGED_ERROR" || reason === "NETWORK_ERROR" || reason === "GENERIC";
21
+ }
22
+ /**
23
+ * Maps a digital-upload response to the UI's failure reason, or `null` when
24
+ * the upload is a success.
25
+ *
26
+ * Failure detection is layered so we don't lose backend rejections that V2
27
+ * was previously dropping (V1 parity): explicit `failReason` first, then a
28
+ * "this document isn't accepted" signal (`acceptedDocuments` populated or
29
+ * `classification === false`) which maps to `ID_TYPE_UNACCEPTABLE`, then
30
+ * the bare `success === false` fallback as a generic rejection.
31
+ */
32
+ function mapDigitalIdFailReason(response) {
33
+ if (!response) return null;
34
+ const { failReason } = response;
35
+ if (typeof failReason === "string" && failReason.length > 0) return isKnownFailReason(failReason) ? failReason : "GENERIC";
36
+ if (response.acceptedDocuments != null && response.acceptedDocuments.length > 0 || response.classification === false) return "ID_TYPE_UNACCEPTABLE";
37
+ if (response.success === false) return "GENERIC";
38
+ return null;
39
+ }
40
+ function isTerminalDigitalIdFailReason(response) {
41
+ return typeof response?.failReason === "string" && TERMINAL_FAIL_REASONS.has(response.failReason);
42
+ }
43
+ function classifyNetworkError(err) {
44
+ const message = err instanceof Error ? err.message : String(err);
45
+ if (message.includes("ERR_UPLOAD_FILE_CHANGED") || message.includes("file changed") || message.includes("FILE_CHANGED")) return "FILE_CHANGED_ERROR";
46
+ return "NETWORK_ERROR";
47
+ }
48
+
49
+ //#endregion
50
+ //#region src/modules/id/digitalUpload/digitalUploadServices.ts
51
+ const DIGITAL_ID_UPLOAD_PATH = "/omni/add/front-id";
52
+ async function uploadDigitalIdFile(params) {
53
+ const { file, signal, onProgress } = params;
54
+ const response = await api.post(DIGITAL_ID_UPLOAD_PATH, file, {
55
+ query: { idType: "DigitalId" },
56
+ headers: { "Content-Type": file.type || "application/pdf" },
57
+ onUploadProgress: onProgress,
58
+ signal
59
+ });
60
+ if (!response.ok) throw new Error(`POST ${DIGITAL_ID_UPLOAD_PATH} failed: ${response.status}`);
61
+ return {
62
+ ...response.data,
63
+ uploadDurationMs: 0
64
+ };
65
+ }
66
+
67
+ //#endregion
68
+ //#region src/modules/id/digitalUpload/types.ts
69
+ const DIGITAL_UPLOAD_MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
70
+ const DIGITAL_UPLOAD_HOLDING_TIMEOUT_MS = 8e3;
71
+ const DIGITAL_UPLOAD_ALLOWED_MIME_TYPES = ["application/pdf"];
72
+
73
+ //#endregion
74
+ //#region src/modules/id/digitalUpload/digitalUploadStateMachine.ts
75
+ const uploadDigitalIdActor = fromPromise(async ({ input, signal }) => {
76
+ return uploadDigitalIdFile({
77
+ file: input.file,
78
+ signal: input.signal ?? signal,
79
+ onProgress: input.onProgress
80
+ });
81
+ });
82
+ const getUploadResponseFromEvent$1 = (event) => {
83
+ if (!("output" in event)) return;
84
+ return event.output;
85
+ };
86
+ const _digitalUploadMachine = setup({
87
+ types: {
88
+ context: {},
89
+ events: {},
90
+ input: {},
91
+ output: {}
92
+ },
93
+ actors: { uploadDigitalId: uploadDigitalIdActor },
94
+ actions: {
95
+ requestPickerIfPending: assign(({ context }) => {
96
+ if (!context.pendingPickerAutoOpen) return {};
97
+ return {
98
+ pickerRequestId: context.pickerRequestId + 1,
99
+ pendingPickerAutoOpen: false
100
+ };
101
+ }),
102
+ setPendingPickerAutoOpen: assign(() => ({ pendingPickerAutoOpen: true })),
103
+ storeSelectedFile: assign(({ event }) => {
104
+ if (event.type !== "FILE_PICKED") return {};
105
+ return {
106
+ file: event.file,
107
+ failReason: null
108
+ };
109
+ }),
110
+ clearSelectedFile: assign(() => ({
111
+ file: null,
112
+ uploadProgress: 0,
113
+ failReason: null,
114
+ response: void 0,
115
+ uploadDurationMs: void 0
116
+ })),
117
+ setInvalidFileTypeError: assign(() => ({ failReason: "INVALID_FILE_TYPE" })),
118
+ setUploadProgressCapped: assign(({ event }) => {
119
+ if (event.type !== "UPLOAD_PROGRESS") return {};
120
+ return { uploadProgress: Math.min(90, Math.max(0, event.progress)) };
121
+ }),
122
+ setUploadProgressCompleted: assign(() => ({ uploadProgress: 100 })),
123
+ storeUploadResponse: assign(({ event }) => {
124
+ if (!("output" in event)) return {};
125
+ const output = event;
126
+ return {
127
+ response: output.output,
128
+ uploadDurationMs: output.output.uploadDurationMs
129
+ };
130
+ }),
131
+ setFailReasonFromResponse: assign(({ event }) => {
132
+ if (!("output" in event)) return {};
133
+ const response = event.output;
134
+ return { failReason: mapDigitalIdFailReason(response) ?? "GENERIC" };
135
+ }),
136
+ setFailReasonFromNetworkError: assign(({ event }) => {
137
+ if (!("error" in event)) return {};
138
+ return { failReason: classifyNetworkError(event.error) };
139
+ }),
140
+ decrementAttemptOnFailure: assign(({ context }) => ({ attemptsRemaining: Math.max(0, context.attemptsRemaining - 1) }))
141
+ },
142
+ guards: {
143
+ isSelectedFileTooLarge: ({ event }) => event.type === "FILE_PICKED" && event.file.size > DIGITAL_UPLOAD_MAX_FILE_SIZE_BYTES,
144
+ isSelectedFileMimeInvalid: ({ event }) => event.type === "FILE_PICKED" && !DIGITAL_UPLOAD_ALLOWED_MIME_TYPES.includes(event.file.type),
145
+ hasSelectedFile: ({ context }) => context.file !== null,
146
+ responseHasFailReason: ({ event }) => mapDigitalIdFailReason(getUploadResponseFromEvent$1(event)) !== null,
147
+ hasAttemptsRemaining: ({ context }) => context.attemptsRemaining > 0,
148
+ isTerminalFailReason: ({ event }) => {
149
+ return isTerminalDigitalIdFailReason(getUploadResponseFromEvent$1(event));
150
+ },
151
+ isCurrentFailReasonTerminal: ({ context }) => {
152
+ const terminalReasons = new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
153
+ return context.failReason !== null && terminalReasons.has(context.failReason);
154
+ }
155
+ }
156
+ }).createMachine({
157
+ id: "digitalUpload",
158
+ initial: "decideStart",
159
+ context: ({ input }) => ({
160
+ showTutorial: input.showTutorial,
161
+ file: null,
162
+ uploadProgress: 0,
163
+ attemptsRemaining: input.captureAttempts,
164
+ failReason: null,
165
+ response: void 0,
166
+ uploadDurationMs: void 0,
167
+ pickerRequestId: 0,
168
+ pendingPickerAutoOpen: !input.showTutorial,
169
+ resultType: null
170
+ }),
171
+ output: ({ context }) => ({ result: context.resultType ?? "exhausted" }),
172
+ states: {
173
+ decideStart: { always: [{
174
+ guard: ({ context }) => context.showTutorial,
175
+ target: "tutorial"
176
+ }, { target: "selecting" }] },
177
+ tutorial: { on: { NEXT_STEP: {
178
+ target: "selecting",
179
+ actions: ["setPendingPickerAutoOpen"]
180
+ } } },
181
+ selecting: {
182
+ entry: ["requestPickerIfPending"],
183
+ on: { FILE_PICKED: [
184
+ {
185
+ guard: "isSelectedFileTooLarge",
186
+ target: "fileTooLarge",
187
+ actions: ["clearSelectedFile"]
188
+ },
189
+ {
190
+ guard: "isSelectedFileMimeInvalid",
191
+ target: "error",
192
+ actions: ["setInvalidFileTypeError"]
193
+ },
194
+ {
195
+ target: "reviewing",
196
+ actions: ["storeSelectedFile"]
197
+ }
198
+ ] }
199
+ },
200
+ fileTooLarge: { on: { CHOOSE_ANOTHER: {
201
+ target: "selecting",
202
+ actions: ["clearSelectedFile", "setPendingPickerAutoOpen"]
203
+ } } },
204
+ reviewing: { on: {
205
+ CONFIRM: {
206
+ target: "uploading",
207
+ guard: "hasSelectedFile"
208
+ },
209
+ REPLACE: {
210
+ target: "selecting",
211
+ actions: ["setPendingPickerAutoOpen"]
212
+ }
213
+ } },
214
+ uploading: {
215
+ invoke: {
216
+ id: "uploadDigitalId",
217
+ src: "uploadDigitalId",
218
+ input: ({ context, self }) => ({
219
+ file: context.file,
220
+ onProgress: (progress) => {
221
+ self.send({
222
+ type: "UPLOAD_PROGRESS",
223
+ progress
224
+ });
225
+ }
226
+ }),
227
+ onDone: [
228
+ {
229
+ guard: "isTerminalFailReason",
230
+ target: "retriesExhausted",
231
+ actions: ["storeUploadResponse", "setFailReasonFromResponse"]
232
+ },
233
+ {
234
+ guard: "responseHasFailReason",
235
+ target: "checkRetries",
236
+ actions: [
237
+ "storeUploadResponse",
238
+ "setFailReasonFromResponse",
239
+ "decrementAttemptOnFailure"
240
+ ]
241
+ },
242
+ {
243
+ target: "success",
244
+ actions: ["storeUploadResponse", "setUploadProgressCompleted"]
245
+ }
246
+ ],
247
+ onError: {
248
+ target: "checkRetries",
249
+ actions: ["setFailReasonFromNetworkError", "decrementAttemptOnFailure"]
250
+ }
251
+ },
252
+ initial: "analyzing",
253
+ states: {
254
+ analyzing: { after: { [DIGITAL_UPLOAD_HOLDING_TIMEOUT_MS]: { target: "holding" } } },
255
+ holding: {}
256
+ },
257
+ on: { UPLOAD_PROGRESS: { actions: ["setUploadProgressCapped"] } }
258
+ },
259
+ checkRetries: { always: [
260
+ {
261
+ guard: "isCurrentFailReasonTerminal",
262
+ target: "retriesExhausted"
263
+ },
264
+ {
265
+ guard: "hasAttemptsRemaining",
266
+ target: "error"
267
+ },
268
+ { target: "retriesExhausted" }
269
+ ] },
270
+ error: { on: {
271
+ RETRY: {
272
+ target: "selecting",
273
+ actions: ["setPendingPickerAutoOpen", "clearSelectedFile"]
274
+ },
275
+ SCAN_INSTEAD: { target: "closed" }
276
+ } },
277
+ retriesExhausted: {
278
+ entry: assign({ resultType: "exhausted" }),
279
+ on: { SCAN_INSTEAD: { target: "closed" } }
280
+ },
281
+ closed: {
282
+ type: "final",
283
+ entry: assign({ resultType: "closed" })
284
+ },
285
+ success: { on: { NEXT_STEP: { target: "completed" } } },
286
+ completed: {
287
+ type: "final",
288
+ entry: assign({ resultType: "success" })
289
+ }
290
+ }
291
+ });
292
+ const digitalUploadMachine = _digitalUploadMachine;
293
+
294
+ //#endregion
295
+ //#region src/modules/id/digitalUpload/instrumentation.ts
296
+ const TERMINAL_REASONS = new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
297
+ function isHoldingState(value) {
298
+ if (value === "holding") return true;
299
+ if (typeof value !== "object" || value === null) return false;
300
+ const uploadingState = value.uploading;
301
+ if (uploadingState === "holding") return true;
302
+ if (typeof uploadingState === "object" && uploadingState !== null) return Object.prototype.hasOwnProperty.call(uploadingState, "holding");
303
+ return false;
304
+ }
305
+ function mapDigitalIdScreenName(value, failReason) {
306
+ if (value === "tutorial") return "uploadDigitalid.tutorial.default";
307
+ if (value === "selecting" || value === "reviewing") return "uploadDigitalid.review.default";
308
+ if (value === "uploading" || isHoldingState(value)) return "uploadDigitalid.analyzing.default";
309
+ if (value === "success") return "uploadDigitalid.success.default";
310
+ if (value === "fileTooLarge") return "uploadDigitalid.error.filetoolarge";
311
+ if (value === "error") {
312
+ if (failReason !== null && TERMINAL_REASONS.has(failReason)) return "uploadDigitalid.error.notaccepted";
313
+ return "uploadDigitalid.error.default";
314
+ }
315
+ return "uploadDigitalid.review.default";
316
+ }
317
+
318
+ //#endregion
319
+ //#region src/modules/id/idCaptureHelpers.ts
320
+ /**
321
+ * Map of config properties received from the backend to adjusted, internal document types.
322
+ */
323
+ const DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP = [
324
+ ["enableId", "id"],
325
+ ["enablePassport", "passport"],
326
+ ["manualUploadIdCapture", "manualIdUpload"],
327
+ ["digitalIdsUpload", "digitalIdUpload"],
328
+ ["deviceWallet", "digitalId"]
329
+ ];
330
+ /**
331
+ * Returns the list of document types enabled by config for the chooser screen, in display order.
332
+ * Used to populate chooser state so UI and headless consumers can render the correct options.
333
+ *
334
+ * @param config - ID capture configuration (from flow or init)
335
+ * @returns Array of IdDocumentType values that should be shown in the document type chooser
336
+ */
337
+ function getAvailableDocumentTypes(config) {
338
+ const adjustedDocumentTypes = [];
339
+ for (const [configProperty, adjustedType] of DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP) if (config[configProperty]) adjustedDocumentTypes.push(adjustedType);
340
+ return adjustedDocumentTypes;
341
+ }
342
+
343
+ //#endregion
344
+ //#region ../infra/src/providers/wasm/IdCaptureProvider.ts
345
+ var IdCaptureProvider = class extends BaseWasmProvider {
346
+ constructor() {
347
+ super(WasmPipelineType.IdBlurGlarePipeline);
348
+ this.lastProcessResult = null;
349
+ this.capturedCanvas = null;
350
+ this.originalCapturedCanvas = null;
351
+ }
352
+ async initialize(config) {
353
+ await this.initializeBase(config, "idCapture");
354
+ }
355
+ setCallbacks(callbacks) {
356
+ this.ensureInitialized();
357
+ const onCaptureWrapper = () => {
358
+ callbacks.onCapture?.();
359
+ };
360
+ mlWasmJSApi_default.setIdCaptureCallbacks(this.getPipelineType(), callbacks.onFarAway ?? (() => {}), callbacks.onDetectionStarted ?? (() => {}), callbacks.onMaskChange ? (show, mask, top, orientation) => callbacks.onMaskChange?.(show, mask, top, orientation) : () => {}, callbacks.onBlur ?? (() => {}), callbacks.onGlare ?? (() => {}), callbacks.onCapturing ?? (() => {}), callbacks.onCapture ? onCaptureWrapper : () => {}, callbacks.onBestFrame ? (blur, glare, orientation) => callbacks.onBestFrame?.(blur, glare, orientation) : () => {}, callbacks.onIdNotDetected ?? (() => {}), callbacks.onSwitchToManualCapture ?? (() => {}), callbacks.onIdTypeChange ? (idType) => callbacks.onIdTypeChange?.(idType) : () => {}, callbacks.onIdSideChange ? (side) => callbacks.onIdSideChange?.(side) : () => {}, callbacks.onCapturingCounterValueChange ? (value) => callbacks.onCapturingCounterValueChange?.(value) : () => {});
361
+ }
362
+ setThresholds(thresholds) {
363
+ this.ensureInitialized();
364
+ mlWasmJSApi_default.setIdCaptureThresholds(this.getPipelineType(), thresholds.blurThreshold, thresholds.blurChangeThreshold, thresholds.glareThreshold, thresholds.clsThreshold, thresholds.sideThreshold, thresholds.iouThreshold, thresholds.idDetectedTimeout, thresholds.autocaptureTimeout, thresholds.framesAggregationInterval);
365
+ }
366
+ setGeometry(geometry) {
367
+ this.ensureInitialized();
368
+ mlWasmJSApi_default.setIdCaptureGeometryParams(this.getPipelineType(), geometry.areaDown, geometry.areaUp, geometry.areaIOSPassportUp, geometry.areaIOSPassportDown, geometry.widthIOSUp, geometry.widthIOSDown, geometry.widthDown, geometry.widthUp, geometry.windowOuterWidth, geometry.windowOuterHeight, geometry.windowInnerWidth, geometry.windowInnerHeight);
369
+ }
370
+ setSettings(settings) {
371
+ this.ensureInitialized();
372
+ mlWasmJSApi_default.setIdCaptureConfigParams(this.getPipelineType(), settings.isFixedMask, settings.isIPhone14OrHigher, settings.idType, settings.blurCheckEnabled, settings.glareCheckEnabled, settings.faceQualityCheckEnabled, settings.iouCheckEnabled, settings.fpsLimitEnabled);
373
+ }
374
+ setModelType(modelType) {
375
+ this.ensureInitialized();
376
+ let wasmModelType;
377
+ switch (modelType) {
378
+ case "v1":
379
+ wasmModelType = IdCaptureModelType.IdCaptureV1x;
380
+ break;
381
+ case "v2":
382
+ wasmModelType = IdCaptureModelType.IdCaptureV2x;
383
+ break;
384
+ case "v3":
385
+ wasmModelType = IdCaptureModelType.IdCaptureV3x;
386
+ break;
387
+ default: throw new Error(`Unknown model type: ${modelType}`);
388
+ }
389
+ mlWasmJSApi_default.setIdCaptureModelType(this.getPipelineType(), wasmModelType);
390
+ }
391
+ /**
392
+ * Processes a frame through the WASM pipeline and stores the result.
393
+ */
394
+ async processFrame(image) {
395
+ const result = await this.processFrameWasm(image);
396
+ const pipelineType = this.getPipelineType();
397
+ if (result && pipelineType === WasmPipelineType.IdBlurGlarePipeline) this.lastProcessResult = result;
398
+ else this.lastProcessResult = null;
399
+ }
400
+ /**
401
+ * Gets the last process result from the most recent frame processing.
402
+ * @returns The last process result with quad coordinates, or null if not available
403
+ */
404
+ getLastProcessResult() {
405
+ return this.lastProcessResult;
406
+ }
407
+ transformPerspective(canvas, frameRect) {
408
+ this.ensureInitialized();
409
+ const originalWidth = canvas.width();
410
+ const originalHeight = canvas.height();
411
+ try {
412
+ const imageData = canvas.getImageData();
413
+ if (!imageData) return canvas;
414
+ const transformedCanvas = mlWasmJSApi_default.IdPerspectiveTransform(imageData, frameRect);
415
+ if (transformedCanvas) {
416
+ const wrappedCanvas = new IncodeCanvas(transformedCanvas);
417
+ const wrappedWidth = wrappedCanvas.width();
418
+ const wrappedHeight = wrappedCanvas.height();
419
+ if (wrappedWidth === originalWidth && wrappedHeight === originalHeight) {
420
+ const croppedCanvas = this.cropCanvasToRect(wrappedCanvas, {
421
+ x: Math.round(frameRect.x),
422
+ y: Math.round(frameRect.y),
423
+ w: Math.round(frameRect.w),
424
+ h: Math.round(frameRect.h)
425
+ });
426
+ if (croppedCanvas) return croppedCanvas;
427
+ }
428
+ return wrappedCanvas;
429
+ }
430
+ return canvas;
431
+ } catch (_error) {
432
+ return canvas;
433
+ }
434
+ }
435
+ /**
436
+ * Crops a canvas to the specified rectangle region.
437
+ * @param canvas - The canvas to crop
438
+ * @param rect - The rectangle to crop to (x, y, w, h)
439
+ * @returns A new IncodeCanvas with the cropped region, or null if cropping fails
440
+ */
441
+ cropCanvasToRect(canvas, rect) {
442
+ const canvasWidth = canvas.width();
443
+ const canvasHeight = canvas.height();
444
+ if (!canvasWidth || !canvasHeight) return null;
445
+ const x = Math.max(0, Math.min(rect.x, canvasWidth));
446
+ const y = Math.max(0, Math.min(rect.y, canvasHeight));
447
+ const w = Math.max(1, Math.min(rect.w, canvasWidth - x));
448
+ const h = Math.max(1, Math.min(rect.h, canvasHeight - y));
449
+ const croppedCanvasElement = document.createElement("canvas");
450
+ croppedCanvasElement.width = w;
451
+ croppedCanvasElement.height = h;
452
+ const ctx = croppedCanvasElement.getContext("2d");
453
+ if (!ctx) return null;
454
+ ctx.drawImage(canvas.canvas, x, y, w, h, 0, 0, w, h);
455
+ return new IncodeCanvas(croppedCanvasElement);
456
+ }
457
+ /**
458
+ * Gets the captured canvas (transformed for preview).
459
+ * @returns The captured canvas, or null if not available
460
+ */
461
+ getCapturedCanvas() {
462
+ return this.capturedCanvas;
463
+ }
464
+ /**
465
+ * Gets the original captured canvas (full frame for upload).
466
+ * @returns The original captured canvas, or null if not available
467
+ */
468
+ getOriginalCapturedCanvas() {
469
+ return this.originalCapturedCanvas;
470
+ }
471
+ /**
472
+ * Sets the captured canvases (original and transformed).
473
+ * @param original - The original full-frame canvas (for upload)
474
+ * @param transformed - The transformed canvas (for preview)
475
+ */
476
+ setCapturedCanvases(original, transformed) {
477
+ this.originalCapturedCanvas = original;
478
+ this.capturedCanvas = transformed;
479
+ }
480
+ reset() {
481
+ super.reset();
482
+ this.lastProcessResult = null;
483
+ this.capturedCanvas = null;
484
+ this.originalCapturedCanvas = null;
485
+ }
486
+ };
487
+
488
+ //#endregion
489
+ //#region src/internal/analytics/deviceStats.ts
490
+ async function postDeviceStats(stats) {
491
+ try {
492
+ await api.post(endpoints.deviceStats, stats);
493
+ } catch {}
494
+ }
495
+
496
+ //#endregion
497
+ //#region src/modules/id/idCameraStream.ts
498
+ async function getIdCameraStream(deviceId) {
499
+ return getBackCameraStream(deviceId);
500
+ }
501
+
502
+ //#endregion
503
+ //#region src/modules/id/manualUpload/types.ts
504
+ const MANUAL_UPLOAD_MAX_RETRIES = 3;
505
+ const MANUAL_UPLOAD_MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
506
+ const MANUAL_UPLOAD_EXHAUSTION_FORWARD_MS = 5e3;
507
+
508
+ //#endregion
509
+ //#region src/modules/id/types.ts
510
+ const ID_ERROR_CODES = {
511
+ UPLOAD_ERROR: "UPLOAD_ERROR",
512
+ CLASSIFICATION_FAILED: "CLASSIFICATION_FAILED",
513
+ LOW_SHARPNESS: "LOW_SHARPNESS",
514
+ GLARE_DETECTED: "GLARE_DETECTED",
515
+ WRONG_DOCUMENT_SIDE: "WRONG_DOCUMENT_SIDE",
516
+ ID_TYPE_UNACCEPTABLE: "ID_TYPE_UNACCEPTABLE",
517
+ READABILITY_ISSUE: "READABILITY_ISSUE",
518
+ RETRY_EXHAUSTED_CONTINUE_TO_BACK: "RETRY_EXHAUSTED_CONTINUE_TO_BACK",
519
+ RETRY_EXHAUSTED_SKIP_BACK: "RETRY_EXHAUSTED_SKIP_BACK",
520
+ NO_MORE_TRIES: "NO_MORE_TRIES",
521
+ UNEXPECTED_ERROR: "UNEXPECTED_ERROR",
522
+ NO_TOKEN: "NO_TOKEN",
523
+ PERMISSION_DENIED: "PERMISSION_DENIED",
524
+ USER_CANCELLED: "USER_CANCELLED",
525
+ SERVER: "SERVER_ERROR"
526
+ };
527
+
528
+ //#endregion
529
+ //#region src/modules/id/idCaptureServices.ts
530
+ /**
531
+ * Camera constraints used for PRC warmup before ID capture.
532
+ * Uses environment-facing camera on mobile devices (for back camera ID capture)
533
+ * and user-facing camera on desktop.
534
+ */
535
+ function getPrcCameraConstraints() {
536
+ if (isDesktop()) return { video: {
537
+ facingMode: "user",
538
+ height: { ideal: 480 },
539
+ width: { ideal: 640 }
540
+ } };
541
+ return { video: {
542
+ facingMode: "environment",
543
+ height: { ideal: 720 }
544
+ } };
545
+ }
546
+ function getUploadEndpoint(type, isSecondId) {
547
+ if (isSecondId) return type === "front" ? endpoints.frontSecondId : endpoints.backSecondId;
548
+ return type === "front" ? endpoints.frontId : endpoints.backId;
549
+ }
550
+ const SHARPNESS_THRESHOLD = 10;
551
+ const GLARE_THRESHOLD = 10;
552
+ const DEFAULT_ID_CAPTURE_THRESHOLDS$1 = {
553
+ blurThreshold: .2,
554
+ blurChangeThreshold: .2,
555
+ glareThreshold: .3,
556
+ clsThreshold: .98,
557
+ sideThreshold: .8,
558
+ iouThreshold: .8,
559
+ framesAggregationInterval: 3e3
560
+ };
561
+ const DEFAULT_ID_CAPTURE_SETTINGS = {
562
+ isFixedMask: false,
563
+ isIPhone14OrHigher: false,
564
+ idType: "",
565
+ blurCheckEnabled: false,
566
+ glareCheckEnabled: false,
567
+ faceQualityCheckEnabled: true,
568
+ iouCheckEnabled: true,
569
+ fpsLimitEnabled: false
570
+ };
571
+ async function initializeIdCapture(params) {
572
+ const { config, deepsightService } = params;
573
+ const provider = new IdCaptureProvider();
574
+ await provider.initialize({});
575
+ provider.setThresholds({
576
+ ...DEFAULT_ID_CAPTURE_THRESHOLDS$1,
577
+ ...config.thresholds,
578
+ idDetectedTimeout: config.thresholds?.idDetectedTimeout ?? config.deviceIdleTimeout * 1e3,
579
+ autocaptureTimeout: config.thresholds?.autocaptureTimeout ?? config.autoCaptureTimeout * 1e3
580
+ });
581
+ if (config.settings) provider.setSettings({
582
+ ...DEFAULT_ID_CAPTURE_SETTINGS,
583
+ ...config.settings
584
+ });
585
+ if (deepsightService) try {
586
+ await deepsightService.performPrcCheck({ constraints: getPrcCameraConstraints() });
587
+ } catch {}
588
+ const { stream, fallbackLevel } = await getIdCameraStream();
589
+ const videoTrack = stream.getVideoTracks()[0];
590
+ let captureResolution;
591
+ if (videoTrack) {
592
+ const settings = videoTrack.getSettings();
593
+ if (typeof settings.width === "number" && typeof settings.height === "number") captureResolution = `${settings.width}x${settings.height}`;
594
+ }
595
+ if (deepsightService && videoTrack) deepsightService.metadata.updateCameraInfo(videoTrack);
596
+ return {
597
+ stream,
598
+ provider,
599
+ captureResolution,
600
+ cameraFallbackLevel: fallbackLevel
601
+ };
602
+ }
603
+ function stopStream(stream) {
604
+ for (const track of stream.getTracks()) track.stop();
605
+ }
606
+ function validateUploadResponse(response, sessionState) {
607
+ if (response.failReason === "ID_TYPE_UNACCEPTABLE") return {
608
+ error: true,
609
+ message: "ID type is not acceptable",
610
+ messageDescription: "Please use a valid ID type",
611
+ errorKey: ID_ERROR_CODES.ID_TYPE_UNACCEPTABLE
612
+ };
613
+ if (response.failReason === "WRONG_DOCUMENT_SIDE") return {
614
+ error: true,
615
+ message: "Wrong side of document",
616
+ messageDescription: response.side === "back" ? "Please show the back side of your ID" : "Please show the front side of your ID",
617
+ errorKey: ID_ERROR_CODES.WRONG_DOCUMENT_SIDE
618
+ };
619
+ if (!response.classification) return {
620
+ error: true,
621
+ message: "ID classification failed",
622
+ errorKey: ID_ERROR_CODES.CLASSIFICATION_FAILED
623
+ };
624
+ const sharpnessThreshold = getDeviceClass() === "desktop" ? -1 : SHARPNESS_THRESHOLD;
625
+ if (response.sharpness !== void 0 && sharpnessThreshold >= 0 && response.sharpness < sharpnessThreshold) return {
626
+ error: true,
627
+ message: "Image is not sharp enough",
628
+ messageDescription: "Please ensure the image is clear and well-focused",
629
+ errorKey: ID_ERROR_CODES.LOW_SHARPNESS
630
+ };
631
+ if (response.glare !== void 0 && response.glare < GLARE_THRESHOLD && !sessionState?.skipGlareFront && !sessionState?.skipGlareBack) return {
632
+ error: true,
633
+ message: "Glare detected on ID",
634
+ messageDescription: "Please avoid bright reflections on your ID",
635
+ errorKey: ID_ERROR_CODES.GLARE_DETECTED
636
+ };
637
+ }
638
+ async function getExtraImages(params) {
639
+ const extraImages = params.ageAssurance ? [params.type === "back" ? "croppedBackID" : "croppedFrontID"] : [];
640
+ try {
641
+ const res = await api.post(endpoints.getImages, { images: ["croppedIDFace", ...extraImages] }, { signal: params.signal });
642
+ if (!res.ok) throw new Error(`Failed to get extra images: ${res.status}`);
643
+ return res.data ?? {
644
+ croppedIDFace: "",
645
+ croppedFrontID: "",
646
+ croppedBackID: ""
647
+ };
648
+ } catch {
649
+ return {
650
+ croppedIDFace: "",
651
+ croppedFrontID: "",
652
+ croppedBackID: ""
653
+ };
654
+ }
655
+ }
656
+ const getRealQualityValue = (value) => (1 - value) * 100;
657
+ async function uploadIdImage(params) {
658
+ const { type, image, onProgress, signal, metadata, ageAssurance, glare, sharpness, shouldSkipGlareBack, analyticsProvider, imageData, isSecondId, onlyFront } = params;
659
+ let finalMetadata = metadata;
660
+ if (analyticsProvider && imageData) try {
661
+ await analyticsProvider.analyzeFrame(imageData);
662
+ analyticsProvider.update();
663
+ const analysisStatus = analyticsProvider.getAnalysisStatus();
664
+ const motionStatus = analyticsProvider.getMotionStatus();
665
+ await postDeviceStats({
666
+ frontIdStatsAnalysisStatus: type === "front" ? analysisStatus : void 0,
667
+ backIdStatsAnalysisStatus: type === "back" ? analysisStatus : void 0,
668
+ motionStatus
669
+ });
670
+ finalMetadata = analyticsProvider.getMetadata();
671
+ } catch (error) {
672
+ console.warn("[IdCapture] Analytics failed:", error);
673
+ }
674
+ const endpoint = getUploadEndpoint(type, isSecondId);
675
+ const body = {
676
+ base64Image: image,
677
+ metadata: finalMetadata
678
+ };
679
+ const queryParams = { imageType: "id" };
680
+ if (onlyFront && type === "front") queryParams.onlyFront = true;
681
+ if (shouldSkipGlareBack && type === "back") queryParams.glare = 0;
682
+ else if (glare !== void 0) queryParams.glare = getRealQualityValue(glare);
683
+ if (sharpness !== void 0) queryParams.sharpness = getRealQualityValue(sharpness);
684
+ try {
685
+ const res = await api.post(endpoint, body, {
686
+ signal,
687
+ query: queryParams,
688
+ onUploadProgress: onProgress
689
+ });
690
+ if (!res.ok) throw new Error(`POST ${endpoint} failed: ${res.status} ${res.statusText}`);
691
+ const response = res.data;
692
+ const extraImages = await getExtraImages({
693
+ type,
694
+ ageAssurance,
695
+ signal
696
+ });
697
+ const fullResponse = {
698
+ ...response,
699
+ originalImage: image,
700
+ frontIdImage: type === "front" ? image : void 0,
701
+ backIdImage: extraImages.croppedBackID,
702
+ ...extraImages
703
+ };
704
+ onProgress?.(100);
705
+ return fullResponse;
706
+ } catch (error) {
707
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
708
+ throw new Error(`${ID_ERROR_CODES.UPLOAD_ERROR}: ${errorMessage}`);
709
+ }
710
+ }
711
+ function buildStandardResolution(width, height) {
712
+ return height > width ? {
713
+ width: 1080,
714
+ height: 1920
715
+ } : {
716
+ width: 1920,
717
+ height: 1080
718
+ };
719
+ }
720
+ function buildResolutionFromStream(stream) {
721
+ const track = stream.getVideoTracks()[0];
722
+ if (!track) return "1080x1920";
723
+ const settings = track.getSettings();
724
+ const width = settings.width;
725
+ const height = settings.height;
726
+ if (typeof width === "number" && typeof height === "number") {
727
+ const standard = buildStandardResolution(width, height);
728
+ return `${standard.width}x${standard.height}`;
729
+ }
730
+ return "1080x1920";
731
+ }
732
+ function preloadIdRecordingProvider(config) {
733
+ if (config.enableIdRecording !== true) return;
734
+ preloadOpenViduProvider();
735
+ }
736
+ async function createOpenViduRecordingProvider() {
737
+ const { OpenViduRecordingProvider } = await import("./OpenViduRecordingProvider-CMu6XVdc.esm.js");
738
+ return new OpenViduRecordingProvider();
739
+ }
740
+ async function startRecordingSession(params) {
741
+ if (params.config.enableIdRecording !== true) return;
742
+ if (params.existing) return params.existing;
743
+ const provider = params.config.recording?.capability ?? await createOpenViduRecordingProvider();
744
+ const clonedStream = params.stream.clone();
745
+ const hasAudio = clonedStream.getAudioTracks().length > 0;
746
+ const resolution = buildResolutionFromStream(clonedStream);
747
+ const session = await createRecordingSession(params.type);
748
+ const connection = await provider.connect({
749
+ sessionToken: session.token,
750
+ stream: clonedStream,
751
+ events: {}
752
+ });
753
+ await startRecording({
754
+ videoRecordingId: session.videoRecordingId,
755
+ type: params.type,
756
+ resolution,
757
+ hasAudio
758
+ });
759
+ return {
760
+ token: session.token,
761
+ sessionId: session.sessionId,
762
+ videoRecordingId: session.videoRecordingId,
763
+ connection,
764
+ resolution,
765
+ hasAudio
766
+ };
767
+ }
768
+ function stopRecording(session) {
769
+ (async () => {
770
+ try {
771
+ await stopRecording$1(session.videoRecordingId);
772
+ } finally {
773
+ await session.connection.disconnect();
774
+ }
775
+ })();
776
+ }
777
+ async function processId(isSecondId = false, queueName = "", signal) {
778
+ const endpoint = isSecondId ? endpoints.processSecondId : endpoints.processId;
779
+ const url = queueName ? `${endpoint}?queueName=${queueName}` : endpoint;
780
+ return { isDocumentExpired: (await api.post(url, {}, { signal })).data?.isDocumentExpired ?? false };
781
+ }
782
+ /**
783
+ * Upload a user-selected image as front / back / passport ID.
784
+ *
785
+ * Uses the same request shape as the live-camera path (`uploadIdImage`):
786
+ * JSON body `{ base64Image }` with default application/json Content-Type,
787
+ * `captureType=UPLOAD` query param, `retry=true` when retrying.
788
+ * Back is POSTed to `/omni/add/back-id/v2` (or `/omni/add/back-second-id/v2`
789
+ * when `isSecondId`); front and passport go to `/omni/add/front-id/v2` (or
790
+ * `/omni/add/front-second-id/v2` when `isSecondId`).
791
+ *
792
+ * The v2 endpoints reject raw `image/jpeg` bodies with 415, so the caller
793
+ * must convert the File to base64 before calling this service.
794
+ */
795
+ async function uploadManualIdFile(params) {
796
+ const { side, base64Image, retry, onlyFront, signal, isSecondId } = params;
797
+ const endpoint = getUploadEndpoint(side === "back" ? "back" : "front", isSecondId);
798
+ const queryParams = { captureType: "UPLOAD" };
799
+ if (retry) queryParams.retry = true;
800
+ if (onlyFront && side === "front") queryParams.onlyFront = true;
801
+ const res = await api.post(endpoint, { base64Image }, {
802
+ signal,
803
+ query: queryParams
804
+ });
805
+ if (!res.ok) throw new Error(`POST ${endpoint} failed: ${res.status} ${res.statusText}`);
806
+ return res.data;
807
+ }
808
+
809
+ //#endregion
810
+ //#region src/modules/id/manualUpload/manualUploadErrors.ts
811
+ /**
812
+ * i18n keys for manual-upload user-facing error copy.
813
+ * Keep in sync with `packages/ui/src/i18n/**.json` under the `manualIdUpload.*` namespace.
814
+ */
815
+ const MANUAL_UPLOAD_ERROR_KEYS = {
816
+ wrongSide: "manualIdUpload.wrongSide",
817
+ wrongDocument: "manualIdUpload.wrongDocument",
818
+ fileTooBig: "manualIdUpload.fileTooBig",
819
+ generic: "manualIdUpload.generic",
820
+ lowSharpness: "manualIdUpload.lowSharpness",
821
+ glareDetected: "manualIdUpload.glareDetected",
822
+ readabilityIssue: "manualIdUpload.readabilityIssue",
823
+ qualityRejected: "manualIdUpload.qualityRejected"
824
+ };
825
+ /**
826
+ * Map the server's `failReason` (plus client-side passport/ID tab mismatch and
827
+ * per-image quality flags) onto an i18n key. Mirrors v1's `shouldUploadAgain`
828
+ * branch logic in
829
+ * `ms-incodesmile-web/packages/incode-welcome/src/manualIdUpload/manuaIdUpload.tsx`,
830
+ * extended to also reject responses where the backend flagged a per-image
831
+ * quality issue (`correctSharpness`, `correctGlare`, `readability`, or
832
+ * `idQualityAttemptApproved` set to `false`).
833
+ *
834
+ * Quality flags are checked with `=== false` so missing/undefined values
835
+ * (older backends, partial payloads) keep the legacy "trust the server"
836
+ * behaviour and do not produce false positives.
837
+ *
838
+ * Returns `null` when the response represents a successful upload — the caller
839
+ * should treat `null` as "no error, advance to next slot".
840
+ */
841
+ function mapFailReasonToErrorKey(response, expectedTab) {
842
+ const failReason = response.failReason;
843
+ if (failReason === "WRONG_DOCUMENT_SIDE") return MANUAL_UPLOAD_ERROR_KEYS.wrongSide;
844
+ if (failReason === "WRONG_ONE_SIDED_DOCUMENT" || failReason === "UNKNOWN_DOCUMENT_TYPE") return MANUAL_UPLOAD_ERROR_KEYS.wrongDocument;
845
+ if (failReason === "ID_TYPE_UNACCEPTABLE") return MANUAL_UPLOAD_ERROR_KEYS.wrongDocument;
846
+ if (expectedTab === "passport" && response.typeOfId && response.typeOfId.toLowerCase() !== "passport") return MANUAL_UPLOAD_ERROR_KEYS.wrongDocument;
847
+ if (expectedTab === "id" && response.typeOfId?.toLowerCase() === "passport") return MANUAL_UPLOAD_ERROR_KEYS.wrongDocument;
848
+ if (response.correctSharpness === false) return MANUAL_UPLOAD_ERROR_KEYS.lowSharpness;
849
+ if (response.correctGlare === false) return MANUAL_UPLOAD_ERROR_KEYS.glareDetected;
850
+ if (response.readability === false) return MANUAL_UPLOAD_ERROR_KEYS.readabilityIssue;
851
+ if (response.idQualityAttemptApproved === false) return MANUAL_UPLOAD_ERROR_KEYS.qualityRejected;
852
+ return null;
853
+ }
854
+
855
+ //#endregion
856
+ //#region src/modules/id/manualUpload/manualUploadServices.ts
857
+ /**
858
+ * Read a File's bytes and return the raw base64 payload (the portion after
859
+ * `data:<mime>;base64,`). The backend's `/omni/add/*-id/v2` endpoints reject
860
+ * full data-URLs with `IllegalArgumentException: Illegal base64 character 3a`,
861
+ * so the prefix must be stripped before posting. Mirrors the live-camera
862
+ * path in `packages/infra/src/media/canvas.ts:getBase64Image()`.
863
+ */
864
+ function fileToBase64Payload(file) {
865
+ return new Promise((resolve, reject) => {
866
+ const reader = new FileReader();
867
+ reader.onload = () => {
868
+ const result = reader.result;
869
+ if (typeof result !== "string") {
870
+ reject(/* @__PURE__ */ new Error("FileReader produced non-string result"));
871
+ return;
872
+ }
873
+ const commaIndex = result.indexOf(",");
874
+ resolve(commaIndex === -1 ? result : result.slice(commaIndex + 1));
875
+ };
876
+ reader.onerror = () => {
877
+ reject(reader.error ?? /* @__PURE__ */ new Error("FileReader failed"));
878
+ };
879
+ reader.readAsDataURL(file);
880
+ });
881
+ }
882
+
883
+ //#endregion
884
+ //#region src/modules/id/manualUpload/manualUploadStateMachine.ts
885
+ const uploadManualFileActor = fromPromise(async ({ input, signal }) => {
886
+ const base64Image = await fileToBase64Payload(input.file);
887
+ return uploadManualIdFile({
888
+ side: input.side,
889
+ base64Image,
890
+ retry: input.retry,
891
+ onlyFront: input.onlyFront,
892
+ isSecondId: input.isSecondId,
893
+ signal
894
+ });
895
+ });
896
+ const getUploadResponseFromEvent = (event) => {
897
+ if ("output" in event) return event.output;
898
+ };
899
+ const _manualUploadMachine = setup({
900
+ types: {
901
+ context: {},
902
+ events: {},
903
+ input: {},
904
+ output: {}
905
+ },
906
+ actors: { uploadManualFile: uploadManualFileActor },
907
+ actions: {
908
+ setManualUploadActiveTab: assign(({ context, event }) => {
909
+ if (event.type !== "MANUAL_UPLOAD_TAB_CHANGED") return {};
910
+ return {
911
+ activeTab: event.tab,
912
+ frontFile: null,
913
+ backFile: null,
914
+ passportFile: null,
915
+ frontUploaded: false,
916
+ backUploaded: false,
917
+ passportUploaded: false,
918
+ skipBackFromServer: false,
919
+ errorMessage: null,
920
+ retriesLeft: context.captureAttempts
921
+ };
922
+ }),
923
+ resetManualUpload: assign(({ context }) => ({
924
+ frontFile: null,
925
+ backFile: null,
926
+ passportFile: null,
927
+ frontUploaded: false,
928
+ backUploaded: false,
929
+ passportUploaded: false,
930
+ skipBackFromServer: false,
931
+ errorMessage: null,
932
+ retriesLeft: context.captureAttempts
933
+ })),
934
+ storeSelectedFile: assign(({ event }) => {
935
+ if (event.type !== "MANUAL_UPLOAD_FILE_SELECTED") return {};
936
+ const updated = { errorMessage: null };
937
+ if (event.side === "front") updated.frontFile = event.file;
938
+ else if (event.side === "back") updated.backFile = event.file;
939
+ else updated.passportFile = event.file;
940
+ return updated;
941
+ }),
942
+ markFrontUploaded: assign(() => ({
943
+ frontUploaded: true,
944
+ errorMessage: null
945
+ })),
946
+ markBackUploaded: assign(() => ({
947
+ backUploaded: true,
948
+ errorMessage: null
949
+ })),
950
+ markPassportUploaded: assign(() => ({
951
+ passportUploaded: true,
952
+ errorMessage: null
953
+ })),
954
+ recordSkipBackFromResponse: assign(({ event }) => {
955
+ if (!("output" in event)) return {};
956
+ if (!event.output.skipBackIdCapture) return {};
957
+ return { skipBackFromServer: true };
958
+ }),
959
+ decrementManualUploadRetries: assign(({ context }) => ({ retriesLeft: Math.max(0, context.retriesLeft - 1) })),
960
+ setManualUploadErrorFromResponse: assign(({ context, event }) => {
961
+ if (!("output" in event)) return {};
962
+ const response = event.output;
963
+ return { errorMessage: mapFailReasonToErrorKey(response, context.activeTab) ?? "manualIdUpload.generic" };
964
+ }),
965
+ setManualUploadGenericError: assign(() => ({ errorMessage: "manualIdUpload.generic" })),
966
+ setManualUploadFileTooLargeError: assign(() => ({ errorMessage: "manualIdUpload.fileTooBig" })),
967
+ clearManualUploadError: assign(() => ({ errorMessage: null }))
968
+ },
969
+ guards: {
970
+ isSelectedFileTooLarge: ({ event }) => {
971
+ if (event.type !== "MANUAL_UPLOAD_FILE_SELECTED") return false;
972
+ return event.file.size > MANUAL_UPLOAD_MAX_FILE_SIZE_BYTES;
973
+ },
974
+ isFrontFileSelection: ({ event }) => event.type === "MANUAL_UPLOAD_FILE_SELECTED" && event.side === "front",
975
+ isBackFileSelection: ({ event }) => event.type === "MANUAL_UPLOAD_FILE_SELECTED" && event.side === "back",
976
+ isPassportFileSelection: ({ event }) => event.type === "MANUAL_UPLOAD_FILE_SELECTED" && event.side === "passport",
977
+ manualUploadRetriesExhausted: ({ context }) => context.retriesLeft <= 0,
978
+ canContinueFromIdTab: ({ context }) => {
979
+ if (context.activeTab !== "id") return false;
980
+ if (!context.frontUploaded) return false;
981
+ if (context.onlyFront) return true;
982
+ if (context.skipBackFromServer) return true;
983
+ return context.backUploaded;
984
+ },
985
+ canContinueFromPassportTab: ({ context }) => context.activeTab === "passport" && context.passportUploaded,
986
+ manualUploadResponseHasError: ({ context, event }) => {
987
+ const response = getUploadResponseFromEvent(event);
988
+ if (!response) return false;
989
+ return mapFailReasonToErrorKey(response, context.activeTab) !== null;
990
+ }
991
+ }
992
+ }).createMachine({
993
+ id: "manualUpload",
994
+ initial: "selecting",
995
+ context: ({ input }) => ({
996
+ onlyFront: input.onlyFront,
997
+ isSecondId: input.isSecondId,
998
+ captureAttempts: input.captureAttempts,
999
+ frontFile: null,
1000
+ backFile: null,
1001
+ passportFile: null,
1002
+ activeTab: "id",
1003
+ retriesLeft: input.captureAttempts,
1004
+ errorMessage: null,
1005
+ skipBackFromServer: false,
1006
+ frontUploaded: false,
1007
+ backUploaded: false,
1008
+ passportUploaded: false
1009
+ }),
1010
+ on: {
1011
+ MANUAL_UPLOAD_TAB_CHANGED: {
1012
+ target: ".selecting",
1013
+ actions: ["setManualUploadActiveTab"]
1014
+ },
1015
+ MANUAL_UPLOAD_RESET: {
1016
+ target: ".selecting",
1017
+ actions: ["resetManualUpload"]
1018
+ }
1019
+ },
1020
+ states: {
1021
+ selecting: { on: {
1022
+ MANUAL_UPLOAD_FILE_SELECTED: [
1023
+ {
1024
+ guard: "isSelectedFileTooLarge",
1025
+ actions: ["setManualUploadFileTooLargeError"]
1026
+ },
1027
+ {
1028
+ guard: "isFrontFileSelection",
1029
+ target: "uploadingFront",
1030
+ actions: ["storeSelectedFile"]
1031
+ },
1032
+ {
1033
+ guard: "isBackFileSelection",
1034
+ target: "uploadingBack",
1035
+ actions: ["storeSelectedFile"]
1036
+ },
1037
+ {
1038
+ guard: "isPassportFileSelection",
1039
+ target: "uploadingPassport",
1040
+ actions: ["storeSelectedFile"]
1041
+ }
1042
+ ],
1043
+ MANUAL_UPLOAD_CONTINUE: [{
1044
+ guard: "canContinueFromIdTab",
1045
+ target: "finished"
1046
+ }, {
1047
+ guard: "canContinueFromPassportTab",
1048
+ target: "finished"
1049
+ }]
1050
+ } },
1051
+ uploadingFront: { invoke: {
1052
+ id: "uploadManualFile",
1053
+ src: "uploadManualFile",
1054
+ input: ({ context }) => ({
1055
+ side: "front",
1056
+ file: context.frontFile,
1057
+ retry: context.retriesLeft < context.captureAttempts,
1058
+ onlyFront: context.onlyFront,
1059
+ isSecondId: context.isSecondId
1060
+ }),
1061
+ onDone: [{
1062
+ guard: "manualUploadResponseHasError",
1063
+ target: "checkRetries",
1064
+ actions: ["decrementManualUploadRetries", "setManualUploadErrorFromResponse"]
1065
+ }, {
1066
+ target: "selecting",
1067
+ actions: [
1068
+ "markFrontUploaded",
1069
+ "recordSkipBackFromResponse",
1070
+ "clearManualUploadError"
1071
+ ]
1072
+ }],
1073
+ onError: {
1074
+ target: "checkRetries",
1075
+ actions: ["decrementManualUploadRetries", "setManualUploadGenericError"]
1076
+ }
1077
+ } },
1078
+ uploadingBack: { invoke: {
1079
+ id: "uploadManualFile",
1080
+ src: "uploadManualFile",
1081
+ input: ({ context }) => ({
1082
+ side: "back",
1083
+ file: context.backFile,
1084
+ retry: context.retriesLeft < context.captureAttempts,
1085
+ onlyFront: false,
1086
+ isSecondId: context.isSecondId
1087
+ }),
1088
+ onDone: [{
1089
+ guard: "manualUploadResponseHasError",
1090
+ target: "checkRetries",
1091
+ actions: ["decrementManualUploadRetries", "setManualUploadErrorFromResponse"]
1092
+ }, {
1093
+ target: "selecting",
1094
+ actions: ["markBackUploaded", "clearManualUploadError"]
1095
+ }],
1096
+ onError: {
1097
+ target: "checkRetries",
1098
+ actions: ["decrementManualUploadRetries", "setManualUploadGenericError"]
1099
+ }
1100
+ } },
1101
+ uploadingPassport: { invoke: {
1102
+ id: "uploadManualFile",
1103
+ src: "uploadManualFile",
1104
+ input: ({ context }) => ({
1105
+ side: "passport",
1106
+ file: context.passportFile,
1107
+ retry: context.retriesLeft < context.captureAttempts,
1108
+ onlyFront: false,
1109
+ isSecondId: context.isSecondId
1110
+ }),
1111
+ onDone: [{
1112
+ guard: "manualUploadResponseHasError",
1113
+ target: "checkRetries",
1114
+ actions: ["decrementManualUploadRetries", "setManualUploadErrorFromResponse"]
1115
+ }, {
1116
+ target: "selecting",
1117
+ actions: ["markPassportUploaded", "clearManualUploadError"]
1118
+ }],
1119
+ onError: {
1120
+ target: "checkRetries",
1121
+ actions: ["decrementManualUploadRetries", "setManualUploadGenericError"]
1122
+ }
1123
+ } },
1124
+ checkRetries: { always: [{
1125
+ guard: "manualUploadRetriesExhausted",
1126
+ target: "retriesExhausted"
1127
+ }, { target: "selecting" }] },
1128
+ retriesExhausted: { after: { [MANUAL_UPLOAD_EXHAUSTION_FORWARD_MS]: { target: "exhausted" } } },
1129
+ exhausted: {
1130
+ type: "final",
1131
+ output: { result: "exhausted" }
1132
+ },
1133
+ finished: {
1134
+ type: "final",
1135
+ output: { result: "success" }
1136
+ }
1137
+ }
1138
+ });
1139
+ const manualUploadMachine = _manualUploadMachine;
1140
+
1141
+ //#endregion
1142
+ //#region ../infra/src/wasm/idCaptureDefaults.ts
1143
+ /**
1144
+ * Default WASM thresholds for ID capture quality checks.
1145
+ * Based on legacy pipelinesConfig.ts values.
1146
+ */
1147
+ const DEFAULT_ID_CAPTURE_THRESHOLDS = {
1148
+ blurThreshold: .2,
1149
+ blurChangeThreshold: .2,
1150
+ glareThreshold: .3,
1151
+ clsThreshold: .98,
1152
+ sideThreshold: .8,
1153
+ iouThreshold: .8,
1154
+ idDetectedTimeout: 1e4,
1155
+ autocaptureTimeout: 5e3,
1156
+ framesAggregationInterval: 3e3
1157
+ };
1158
+ /**
1159
+ * Default model version for ID capture.
1160
+ */
1161
+ const DEFAULT_ID_CAPTURE_MODEL_VERSION = "v2";
1162
+
1163
+ //#endregion
1164
+ //#region src/modules/id/idCaptureActors.ts
1165
+ const checkPermissionActor = fromPromise(async () => {
1166
+ return checkPermission();
1167
+ });
1168
+ const requestPermissionActor = fromPromise(async ({ input }) => {
1169
+ return requestPermission({ requestMotion: input.requestMotionPermission });
1170
+ });
1171
+ const initializeCameraActor = fromPromise(async ({ input }) => {
1172
+ return initializeIdCapture(input);
1173
+ });
1174
+ const runDetectionActor = fromCallback(({ input, sendBack }) => {
1175
+ if (!input.frameCapturer || !input.provider) {
1176
+ sendBack({
1177
+ type: "DETECTION_UPDATE",
1178
+ status: "error"
1179
+ });
1180
+ return () => {};
1181
+ }
1182
+ const provider = input.provider;
1183
+ let currentCanvas = null;
1184
+ let bestCanvas = null;
1185
+ let storedQualityElements = {};
1186
+ let isCapturing = false;
1187
+ const timer = BrowserTimerProvider.getInstance();
1188
+ let notificationTimeout = null;
1189
+ let currentNotificationStatus = null;
1190
+ let lastReportedSide = null;
1191
+ const NOTIFICATION_DURATION_MS = 500;
1192
+ const isReportedSideWrong = () => {
1193
+ if (!lastReportedSide) return false;
1194
+ const detectedSide = lastReportedSide.toLowerCase();
1195
+ if (detectedSide === "wrong") return true;
1196
+ const isBackDetected = detectedSide.includes("back") && !detectedSide.includes("front");
1197
+ const isFrontDetected = detectedSide.includes("front") && !detectedSide.includes("back");
1198
+ return input.currentMode === "front" && isBackDetected || input.currentMode === "back" && isFrontDetected;
1199
+ };
1200
+ const clearNotificationTimeout = () => {
1201
+ if (notificationTimeout) {
1202
+ timer.clearTimeout(notificationTimeout);
1203
+ notificationTimeout = null;
1204
+ currentNotificationStatus = null;
1205
+ }
1206
+ };
1207
+ const sendNotification = (status) => {
1208
+ if (isReportedSideWrong()) return;
1209
+ if (notificationTimeout && currentNotificationStatus !== status) return;
1210
+ if (notificationTimeout && currentNotificationStatus === status) timer.clearTimeout(notificationTimeout);
1211
+ currentNotificationStatus = status;
1212
+ sendBack({
1213
+ type: "DETECTION_UPDATE",
1214
+ status
1215
+ });
1216
+ notificationTimeout = timer.setTimeout(() => {
1217
+ notificationTimeout = null;
1218
+ currentNotificationStatus = null;
1219
+ sendBack({
1220
+ type: "DETECTION_UPDATE",
1221
+ status: "detecting"
1222
+ });
1223
+ }, NOTIFICATION_DURATION_MS);
1224
+ };
1225
+ const canvas = input.frameCapturer.getLatestCanvas();
1226
+ const windowDimensions = getWindowDimensions(canvas?.width() ?? 1280, canvas?.height() ?? 720);
1227
+ const DEFAULT_GEOMETRY = {
1228
+ areaDown: 25e3,
1229
+ areaUp: 55e3,
1230
+ areaIOSPassportUp: 3e4,
1231
+ areaIOSPassportDown: 2e4,
1232
+ widthIOSUp: 160,
1233
+ widthIOSDown: 85,
1234
+ widthDown: 110,
1235
+ widthUp: 205
1236
+ };
1237
+ if (input.config.geometry) provider.setGeometry({
1238
+ ...input.config.geometry,
1239
+ windowOuterWidth: windowDimensions.outerWidth,
1240
+ windowOuterHeight: windowDimensions.outerHeight,
1241
+ windowInnerWidth: windowDimensions.innerWidth,
1242
+ windowInnerHeight: windowDimensions.innerHeight
1243
+ });
1244
+ else provider.setGeometry({
1245
+ ...DEFAULT_GEOMETRY,
1246
+ windowOuterWidth: windowDimensions.outerWidth,
1247
+ windowOuterHeight: windowDimensions.outerHeight,
1248
+ windowInnerWidth: windowDimensions.innerWidth,
1249
+ windowInnerHeight: windowDimensions.innerHeight
1250
+ });
1251
+ const idType = input.currentMode === "back" ? "BackId" : input.currentMode === "passport" ? "Passport" : "FrontId";
1252
+ provider.setSettings({
1253
+ isFixedMask: input.config.settings?.isFixedMask ?? false,
1254
+ isIPhone14OrHigher: input.config.settings?.isIPhone14OrHigher ?? false,
1255
+ idType,
1256
+ blurCheckEnabled: input.config.settings?.blurCheckEnabled ?? false,
1257
+ glareCheckEnabled: input.config.settings?.glareCheckEnabled ?? false,
1258
+ faceQualityCheckEnabled: input.config.settings?.faceQualityCheckEnabled ?? true,
1259
+ iouCheckEnabled: input.config.settings?.iouCheckEnabled ?? true,
1260
+ fpsLimitEnabled: input.config.settings?.fpsLimitEnabled ?? false
1261
+ });
1262
+ const thresholds = {
1263
+ ...DEFAULT_ID_CAPTURE_THRESHOLDS,
1264
+ ...input.config.thresholds,
1265
+ idDetectedTimeout: (input.config.deviceIdleTimeout ?? 10) * 1e3,
1266
+ autocaptureTimeout: (input.config.autoCaptureTimeout ?? 5) * 1e3
1267
+ };
1268
+ provider.setThresholds(thresholds);
1269
+ const modelType = input.config.modelVersion ?? DEFAULT_ID_CAPTURE_MODEL_VERSION;
1270
+ provider.setModelType(modelType);
1271
+ provider.setCallbacks({
1272
+ onFarAway: () => {
1273
+ if (!isCapturing) sendNotification("farAway");
1274
+ },
1275
+ onDetectionStarted: () => {},
1276
+ onMaskChange: (_show, _mask, _top, orientation) => {
1277
+ sendBack({
1278
+ type: "ORIENTATION_CHANGE",
1279
+ orientation
1280
+ });
1281
+ },
1282
+ onBlur: () => {
1283
+ if (!isCapturing) sendNotification("blur");
1284
+ },
1285
+ onGlare: () => {
1286
+ if (!isCapturing) sendNotification("glare");
1287
+ },
1288
+ onIdNotDetected: () => {
1289
+ if (!isCapturing) sendBack({
1290
+ type: "DETECTION_UPDATE",
1291
+ status: "idNotDetected"
1292
+ });
1293
+ },
1294
+ onSwitchToManualCapture: () => {
1295
+ isCapturing = false;
1296
+ sendBack({ type: "SWITCH_TO_MANUAL_CAPTURE" });
1297
+ },
1298
+ onCapturing: () => {
1299
+ clearNotificationTimeout();
1300
+ lastReportedSide = null;
1301
+ isCapturing = true;
1302
+ sendBack({
1303
+ type: "DETECTION_UPDATE",
1304
+ status: "capturing"
1305
+ });
1306
+ },
1307
+ onBestFrame: (blur, glare, orientation) => {
1308
+ if (currentCanvas) {
1309
+ bestCanvas = currentCanvas.clone();
1310
+ storedQualityElements = {
1311
+ glare,
1312
+ sharpness: blur
1313
+ };
1314
+ }
1315
+ if (orientation === "horizontal" || orientation === "vertical") sendBack({
1316
+ type: "ORIENTATION_CHANGE",
1317
+ orientation
1318
+ });
1319
+ },
1320
+ onCapture: () => {
1321
+ isCapturing = false;
1322
+ if (bestCanvas) sendBack({
1323
+ type: "DETECTION_SUCCESS",
1324
+ canvas: bestCanvas,
1325
+ qualityElements: storedQualityElements
1326
+ });
1327
+ else if (currentCanvas) sendBack({
1328
+ type: "DETECTION_SUCCESS",
1329
+ canvas: currentCanvas.clone(),
1330
+ qualityElements: {}
1331
+ });
1332
+ },
1333
+ onIdTypeChange: (idType$1) => {
1334
+ sendBack({
1335
+ type: "ID_TYPE_CHANGE",
1336
+ idType: idType$1
1337
+ });
1338
+ },
1339
+ onIdSideChange: (side) => {
1340
+ if (isCapturing) return;
1341
+ lastReportedSide = side;
1342
+ if (isReportedSideWrong()) clearNotificationTimeout();
1343
+ sendBack({
1344
+ type: "ID_SIDE_CHANGE",
1345
+ side
1346
+ });
1347
+ },
1348
+ onCapturingCounterValueChange: (value) => {
1349
+ sendBack({
1350
+ type: "COUNTER_VALUE_CHANGE",
1351
+ value
1352
+ });
1353
+ }
1354
+ });
1355
+ sendBack({
1356
+ type: "DETECTION_UPDATE",
1357
+ status: "detecting"
1358
+ });
1359
+ const session = new StreamCanvasProcessingSession({
1360
+ capturer: input.frameCapturer,
1361
+ provider: {
1362
+ processFrame: async (frame) => {
1363
+ currentCanvas = IncodeCanvas.fromImageData(frame);
1364
+ sendBack({
1365
+ type: "DETECTION_FRAME",
1366
+ frame
1367
+ });
1368
+ await provider.processFrame(frame);
1369
+ },
1370
+ reset: () => {
1371
+ if (notificationTimeout) {
1372
+ timer.clearTimeout(notificationTimeout);
1373
+ notificationTimeout = null;
1374
+ currentNotificationStatus = null;
1375
+ }
1376
+ currentCanvas = null;
1377
+ bestCanvas = null;
1378
+ storedQualityElements = {};
1379
+ isCapturing = false;
1380
+ lastReportedSide = null;
1381
+ provider.reset();
1382
+ }
1383
+ },
1384
+ onFrame: (frame) => sendBack({
1385
+ type: "DETECTION_FRAME",
1386
+ frame
1387
+ })
1388
+ });
1389
+ sendBack({
1390
+ type: "DETECTION_RESET_READY",
1391
+ reset: () => {
1392
+ provider.reset();
1393
+ }
1394
+ });
1395
+ return () => {
1396
+ clearNotificationTimeout();
1397
+ session?.dispose();
1398
+ };
1399
+ });
1400
+ const uploadIdImageActor = fromPromise(async ({ input, signal }) => {
1401
+ const image = input.canvas.getBase64Image();
1402
+ if (!image) throw new Error(ID_ERROR_CODES.UPLOAD_ERROR);
1403
+ let metadata;
1404
+ if (input.deepsightService) try {
1405
+ const sessionToken = getToken();
1406
+ const frameSource = input.type === "back" ? "BACK_ID" : "FRONT_ID";
1407
+ await input.deepsightService.performVirtualCameraCheck(sessionToken, frameSource);
1408
+ const imageData$1 = input.canvas.getImageData();
1409
+ if (imageData$1) await input.deepsightService.analyzeFrame(imageData$1);
1410
+ const analysisStatus = input.deepsightService.getAnalysisStatus();
1411
+ const motionStatus = input.deepsightService.getMotionStatus();
1412
+ if (input.type === "front") await addDeviceStats({
1413
+ frontIdStatsAnalysisStatus: analysisStatus,
1414
+ backIdStatsAnalysisStatus: "",
1415
+ selfieStatsAnalysisStatus: "",
1416
+ motionStatus
1417
+ });
1418
+ else await addDeviceStats({
1419
+ frontIdStatsAnalysisStatus: "",
1420
+ backIdStatsAnalysisStatus: analysisStatus,
1421
+ selfieStatsAnalysisStatus: "",
1422
+ motionStatus
1423
+ });
1424
+ metadata = input.deepsightService.getMetadata();
1425
+ } catch {}
1426
+ const imageData = input.canvas?.getImageData() ?? void 0;
1427
+ const logs = input.deepsightService?.getPipelineState() ?? "";
1428
+ input.dependencies?.trackCaptureAttemptFinished?.({
1429
+ logs,
1430
+ resolution: input.captureResolution,
1431
+ fallbackLevel: input.cameraFallbackLevel
1432
+ });
1433
+ return uploadIdImage({
1434
+ image,
1435
+ type: input.type,
1436
+ sendBase64: true,
1437
+ glare: input.qualityElements?.glare,
1438
+ sharpness: input.qualityElements?.sharpness,
1439
+ ageAssurance: input.ageAssurance,
1440
+ signal,
1441
+ onProgress: input.onProgress,
1442
+ metadata,
1443
+ analyticsProvider: input.analyticsProvider,
1444
+ imageData,
1445
+ isSecondId: input.isSecondId,
1446
+ onlyFront: input.onlyFront
1447
+ });
1448
+ });
1449
+ const processIdActor = fromPromise(async ({ input, signal }) => {
1450
+ return processId(input.isSecondId, "", signal);
1451
+ });
1452
+ const startRecordingActor = fromPromise(async ({ input }) => {
1453
+ if (!input.stream) return;
1454
+ const type = input.currentMode === "back" ? "backId" : "frontId";
1455
+ return startRecordingSession({
1456
+ config: input.config,
1457
+ stream: input.stream,
1458
+ existing: input.existing,
1459
+ type
1460
+ });
1461
+ });
1462
+ const checkMotionSensorActor = fromCallback(({ input, sendBack }) => {
1463
+ if (!input.motionProvider) {
1464
+ sendBack({
1465
+ type: "MOTION_STATUS",
1466
+ status: "UNCLEAR"
1467
+ });
1468
+ return () => {};
1469
+ }
1470
+ const timer = BrowserTimerProvider.getInstance();
1471
+ const interval = timer.setInterval(() => {
1472
+ sendBack({
1473
+ type: "MOTION_STATUS",
1474
+ status: input.motionProvider.check()
1475
+ });
1476
+ }, 500);
1477
+ return () => timer.clearInterval(interval);
1478
+ });
1479
+ const initializeDeepsightSessionActor = fromPromise(async ({ input }) => {
1480
+ if (!input.dependencies) return;
1481
+ const { loadDeepsightSession } = await import("./deepsightLoader-Cm4JIT_z.esm.js");
1482
+ return loadDeepsightSession({
1483
+ ds: input.ds,
1484
+ storage: input.dependencies.storage,
1485
+ disableIpify: input.disableIpify
1486
+ });
1487
+ });
1488
+ const checkVirtualCameraActor = fromPromise(async ({ input }) => {
1489
+ if (!input.deepsightService || !input.stream) return false;
1490
+ const videoTrack = input.stream.getVideoTracks()[0];
1491
+ if (!videoTrack) return false;
1492
+ return input.deepsightService.checkVirtualCamera(videoTrack);
1493
+ });
1494
+
1495
+ //#endregion
1496
+ //#region src/modules/id/idCaptureActions.ts
1497
+ function performStopMediaStream(context) {
1498
+ context.frameCapturer?.dispose();
1499
+ if (context.stream) stopStream(context.stream);
1500
+ }
1501
+ function performDisposeProvider(context) {
1502
+ context.provider?.dispose?.();
1503
+ }
1504
+ function performCleanupDeepsight(context) {
1505
+ context.deepsightService?.cleanup();
1506
+ }
1507
+ function performResetForBackCapture(context) {
1508
+ context.frameCapturer?.dispose();
1509
+ if (context.stream) stopStream(context.stream);
1510
+ context.provider?.reset();
1511
+ }
1512
+ function performResetForFrontCapture(context) {
1513
+ context.frameCapturer?.dispose();
1514
+ if (context.stream) stopStream(context.stream);
1515
+ context.provider?.reset();
1516
+ }
1517
+ function performResetDetection(context) {
1518
+ context.resetDetection?.();
1519
+ }
1520
+ function performTrackTutorialId() {}
1521
+ function performTrackContinue() {}
1522
+ function performTrackCameraId(context) {}
1523
+ function performStopMediaRecording(context) {
1524
+ if (context.recordingSession) stopRecording(context.recordingSession);
1525
+ }
1526
+ function getStreamFromEvent(event) {
1527
+ if ("output" in event) return event.output.stream;
1528
+ }
1529
+ function getProviderFromEvent(event) {
1530
+ if ("output" in event) return event.output.provider;
1531
+ }
1532
+ function getCaptureResolutionFromEvent(event) {
1533
+ if ("output" in event) return event.output.captureResolution;
1534
+ }
1535
+ function getCameraFallbackLevelFromEvent(event) {
1536
+ if ("output" in event) return event.output.cameraFallbackLevel;
1537
+ }
1538
+ function getFrameCapturerFromEvent(event) {
1539
+ if ("output" in event) {
1540
+ const output = event.output;
1541
+ if (output.stream) return new StreamCanvasCapture(output.stream);
1542
+ }
1543
+ }
1544
+ function getResetContextValues(context) {
1545
+ context.provider?.reset();
1546
+ const currentMode = context.config.onlyBack ? "back" : !context.config.enableId && context.config.enablePassport ? "passport" : context.config.usSmartCapture ? "back" : "front";
1547
+ return {
1548
+ stream: void 0,
1549
+ provider: context.provider,
1550
+ frameCapturer: void 0,
1551
+ error: void 0,
1552
+ detectionStatus: "idle",
1553
+ counterValue: 0,
1554
+ orientation: void 0,
1555
+ capturedImages: {},
1556
+ captureOnlyImages: {},
1557
+ uploadResponse: void 0,
1558
+ recordingSession: void 0,
1559
+ attemptsRemaining: context.config.captureAttempts,
1560
+ expiredAttempts: 0,
1561
+ skipProcessId: false,
1562
+ expiredFromUpload: false,
1563
+ isDigitalUpload: false,
1564
+ exhaustedFromUpload: false,
1565
+ forceFinishAfterProcessing: false,
1566
+ uploadError: void 0,
1567
+ permissionResult: void 0,
1568
+ resetDetection: void 0,
1569
+ idType: void 0,
1570
+ qualityElements: void 0,
1571
+ previewImageUrl: void 0,
1572
+ uploadProgress: void 0,
1573
+ currentMode,
1574
+ selectedDocumentType: void 0,
1575
+ manualCaptureTriggered: false,
1576
+ captureResolution: void 0,
1577
+ cameraFallbackLevel: void 0
1578
+ };
1579
+ }
1580
+ function getClearUploadFailureValues(context) {
1581
+ if (context.previewImageUrl) revokeObjectURL(context.previewImageUrl);
1582
+ return {
1583
+ uploadError: void 0,
1584
+ detectionStatus: "idle",
1585
+ previewImageUrl: void 0,
1586
+ uploadProgress: void 0
1587
+ };
1588
+ }
1589
+ function getUploadValidationError(context) {
1590
+ if (!context.uploadResponse) return ID_ERROR_CODES.SERVER;
1591
+ return validateUploadResponse(context.uploadResponse, {
1592
+ skipGlareFront: context.uploadResponse.skipGlareFront,
1593
+ skipGlareBack: context.uploadResponse.skipGlareBack
1594
+ })?.errorKey ?? ID_ERROR_CODES.SERVER;
1595
+ }
1596
+ function storeCapturedCanvasInProviderLogic(context, event) {
1597
+ let canvas = null;
1598
+ if ("canvas" in event && event.canvas) canvas = event.canvas;
1599
+ else canvas = context.frameCapturer?.getLatestCanvas() ?? null;
1600
+ if (!canvas || !context.provider) return;
1601
+ const canvasWidth = canvas.width();
1602
+ const canvasHeight = canvas.height();
1603
+ if (!canvasWidth || !canvasHeight) return;
1604
+ const originalCanvas = canvas;
1605
+ let frameRect;
1606
+ const { innerWidth: viewportWidth, innerHeight: viewportHeight } = getWindowDimensions();
1607
+ if (context.detectionArea) {
1608
+ const scaleX = viewportWidth / canvasWidth;
1609
+ const scaleY = viewportHeight / canvasHeight;
1610
+ const scale = Math.max(scaleX, scaleY);
1611
+ const displayedWidth = canvasWidth * scale;
1612
+ const displayedHeight = canvasHeight * scale;
1613
+ const offsetX = (viewportWidth - displayedWidth) / 2;
1614
+ const offsetY = (viewportHeight - displayedHeight) / 2;
1615
+ frameRect = {
1616
+ x: (context.detectionArea.x - offsetX) / scale,
1617
+ y: (context.detectionArea.y - offsetY) / scale,
1618
+ w: context.detectionArea.width / scale,
1619
+ h: context.detectionArea.height / scale
1620
+ };
1621
+ } else if (context.frameRect) {
1622
+ const scaleX = viewportWidth / canvasWidth;
1623
+ const scaleY = viewportHeight / canvasHeight;
1624
+ const scale = Math.max(scaleX, scaleY);
1625
+ const displayedWidth = canvasWidth * scale;
1626
+ const displayedHeight = canvasHeight * scale;
1627
+ const offsetX = (viewportWidth - displayedWidth) / 2;
1628
+ const offsetY = (viewportHeight - displayedHeight) / 2;
1629
+ frameRect = {
1630
+ x: (context.frameRect.x - offsetX) / scale,
1631
+ y: (context.frameRect.y - offsetY) / scale,
1632
+ w: context.frameRect.w / scale,
1633
+ h: context.frameRect.h / scale
1634
+ };
1635
+ } else {
1636
+ const quadValue = (context.provider.getLastProcessResult?.())?.quad;
1637
+ const hasQuad = !!quadValue;
1638
+ const quadSize = quadValue?.size ? quadValue.size() : quadValue?.length ?? 0;
1639
+ if (hasQuad && quadSize >= 4 && quadValue.get) {
1640
+ const p0 = quadValue.get(0);
1641
+ const p1 = quadValue.get(1);
1642
+ const p2 = quadValue.get(2);
1643
+ const p3 = quadValue.get(3);
1644
+ const minX = Math.min(p0.x, p1.x, p2.x, p3.x);
1645
+ const maxX = Math.max(p0.x, p1.x, p2.x, p3.x);
1646
+ const minY = Math.min(p0.y, p1.y, p2.y, p3.y);
1647
+ const maxY = Math.max(p0.y, p1.y, p2.y, p3.y);
1648
+ frameRect = {
1649
+ x: minX,
1650
+ y: minY,
1651
+ w: maxX - minX,
1652
+ h: maxY - minY
1653
+ };
1654
+ } else {
1655
+ const frameViewportWidth = Math.min(387, viewportWidth * .9);
1656
+ const frameViewportHeight = frameViewportWidth / (35 / 22);
1657
+ const frameViewportX = (viewportWidth - frameViewportWidth) / 2;
1658
+ const frameViewportY = (viewportHeight - frameViewportHeight) / 2;
1659
+ frameRect = {
1660
+ x: canvasWidth * frameViewportX / viewportWidth,
1661
+ y: canvasHeight * frameViewportY / viewportHeight,
1662
+ w: canvasWidth * frameViewportWidth / viewportWidth,
1663
+ h: canvasHeight * frameViewportHeight / viewportHeight
1664
+ };
1665
+ }
1666
+ }
1667
+ const transformedCanvas = context.provider.transformPerspective(originalCanvas, frameRect);
1668
+ context.provider.setCapturedCanvases(originalCanvas, transformedCanvas);
1669
+ }
1670
+ function getStoreCapturedImageValues(context, event) {
1671
+ if (!context.currentMode) return {
1672
+ capturedImages: context.capturedImages,
1673
+ previewImageUrl: context.previewImageUrl
1674
+ };
1675
+ const transformedCanvas = context.provider?.getCapturedCanvas();
1676
+ const transformedImage = transformedCanvas?.getBase64Image(1, true);
1677
+ let fallbackImage = "";
1678
+ if ("output" in event) fallbackImage = event.output.originalImage ?? "";
1679
+ const imageData = { imageBase64: transformedImage ?? fallbackImage };
1680
+ let capturedImages = context.capturedImages;
1681
+ if (context.currentMode === "front" || context.currentMode === "passport") capturedImages = {
1682
+ ...context.capturedImages,
1683
+ front: imageData
1684
+ };
1685
+ else capturedImages = {
1686
+ ...context.capturedImages,
1687
+ back: imageData
1688
+ };
1689
+ let previewImageUrl = context.previewImageUrl;
1690
+ if (transformedCanvas) {
1691
+ transformedCanvas.updateBlob();
1692
+ const blobData = transformedCanvas.getBlobData();
1693
+ if (blobData?.url) previewImageUrl = blobData.url;
1694
+ } else if ("canvas" in event && event.canvas) {
1695
+ const canvas = event.canvas;
1696
+ canvas.updateBlob();
1697
+ const blobData = canvas.getBlobData();
1698
+ if (blobData?.url) previewImageUrl = blobData.url;
1699
+ }
1700
+ return {
1701
+ capturedImages,
1702
+ previewImageUrl
1703
+ };
1704
+ }
1705
+ function getDetectionStatusFromUpdate(context, event) {
1706
+ if (event.type === "DETECTION_UPDATE") {
1707
+ const newStatus = event.status;
1708
+ const currentStatus = context.detectionStatus;
1709
+ if (currentStatus === "wrongSide") {
1710
+ if (!(newStatus === "capturing" || newStatus === "manualCapture" || newStatus === "offline")) return currentStatus;
1711
+ return newStatus;
1712
+ }
1713
+ if ((newStatus === "blur" || newStatus === "glare") && currentStatus === "farAway") return currentStatus;
1714
+ if ((newStatus === "wrongSide" || newStatus === "farAway") && (currentStatus === "blur" || currentStatus === "glare")) return newStatus;
1715
+ return newStatus;
1716
+ }
1717
+ return "idle";
1718
+ }
1719
+ function getDetectionStatusFromSideChange(context, side) {
1720
+ const detectedSide = side?.toLowerCase() || "";
1721
+ const currentMode = context.currentMode;
1722
+ if (detectedSide === "wrong") return "wrongSide";
1723
+ const isBackDetected = detectedSide.includes("back") && !detectedSide.includes("front");
1724
+ const isFrontDetected = detectedSide.includes("front") && !detectedSide.includes("back");
1725
+ if (currentMode === "front" && isBackDetected || currentMode === "back" && isFrontDetected) return "wrongSide";
1726
+ if (currentMode === "front" && isFrontDetected || currentMode === "back" && isBackDetected || currentMode === "passport") return "detecting";
1727
+ return "detecting";
1728
+ }
1729
+ function getCurrentModeFromEvent(context, event) {
1730
+ if ("documentType" in event) {
1731
+ if (event.documentType === "passport") return "passport";
1732
+ return context.config.usSmartCapture ? "back" : "front";
1733
+ }
1734
+ if (event.type === "FRONT_COMPLETE") return "back";
1735
+ return context.currentMode;
1736
+ }
1737
+
1738
+ //#endregion
1739
+ //#region src/modules/id/idCaptureGuards.ts
1740
+ const hasShowTutorialGuard = ({ context }) => context.config.showTutorial;
1741
+ const hasAgeAssuranceGuard = ({ context }) => context.config.ageAssurance === true;
1742
+ const hasShowDocumentChooserGuard = ({ context }) => !context.config.onlyBack && (context.config.showDocumentChooserScreen ?? false);
1743
+ const isPermissionGrantedGuard = ({ event }) => {
1744
+ if ("output" in event) return event.output === "granted";
1745
+ return false;
1746
+ };
1747
+ const isPermissionDeniedErrorGuard = ({ event }) => {
1748
+ if ("error" in event) {
1749
+ const error = event.error;
1750
+ return error?.name === "NotAllowedError" || error?.name === "PermissionDeniedError";
1751
+ }
1752
+ return false;
1753
+ };
1754
+ const hasStreamGuard = ({ context }) => context.stream !== void 0;
1755
+ const hasAttemptsRemainingGuard = ({ context }) => context.attemptsRemaining > 0;
1756
+ const hasCapturedImageGuard = ({ context }) => {
1757
+ return context.provider?.getCapturedCanvas() !== null;
1758
+ };
1759
+ const hasUploadValidationErrorGuard = ({ context }) => {
1760
+ if (!context.uploadResponse) return false;
1761
+ return validateUploadResponse(context.uploadResponse, {
1762
+ skipGlareFront: context.uploadResponse.skipGlareFront,
1763
+ skipGlareBack: context.uploadResponse.skipGlareBack
1764
+ }) !== void 0;
1765
+ };
1766
+ const isFrontModeGuard = ({ context }) => context.currentMode === "front" || context.currentMode === "passport";
1767
+ /**
1768
+ * `config.onlyFront` from the orchestrated flow JSON is intentionally not
1769
+ * read here: the flow value cannot account for per-document overrides, so the
1770
+ * backend resolves the real policy per document at upload time
1771
+ * (via `skipBackIdCapture` on the upload response). Standalone
1772
+ * `idCaptureManager` consumers that pass `onlyFront: true` directly will
1773
+ * therefore also be ignored — re-wire this guard if that capability is needed
1774
+ * again.
1775
+ */
1776
+ const isOnlyFrontGuard = (_args) => false;
1777
+ const shouldContinueToBackGuard = ({ context }) => {
1778
+ if (context.currentMode !== "front" && context.currentMode !== "passport") return false;
1779
+ if (context.config.onlyBack) return false;
1780
+ if (context.config.usSmartCapture) return false;
1781
+ if (context.uploadResponse?.skipBackIdCapture) {
1782
+ if (!(context.config.alwaysCaptureBackOfId === true && context.currentMode !== "passport")) return false;
1783
+ }
1784
+ return true;
1785
+ };
1786
+ const shouldContinueToFrontGuard = ({ context }) => context.config.usSmartCapture === true && context.currentMode === "back" && context.uploadResponse?.forceFrontIdCapture === true;
1787
+ const hasMandatoryConsentGuard = ({ context }) => context.uploadResponse?.showMandatoryConsent === true;
1788
+ const isDeepsightEnabledGuard = ({ context }) => context.dependencies !== void 0;
1789
+ const isDeepsightReadyGuard = ({ context }) => context.deepsightService !== void 0;
1790
+ const needsDeepsightInitGuard = ({ context }) => context.dependencies !== void 0 && context.deepsightService === void 0 && !context.deepsightInitAttempted;
1791
+ const hasOnlyManualUploadAvailableGuard = ({ context }) => context.availableDocumentTypes.length === 1 && context.availableDocumentTypes[0] === "manualIdUpload";
1792
+ const isManualIdUploadSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "manualIdUpload";
1793
+ const isDigitalIdUploadSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "digitalIdUpload";
1794
+ const isUploadExpiredGuard = ({ context }) => context.uploadResponse?.isDocumentExpired === true;
1795
+ /**
1796
+ * True when *this* expired upload will exhaust the budget. Compares the
1797
+ * post-increment count, so the exhaustion branch can be picked in the same
1798
+ * tick that runs `incrementExpiredAttempts`. With `captureAttempts=3`:
1799
+ * - attempt 1 → 0+1=1 (not exhausted)
1800
+ * - attempt 2 → 1+1=2 (not exhausted)
1801
+ * - attempt 3 → 2+1=3 (exhausted, force-back / finish)
1802
+ */
1803
+ const isExpiredAttemptsExhaustedGuard = ({ context }) => context.expiredAttempts + 1 >= context.config.captureAttempts;
1804
+ const isNotPassportModeGuard = ({ context }) => context.currentMode !== "passport";
1805
+ /**
1806
+ * V1 parity for `shouldApplyAlwaysCaptureBackOverride` — force-redirects to
1807
+ * back capture after expired-front-attempts exhaust, but only when:
1808
+ * - we're on the front side
1809
+ * - `alwaysCaptureBackOfId` is set
1810
+ * - the flow isn't single-side (onlyBack / usSmartCapture)
1811
+ * - the session isn't a Digital ID upload (digital IDs are PDFs — no back
1812
+ * side exists, so the override never applies regardless of config)
1813
+ */
1814
+ const shouldForceBackOnExpiredGuard = ({ context }) => context.currentMode === "front" && context.config.alwaysCaptureBackOfId === true && !context.config.onlyBack && !context.config.usSmartCapture && !context.isDigitalUpload;
1815
+ const wasExpiredFromUploadGuard = ({ context }) => context.expiredFromUpload === true;
1816
+ const shouldSkipProcessIdGuard = ({ context }) => context.skipProcessId === true;
1817
+ /**
1818
+ * Bug 4 fix: when `expiredExhausted` is reached via the per-upload-expired
1819
+ * exhaustion path with a back side captured (or the entire single-side back
1820
+ * flow), we want `processId` to run once on Continue so the backend
1821
+ * processes whatever sides were uploaded. Front-only exhaustion (no back to
1822
+ * process) and the force-back V1 path keep using `setSkipProcessId` instead.
1823
+ */
1824
+ const shouldProcessAfterExhaustionGuard = ({ context }) => context.exhaustedFromUpload === true && context.currentMode === "back";
1825
+ /**
1826
+ * `processing.onDone` reads this to short-circuit straight to `finished`
1827
+ * after the post-exhaustion `processId` call returns — without it, an
1828
+ * `isDocumentExpired:true` response would loop back to the Expired screen
1829
+ * we just terminated.
1830
+ */
1831
+ const forceFinishAfterProcessingGuard = ({ context }) => context.forceFinishAfterProcessing === true;
1832
+ /**
1833
+ * Cap on the end-of-flow expired path. All capture types (camera, digital,
1834
+ * manual) share `config.captureAttempts` for consistency — the user-visible
1835
+ * "X attempts remaining" counter is the same regardless of how the document
1836
+ * was submitted.
1837
+ */
1838
+ const isProcessingExpiredExhaustedGuard = ({ context }) => context.processingExpiredAttempts + 1 >= context.config.captureAttempts;
1839
+
1840
+ //#endregion
1841
+ //#region src/modules/id/idCaptureStateMachine.ts
1842
+ function getIdErrorCodeFromUnknown(error) {
1843
+ if (error instanceof Error) {
1844
+ const message = error.message;
1845
+ return Object.values(ID_ERROR_CODES).find((value) => message.includes(value));
1846
+ }
1847
+ }
1848
+ const _idCaptureMachine = setup({
1849
+ types: {
1850
+ context: {},
1851
+ events: {},
1852
+ input: {}
1853
+ },
1854
+ actors: {
1855
+ checkPermission: checkPermissionActor,
1856
+ requestPermission: requestPermissionActor,
1857
+ initializeCamera: initializeCameraActor,
1858
+ runDetection: runDetectionActor,
1859
+ uploadIdImage: uploadIdImageActor,
1860
+ processId: processIdActor,
1861
+ startRecording: startRecordingActor,
1862
+ checkMotionSensor: checkMotionSensorActor,
1863
+ initializeDeepsightSession: initializeDeepsightSessionActor,
1864
+ checkVirtualCamera: checkVirtualCameraActor,
1865
+ manualUploadMachine,
1866
+ digitalUploadMachine
1867
+ },
1868
+ actions: {
1869
+ stopMediaStream: assign(({ context }) => {
1870
+ performStopMediaStream(context);
1871
+ return {
1872
+ stream: void 0,
1873
+ frameCapturer: void 0
1874
+ };
1875
+ }),
1876
+ disposeProvider: ({ context }) => {
1877
+ performDisposeProvider(context);
1878
+ },
1879
+ cleanupDeepsight: ({ context }) => {
1880
+ performCleanupDeepsight(context);
1881
+ },
1882
+ flagIdManualReview: () => {
1883
+ flagIdManualReview();
1884
+ },
1885
+ resetForBackCapture: assign(({ context }) => {
1886
+ performResetForBackCapture(context);
1887
+ return {
1888
+ stream: void 0,
1889
+ frameCapturer: void 0,
1890
+ detectionStatus: "idle",
1891
+ counterValue: 0,
1892
+ orientation: void 0,
1893
+ resetDetection: void 0,
1894
+ idType: void 0,
1895
+ qualityElements: void 0,
1896
+ debugFrame: void 0,
1897
+ frameRect: void 0,
1898
+ previewImageUrl: void 0,
1899
+ uploadProgress: void 0,
1900
+ manualCaptureTriggered: false,
1901
+ attemptsRemaining: context.config.captureAttempts,
1902
+ expiredAttempts: 0,
1903
+ expiredFromUpload: false,
1904
+ exhaustedFromUpload: false,
1905
+ forceFinishAfterProcessing: false,
1906
+ captureResolution: void 0,
1907
+ cameraFallbackLevel: void 0
1908
+ };
1909
+ }),
1910
+ resetForFrontCapture: assign(({ context }) => {
1911
+ performResetForFrontCapture(context);
1912
+ return {
1913
+ stream: void 0,
1914
+ frameCapturer: void 0,
1915
+ detectionStatus: "idle",
1916
+ counterValue: 0,
1917
+ orientation: void 0,
1918
+ resetDetection: void 0,
1919
+ idType: void 0,
1920
+ qualityElements: void 0,
1921
+ debugFrame: void 0,
1922
+ frameRect: void 0,
1923
+ previewImageUrl: void 0,
1924
+ uploadProgress: void 0,
1925
+ manualCaptureTriggered: false,
1926
+ attemptsRemaining: context.config.captureAttempts,
1927
+ expiredAttempts: 0,
1928
+ expiredFromUpload: false,
1929
+ exhaustedFromUpload: false,
1930
+ forceFinishAfterProcessing: false,
1931
+ captureResolution: void 0,
1932
+ cameraFallbackLevel: void 0
1933
+ };
1934
+ }),
1935
+ prepareForBackCapture: assign(({ context }) => {
1936
+ context.provider?.reset();
1937
+ return {
1938
+ detectionStatus: "idle",
1939
+ counterValue: 0,
1940
+ orientation: void 0,
1941
+ resetDetection: void 0,
1942
+ idType: void 0,
1943
+ qualityElements: void 0,
1944
+ debugFrame: void 0,
1945
+ frameRect: void 0,
1946
+ previewImageUrl: void 0,
1947
+ uploadProgress: void 0,
1948
+ manualCaptureTriggered: false,
1949
+ attemptsRemaining: context.config.captureAttempts
1950
+ };
1951
+ }),
1952
+ setStreamAndCapturer: assign({
1953
+ stream: ({ event }) => getStreamFromEvent(event),
1954
+ provider: ({ event }) => getProviderFromEvent(event),
1955
+ frameCapturer: ({ event }) => getFrameCapturerFromEvent(event),
1956
+ captureResolution: ({ event }) => getCaptureResolutionFromEvent(event),
1957
+ cameraFallbackLevel: ({ event }) => getCameraFallbackLevelFromEvent(event)
1958
+ }),
1959
+ trackTutorialId: () => {
1960
+ /* @__PURE__ */ performTrackTutorialId();
1961
+ },
1962
+ trackContinue: () => {
1963
+ /* @__PURE__ */ performTrackContinue();
1964
+ },
1965
+ trackCameraId: ({ context }) => {
1966
+ /* @__PURE__ */ performTrackCameraId(context);
1967
+ },
1968
+ preloadRecordingProvider: ({ context }) => {
1969
+ preloadIdRecordingProvider(context.config);
1970
+ },
1971
+ resetContext: assign(({ context }) => getResetContextValues(context)),
1972
+ resetDetection: ({ context }) => {
1973
+ performResetDetection(context);
1974
+ },
1975
+ captureImage: assign({ qualityElements: ({ event }) => {
1976
+ if ("qualityElements" in event) return event.qualityElements;
1977
+ } }),
1978
+ storeCapturedCanvasInProvider: ({ context, event }) => {
1979
+ storeCapturedCanvasInProviderLogic(context, event);
1980
+ },
1981
+ captureLatestFrame: ({ context }) => {
1982
+ context.frameCapturer?.getLatestCanvas();
1983
+ },
1984
+ clearUploadFailure: assign(({ context }) => getClearUploadFailureValues(context)),
1985
+ clearStreamForRetry: assign(({ context }) => {
1986
+ performStopMediaStream(context);
1987
+ performDisposeProvider(context);
1988
+ return {
1989
+ stream: void 0,
1990
+ provider: void 0,
1991
+ frameCapturer: void 0,
1992
+ captureResolution: void 0,
1993
+ cameraFallbackLevel: void 0
1994
+ };
1995
+ }),
1996
+ decrementAttemptsRemaining: assign(({ context }) => ({ attemptsRemaining: context.attemptsRemaining - 1 })),
1997
+ setUploadErrorFromUploadValidation: assign({ uploadError: ({ context }) => getUploadValidationError(context) }),
1998
+ stopMediaRecording: ({ context }) => {
1999
+ performStopMediaRecording(context);
2000
+ },
2001
+ clearRecordingSession: assign({ recordingSession: () => void 0 }),
2002
+ setSelectedDocument: assign({ selectedDocumentType: ({ event }) => {
2003
+ if ("documentType" in event) return event.documentType;
2004
+ } }),
2005
+ setCurrentMode: assign({ currentMode: ({ event, context }) => getCurrentModeFromEvent(context, event) }),
2006
+ storeCapturedImage: assign(({ context, event }) => getStoreCapturedImageValues(context, event)),
2007
+ setDetectionStatus: assign({ detectionStatus: ({ event, context }) => getDetectionStatusFromUpdate(context, event) }),
2008
+ setCounterValue: assign({ counterValue: ({ event }) => {
2009
+ if ("value" in event) return event.value;
2010
+ return 0;
2011
+ } }),
2012
+ setIdType: assign({ idType: ({ event }) => {
2013
+ if ("idType" in event) return event.idType;
2014
+ } }),
2015
+ setOrientation: assign({ orientation: ({ event }) => {
2016
+ if ("orientation" in event) return event.orientation;
2017
+ } }),
2018
+ setFrameRect: assign({ frameRect: ({ event }) => {
2019
+ if ("frameRect" in event) return event.frameRect;
2020
+ } }),
2021
+ setDetectionArea: assign({ detectionArea: ({ event }) => {
2022
+ if ("detectionArea" in event) return event.detectionArea;
2023
+ } }),
2024
+ setMotionStatus: assign({ motionStatus: ({ event }) => {
2025
+ if ("status" in event && event.type === "MOTION_STATUS") return event.status;
2026
+ } }),
2027
+ incrementExpiredAttempts: assign(({ context }) => ({ expiredAttempts: context.expiredAttempts + 1 })),
2028
+ storeDigitalUploadResponse: assign(({ self }) => {
2029
+ const response = ((self.getSnapshot().children?.["digitalIdUpload"]?.getSnapshot())?.context)?.response;
2030
+ if (!response) return { isDigitalUpload: true };
2031
+ return {
2032
+ uploadResponse: response,
2033
+ isDigitalUpload: true
2034
+ };
2035
+ }),
2036
+ incrementProcessingExpiredAttempts: assign(({ context }) => ({ processingExpiredAttempts: context.processingExpiredAttempts + 1 })),
2037
+ setSkipProcessId: assign({ skipProcessId: () => true }),
2038
+ setExpiredFromUpload: assign({ expiredFromUpload: () => true }),
2039
+ setExhaustedFromUpload: assign({ exhaustedFromUpload: () => true }),
2040
+ setForceFinishAfterProcessing: assign({ forceFinishAfterProcessing: () => true }),
2041
+ clearExpiredFromUpload: assign({ expiredFromUpload: () => false })
2042
+ },
2043
+ guards: {
2044
+ hasShowTutorial: hasShowTutorialGuard,
2045
+ hasAgeAssurance: hasAgeAssuranceGuard,
2046
+ hasShowDocumentChooser: hasShowDocumentChooserGuard,
2047
+ isPermissionGranted: isPermissionGrantedGuard,
2048
+ isPermissionDeniedError: isPermissionDeniedErrorGuard,
2049
+ hasStream: hasStreamGuard,
2050
+ hasAttemptsRemaining: hasAttemptsRemainingGuard,
2051
+ hasCapturedImage: hasCapturedImageGuard,
2052
+ hasUploadValidationError: hasUploadValidationErrorGuard,
2053
+ isFrontMode: isFrontModeGuard,
2054
+ isOnlyFront: isOnlyFrontGuard,
2055
+ shouldContinueToBack: shouldContinueToBackGuard,
2056
+ shouldContinueToFront: shouldContinueToFrontGuard,
2057
+ hasMandatoryConsent: hasMandatoryConsentGuard,
2058
+ isDeepsightEnabled: isDeepsightEnabledGuard,
2059
+ isDeepsightReady: isDeepsightReadyGuard,
2060
+ needsDeepsightInit: needsDeepsightInitGuard,
2061
+ hasOnlyManualUploadAvailable: hasOnlyManualUploadAvailableGuard,
2062
+ isManualIdUploadSelected: isManualIdUploadSelectedGuard,
2063
+ isDigitalIdUploadSelected: isDigitalIdUploadSelectedGuard,
2064
+ isUploadExpired: isUploadExpiredGuard,
2065
+ isExpiredAttemptsExhausted: isExpiredAttemptsExhaustedGuard,
2066
+ isNotPassportMode: isNotPassportModeGuard,
2067
+ shouldForceBackOnExpired: shouldForceBackOnExpiredGuard,
2068
+ wasExpiredFromUpload: wasExpiredFromUploadGuard,
2069
+ shouldSkipProcessId: shouldSkipProcessIdGuard,
2070
+ isProcessingExpiredExhausted: isProcessingExpiredExhaustedGuard,
2071
+ shouldProcessAfterExhaustion: shouldProcessAfterExhaustionGuard,
2072
+ forceFinishAfterProcessing: forceFinishAfterProcessingGuard,
2073
+ isManualUploadExhausted: ({ event }) => event.output?.result === "exhausted",
2074
+ isDigitalUploadExhausted: ({ event }) => event.output?.result === "exhausted",
2075
+ isDigitalUploadClosed: ({ event }) => event.output?.result === "closed",
2076
+ isDigitalUploadSuccessful: ({ event }) => event.output?.result === "success"
2077
+ }
2078
+ }).createMachine({
2079
+ id: "idCapture",
2080
+ initial: "idle",
2081
+ context: ({ input }) => {
2082
+ const currentMode = input.config.onlyBack ? "back" : !input.config.enableId && input.config.enablePassport ? "passport" : input.config.usSmartCapture ? "back" : "front";
2083
+ return {
2084
+ config: input.config,
2085
+ currentMode,
2086
+ selectedDocumentType: void 0,
2087
+ stream: void 0,
2088
+ provider: void 0,
2089
+ frameCapturer: void 0,
2090
+ error: void 0,
2091
+ detectionStatus: "idle",
2092
+ counterValue: 0,
2093
+ orientation: void 0,
2094
+ capturedImages: {},
2095
+ captureOnlyImages: {},
2096
+ uploadResponse: void 0,
2097
+ recordingSession: void 0,
2098
+ attemptsRemaining: input.config.captureAttempts,
2099
+ expiredAttempts: 0,
2100
+ processingExpiredAttempts: 0,
2101
+ skipProcessId: input.config.skipProcessId === true,
2102
+ expiredFromUpload: false,
2103
+ isDigitalUpload: false,
2104
+ exhaustedFromUpload: false,
2105
+ forceFinishAfterProcessing: false,
2106
+ uploadError: void 0,
2107
+ permissionResult: void 0,
2108
+ resetDetection: void 0,
2109
+ idType: void 0,
2110
+ qualityElements: void 0,
2111
+ debugFrame: void 0,
2112
+ frameRect: void 0,
2113
+ detectionArea: void 0,
2114
+ previewImageUrl: void 0,
2115
+ uploadProgress: void 0,
2116
+ motionStatus: void 0,
2117
+ manualCaptureTriggered: false,
2118
+ deepsightService: void 0,
2119
+ analyticsProvider: input.analyticsProvider,
2120
+ dependencies: input.dependencies,
2121
+ disableIpify: getDisableIpify(),
2122
+ deepsightInitAttempted: false,
2123
+ availableDocumentTypes: getAvailableDocumentTypes(input.config),
2124
+ captureResolution: void 0,
2125
+ cameraFallbackLevel: void 0
2126
+ };
2127
+ },
2128
+ on: {
2129
+ QUIT: { target: "#idCapture.closed" },
2130
+ UPDATE_DETECTION_AREA: { actions: "setDetectionArea" }
2131
+ },
2132
+ states: {
2133
+ idle: { on: { LOAD: [
2134
+ {
2135
+ target: "manualIdUpload",
2136
+ guard: "hasOnlyManualUploadAvailable"
2137
+ },
2138
+ {
2139
+ target: "chooser",
2140
+ guard: "hasShowDocumentChooser"
2141
+ },
2142
+ {
2143
+ target: "ageVerification",
2144
+ guard: "hasAgeAssurance"
2145
+ },
2146
+ {
2147
+ target: "tutorial",
2148
+ guard: "hasShowTutorial"
2149
+ },
2150
+ { target: "loading" }
2151
+ ] } },
2152
+ chooser: { on: { SELECT_DOCUMENT: [
2153
+ {
2154
+ target: "digitalIdUpload",
2155
+ guard: "isDigitalIdUploadSelected",
2156
+ actions: ["setSelectedDocument"]
2157
+ },
2158
+ {
2159
+ target: "manualIdUpload",
2160
+ guard: "isManualIdUploadSelected",
2161
+ actions: ["setSelectedDocument"]
2162
+ },
2163
+ {
2164
+ target: "ageVerification",
2165
+ guard: "hasAgeAssurance",
2166
+ actions: ["setSelectedDocument", "setCurrentMode"]
2167
+ },
2168
+ {
2169
+ target: "tutorial",
2170
+ guard: "hasShowTutorial",
2171
+ actions: ["setSelectedDocument", "setCurrentMode"]
2172
+ },
2173
+ {
2174
+ target: "loading",
2175
+ actions: ["setSelectedDocument", "setCurrentMode"]
2176
+ }
2177
+ ] } },
2178
+ ageVerification: { on: { NEXT_STEP: [{
2179
+ target: "tutorial",
2180
+ guard: "hasShowTutorial",
2181
+ actions: "trackContinue"
2182
+ }, {
2183
+ target: "loading",
2184
+ actions: "trackContinue"
2185
+ }] } },
2186
+ loading: {
2187
+ entry: "preloadRecordingProvider",
2188
+ type: "parallel",
2189
+ states: {
2190
+ permissionCheck: {
2191
+ initial: "checking",
2192
+ states: {
2193
+ checking: { invoke: {
2194
+ id: "checkPermissionLoading",
2195
+ src: "checkPermission",
2196
+ onDone: {
2197
+ target: "done",
2198
+ actions: assign({ permissionResult: ({ event }) => event.output })
2199
+ },
2200
+ onError: {
2201
+ target: "done",
2202
+ actions: assign({ permissionResult: () => "prompt" })
2203
+ }
2204
+ } },
2205
+ done: { type: "final" }
2206
+ }
2207
+ },
2208
+ deepsightInit: {
2209
+ initial: "initializing",
2210
+ states: {
2211
+ initializing: { invoke: {
2212
+ id: "initDeepsightLoading",
2213
+ src: "initializeDeepsightSession",
2214
+ input: ({ context }) => ({
2215
+ ds: context.config.ds,
2216
+ dependencies: context.dependencies,
2217
+ disableIpify: context.disableIpify
2218
+ }),
2219
+ onDone: {
2220
+ target: "done",
2221
+ actions: assign({
2222
+ deepsightService: ({ event }) => event.output,
2223
+ deepsightInitAttempted: () => true
2224
+ })
2225
+ },
2226
+ onError: {
2227
+ target: "done",
2228
+ actions: [assign({ deepsightInitAttempted: () => true }), () => console.warn("Deepsight initialization failed")]
2229
+ }
2230
+ } },
2231
+ done: { type: "final" }
2232
+ }
2233
+ }
2234
+ },
2235
+ onDone: [{
2236
+ target: "capture",
2237
+ guard: "isPermissionGranted"
2238
+ }, { target: "permissions" }]
2239
+ },
2240
+ tutorial: {
2241
+ initial: "checkingPermission",
2242
+ entry: ["trackTutorialId", "preloadRecordingProvider"],
2243
+ states: {
2244
+ checkingPermission: {
2245
+ invoke: {
2246
+ id: "checkPermissionTutorial",
2247
+ src: "checkPermission",
2248
+ onDone: [{
2249
+ target: "initializingCamera",
2250
+ guard: "isPermissionGranted",
2251
+ actions: assign({ permissionResult: ({ event }) => event.output })
2252
+ }, {
2253
+ target: "ready",
2254
+ actions: assign({ permissionResult: ({ event }) => event.output })
2255
+ }]
2256
+ },
2257
+ on: { NEXT_STEP: {
2258
+ target: "#idCapture.capture",
2259
+ actions: "trackContinue"
2260
+ } }
2261
+ },
2262
+ initializingCamera: {
2263
+ type: "parallel",
2264
+ states: {
2265
+ cameraInit: {
2266
+ initial: "initializingDeepsight",
2267
+ states: {
2268
+ initializingDeepsight: { invoke: {
2269
+ id: "tutorialInitDeepsight",
2270
+ src: "initializeDeepsightSession",
2271
+ input: ({ context }) => ({
2272
+ ds: context.config.ds,
2273
+ dependencies: context.dependencies,
2274
+ disableIpify: context.disableIpify
2275
+ }),
2276
+ onDone: {
2277
+ target: "initializingStream",
2278
+ actions: assign({
2279
+ deepsightService: ({ event }) => event.output,
2280
+ deepsightInitAttempted: () => true
2281
+ })
2282
+ },
2283
+ onError: {
2284
+ target: "initializingStream",
2285
+ actions: [assign({ deepsightInitAttempted: () => true }), () => console.warn("Deepsight initialization failed in tutorial")]
2286
+ }
2287
+ } },
2288
+ initializingStream: { invoke: {
2289
+ id: "tutorialInitCamera",
2290
+ src: "initializeCamera",
2291
+ input: ({ context }) => ({
2292
+ config: context.config,
2293
+ deepsightService: context.deepsightService
2294
+ }),
2295
+ onDone: {
2296
+ target: "ready",
2297
+ actions: "setStreamAndCapturer"
2298
+ },
2299
+ onError: [{
2300
+ target: "#idCapture.tutorial.ready",
2301
+ guard: "isPermissionDeniedError",
2302
+ actions: assign({ permissionResult: () => {
2303
+ return "denied";
2304
+ } })
2305
+ }, {
2306
+ target: "#idCapture.tutorial.ready",
2307
+ actions: assign({ error: ({ event }) => String(event.error) })
2308
+ }]
2309
+ } },
2310
+ ready: { type: "final" }
2311
+ }
2312
+ },
2313
+ userIntent: {
2314
+ initial: "booting",
2315
+ states: {
2316
+ booting: { on: { NEXT_STEP: {
2317
+ target: "clicked",
2318
+ actions: "trackContinue"
2319
+ } } },
2320
+ clicked: { type: "final" }
2321
+ }
2322
+ }
2323
+ },
2324
+ onDone: { target: "#idCapture.capture" }
2325
+ },
2326
+ ready: { on: { NEXT_STEP: {
2327
+ target: "waitingForPermission",
2328
+ actions: "trackContinue"
2329
+ } } },
2330
+ waitingForPermission: { invoke: {
2331
+ id: "checkPermissionWaiting",
2332
+ src: "checkPermission",
2333
+ onDone: [{
2334
+ target: "#idCapture.capture",
2335
+ guard: "isPermissionGranted",
2336
+ actions: assign({ permissionResult: ({ event }) => event.output })
2337
+ }, {
2338
+ target: "#idCapture.permissions",
2339
+ actions: assign({ permissionResult: ({ event }) => event.output })
2340
+ }]
2341
+ } }
2342
+ }
2343
+ },
2344
+ permissions: {
2345
+ entry: "preloadRecordingProvider",
2346
+ initial: "idle",
2347
+ states: {
2348
+ idle: {
2349
+ invoke: {
2350
+ id: "checkPermissionIdle",
2351
+ src: "checkPermission",
2352
+ onDone: [
2353
+ {
2354
+ target: "#idCapture.capture",
2355
+ guard: "isPermissionGranted",
2356
+ actions: assign({ permissionResult: ({ event }) => event.output })
2357
+ },
2358
+ {
2359
+ target: "denied",
2360
+ guard: ({ event }) => event.output === "denied",
2361
+ actions: assign({ permissionResult: ({ event }) => event.output })
2362
+ },
2363
+ {
2364
+ target: "waitingForUser",
2365
+ actions: assign({ permissionResult: ({ event }) => event.output })
2366
+ }
2367
+ ],
2368
+ onError: {
2369
+ target: "waitingForUser",
2370
+ actions: assign({ permissionResult: () => "prompt" })
2371
+ }
2372
+ },
2373
+ on: {
2374
+ REQUEST_PERMISSION: "requesting",
2375
+ GO_TO_LEARN_MORE: "learnMore"
2376
+ }
2377
+ },
2378
+ waitingForUser: { on: {
2379
+ REQUEST_PERMISSION: "requesting",
2380
+ GO_TO_LEARN_MORE: "learnMore"
2381
+ } },
2382
+ learnMore: { on: {
2383
+ BACK: "idle",
2384
+ REQUEST_PERMISSION: "requesting"
2385
+ } },
2386
+ requesting: { invoke: {
2387
+ id: "requestPermission",
2388
+ src: "requestPermission",
2389
+ input: ({ context }) => ({ requestMotionPermission: context.config.ds === true }),
2390
+ onDone: [
2391
+ {
2392
+ target: "#idCapture.capture",
2393
+ guard: "isPermissionGranted",
2394
+ actions: assign({ permissionResult: ({ event }) => event.output })
2395
+ },
2396
+ {
2397
+ target: "denied",
2398
+ guard: ({ event }) => event.output === "denied",
2399
+ actions: assign({ permissionResult: ({ event }) => event.output })
2400
+ },
2401
+ {
2402
+ target: "idle",
2403
+ actions: assign({ permissionResult: ({ event }) => event.output })
2404
+ }
2405
+ ],
2406
+ onError: { target: "denied" }
2407
+ } },
2408
+ denied: { entry: assign({ permissionResult: () => "refresh" }) }
2409
+ }
2410
+ },
2411
+ capture: {
2412
+ initial: "checkingStream",
2413
+ entry: ["trackCameraId", "preloadRecordingProvider"],
2414
+ exit: ["stopMediaRecording", "clearRecordingSession"],
2415
+ on: { SET_FRAME_RECT: { actions: "setFrameRect" } },
2416
+ states: {
2417
+ checkingStream: { always: [
2418
+ {
2419
+ target: "initializingDeepsight",
2420
+ guard: "needsDeepsightInit"
2421
+ },
2422
+ {
2423
+ target: "detecting",
2424
+ guard: "hasStream"
2425
+ },
2426
+ { target: "initializing" }
2427
+ ] },
2428
+ initializingDeepsight: { invoke: {
2429
+ id: "initDeepsightCapture",
2430
+ src: "initializeDeepsightSession",
2431
+ input: ({ context }) => ({
2432
+ ds: context.config.ds,
2433
+ dependencies: context.dependencies,
2434
+ disableIpify: context.disableIpify
2435
+ }),
2436
+ onDone: {
2437
+ target: "checkingStream",
2438
+ actions: assign({
2439
+ deepsightService: ({ event }) => event.output,
2440
+ deepsightInitAttempted: () => true
2441
+ })
2442
+ },
2443
+ onError: {
2444
+ target: "checkingStream",
2445
+ actions: [assign({ deepsightInitAttempted: () => true }), () => console.warn("Deepsight initialization failed in capture")]
2446
+ }
2447
+ } },
2448
+ initializing: { invoke: {
2449
+ id: "initializeCamera",
2450
+ src: "initializeCamera",
2451
+ input: ({ context }) => ({
2452
+ config: context.config,
2453
+ deepsightService: context.deepsightService
2454
+ }),
2455
+ onDone: {
2456
+ target: "detecting",
2457
+ actions: "setStreamAndCapturer"
2458
+ },
2459
+ onError: [{
2460
+ target: "#idCapture.permissions",
2461
+ guard: "isPermissionDeniedError",
2462
+ actions: assign({ permissionResult: () => "denied" })
2463
+ }, {
2464
+ target: "#idCapture.error",
2465
+ actions: assign({ error: ({ event }) => String(event.error) })
2466
+ }]
2467
+ } },
2468
+ detecting: {
2469
+ always: [{
2470
+ target: "manualCaptureWaiting",
2471
+ guard: ({ context }) => context.manualCaptureTriggered,
2472
+ actions: assign({ detectionStatus: () => "manualCapture" })
2473
+ }],
2474
+ entry: [assign({ detectionStatus: () => "detecting" })],
2475
+ invoke: [{
2476
+ id: "startRecording",
2477
+ src: "startRecording",
2478
+ input: ({ context }) => ({
2479
+ config: context.config,
2480
+ stream: context.stream,
2481
+ existing: context.recordingSession,
2482
+ currentMode: context.currentMode
2483
+ }),
2484
+ onDone: { actions: assign({ recordingSession: ({ context, event }) => {
2485
+ return event.output ?? context.recordingSession;
2486
+ } }) },
2487
+ onError: { actions: () => void 0 }
2488
+ }, {
2489
+ id: "runDetection",
2490
+ src: "runDetection",
2491
+ input: ({ context }) => ({
2492
+ frameCapturer: context.frameCapturer,
2493
+ provider: context.provider,
2494
+ config: context.config,
2495
+ currentMode: context.currentMode,
2496
+ detectionArea: context.detectionArea ?? context.config.detectionArea
2497
+ })
2498
+ }],
2499
+ on: {
2500
+ DETECTION_UPDATE: { actions: "setDetectionStatus" },
2501
+ DETECTION_FRAME: { actions: assign({ debugFrame: ({ event }) => event.frame }) },
2502
+ DETECTION_RESET_READY: { actions: assign({ resetDetection: ({ event }) => event.reset }) },
2503
+ DETECTION_SUCCESS: {
2504
+ target: "capturing",
2505
+ actions: assign({ qualityElements: ({ event }) => event.qualityElements })
2506
+ },
2507
+ MANUAL_CAPTURE: { target: "capturingManual" },
2508
+ SWITCH_TO_MANUAL_CAPTURE: {
2509
+ target: "manualCaptureWaiting",
2510
+ actions: assign({
2511
+ detectionStatus: () => "manualCapture",
2512
+ manualCaptureTriggered: () => true
2513
+ })
2514
+ },
2515
+ COUNTER_VALUE_CHANGE: { actions: "setCounterValue" },
2516
+ ID_TYPE_CHANGE: { actions: "setIdType" },
2517
+ ID_SIDE_CHANGE: { actions: assign({ detectionStatus: ({ event, context }) => getDetectionStatusFromSideChange(context, event.side) }) },
2518
+ ORIENTATION_CHANGE: { actions: "setOrientation" }
2519
+ }
2520
+ },
2521
+ manualCaptureWaiting: { on: { MANUAL_CAPTURE: { target: "capturingManual" } } },
2522
+ capturing: {
2523
+ entry: [
2524
+ "captureImage",
2525
+ "storeCapturedCanvasInProvider",
2526
+ "storeCapturedImage"
2527
+ ],
2528
+ always: [{
2529
+ target: "uploading",
2530
+ guard: "hasCapturedImage"
2531
+ }, {
2532
+ target: "uploadError",
2533
+ actions: assign(({ context }) => ({
2534
+ uploadError: ID_ERROR_CODES.UPLOAD_ERROR,
2535
+ attemptsRemaining: context.attemptsRemaining - 1
2536
+ }))
2537
+ }]
2538
+ },
2539
+ capturingManual: {
2540
+ entry: [
2541
+ "captureLatestFrame",
2542
+ "storeCapturedCanvasInProvider",
2543
+ "storeCapturedImage"
2544
+ ],
2545
+ always: [{
2546
+ target: "uploading",
2547
+ guard: "hasCapturedImage"
2548
+ }, {
2549
+ target: "uploadError",
2550
+ actions: assign(({ context }) => ({
2551
+ uploadError: ID_ERROR_CODES.UPLOAD_ERROR,
2552
+ attemptsRemaining: context.attemptsRemaining - 1
2553
+ }))
2554
+ }]
2555
+ },
2556
+ uploading: {
2557
+ entry: assign({ uploadProgress: () => 0 }),
2558
+ invoke: {
2559
+ id: "uploadIdImage",
2560
+ src: "uploadIdImage",
2561
+ input: ({ context, self }) => {
2562
+ const canvas = context.provider?.getOriginalCapturedCanvas();
2563
+ if (!canvas) throw new Error(ID_ERROR_CODES.UPLOAD_ERROR);
2564
+ return {
2565
+ canvas,
2566
+ type: context.currentMode === "back" ? "back" : "front",
2567
+ qualityElements: context.qualityElements,
2568
+ onProgress: (progress) => {
2569
+ self.send({
2570
+ type: "UPLOAD_PROGRESS",
2571
+ progress
2572
+ });
2573
+ },
2574
+ deepsightService: context.deepsightService,
2575
+ stream: context.stream,
2576
+ isSecondId: context.config.isSecondId ?? false,
2577
+ onlyFront: false,
2578
+ ageAssurance: context.config.ageAssurance,
2579
+ dependencies: context.dependencies,
2580
+ captureResolution: context.captureResolution,
2581
+ cameraFallbackLevel: context.cameraFallbackLevel,
2582
+ croppedCanvas: context.provider?.getCapturedCanvas() ?? null
2583
+ };
2584
+ },
2585
+ onDone: {
2586
+ target: "validatingUpload",
2587
+ actions: [assign({
2588
+ uploadResponse: ({ event }) => event.output,
2589
+ uploadProgress: () => 100
2590
+ }), "storeCapturedImage"]
2591
+ },
2592
+ onError: {
2593
+ target: "uploadError",
2594
+ actions: assign(({ context, event }) => ({
2595
+ uploadError: getIdErrorCodeFromUnknown(event.error) ?? ID_ERROR_CODES.UPLOAD_ERROR,
2596
+ attemptsRemaining: context.attemptsRemaining - 1
2597
+ }))
2598
+ }
2599
+ },
2600
+ on: { UPLOAD_PROGRESS: { actions: assign({ uploadProgress: ({ event }) => event.progress }) } }
2601
+ },
2602
+ validatingUpload: { always: [
2603
+ {
2604
+ target: "uploadError",
2605
+ guard: "hasUploadValidationError",
2606
+ actions: ["setUploadErrorFromUploadValidation", "decrementAttemptsRemaining"]
2607
+ },
2608
+ {
2609
+ target: "#idCapture.finished",
2610
+ guard: and(["shouldSkipProcessId", "isUploadExpired"])
2611
+ },
2612
+ {
2613
+ target: "#idCapture.expiredExhausted",
2614
+ guard: and([
2615
+ "isNotPassportMode",
2616
+ "isUploadExpired",
2617
+ "isExpiredAttemptsExhausted"
2618
+ ]),
2619
+ actions: ["incrementExpiredAttempts", "setExhaustedFromUpload"]
2620
+ },
2621
+ {
2622
+ target: "#idCapture.expired",
2623
+ guard: and(["isNotPassportMode", "isUploadExpired"]),
2624
+ actions: ["incrementExpiredAttempts", "setExpiredFromUpload"]
2625
+ },
2626
+ { target: "success" }
2627
+ ] },
2628
+ uploadError: { on: { CONTINUE_FROM_ERROR: [
2629
+ {
2630
+ target: "checkingStream",
2631
+ guard: "hasAttemptsRemaining",
2632
+ actions: [
2633
+ "resetDetection",
2634
+ "clearUploadFailure",
2635
+ "clearStreamForRetry"
2636
+ ]
2637
+ },
2638
+ {
2639
+ target: "#idCapture.frontFinished",
2640
+ guard: "shouldContinueToBack",
2641
+ actions: ["flagIdManualReview"]
2642
+ },
2643
+ {
2644
+ target: "#idCapture.backFinished",
2645
+ guard: "shouldContinueToFront",
2646
+ actions: ["flagIdManualReview"]
2647
+ },
2648
+ {
2649
+ target: "#idCapture.processing",
2650
+ actions: ["flagIdManualReview"]
2651
+ }
2652
+ ] } },
2653
+ success: { on: { NEXT_STEP: [
2654
+ {
2655
+ target: "#idCapture.mandatoryConsent",
2656
+ guard: "hasMandatoryConsent"
2657
+ },
2658
+ {
2659
+ target: "#idCapture.frontFinished",
2660
+ guard: "shouldContinueToBack"
2661
+ },
2662
+ {
2663
+ target: "#idCapture.backFinished",
2664
+ guard: "shouldContinueToFront"
2665
+ },
2666
+ { target: "#idCapture.processing" }
2667
+ ] } }
2668
+ }
2669
+ },
2670
+ mandatoryConsent: { on: {
2671
+ CONSENT_ACCEPT: [
2672
+ {
2673
+ target: "frontFinished",
2674
+ guard: "shouldContinueToBack"
2675
+ },
2676
+ {
2677
+ target: "backFinished",
2678
+ guard: "shouldContinueToFront"
2679
+ },
2680
+ { target: "processing" }
2681
+ ],
2682
+ CONSENT_CANCEL: { target: "closed" }
2683
+ } },
2684
+ frontFinished: {
2685
+ entry: ["stopMediaRecording", "resetForBackCapture"],
2686
+ type: "parallel",
2687
+ states: {
2688
+ cameraInit: {
2689
+ initial: "checking",
2690
+ states: {
2691
+ checking: { always: [{
2692
+ target: "ready",
2693
+ guard: "hasStream"
2694
+ }, { target: "initializingStream" }] },
2695
+ initializingStream: { invoke: {
2696
+ id: "frontFinishedInitCamera",
2697
+ src: "initializeCamera",
2698
+ input: ({ context }) => ({
2699
+ config: context.config,
2700
+ deepsightService: context.deepsightService
2701
+ }),
2702
+ onDone: {
2703
+ target: "ready",
2704
+ actions: "setStreamAndCapturer"
2705
+ },
2706
+ onError: {
2707
+ target: "ready",
2708
+ actions: () => {
2709
+ console.warn("Camera initialization failed during flip transition");
2710
+ }
2711
+ }
2712
+ } },
2713
+ ready: { type: "final" }
2714
+ }
2715
+ },
2716
+ userIntent: {
2717
+ initial: "waiting",
2718
+ states: {
2719
+ waiting: { on: { CONTINUE_TO_BACK: {
2720
+ target: "clicked",
2721
+ actions: assign({ currentMode: () => "back" })
2722
+ } } },
2723
+ clicked: { type: "final" }
2724
+ }
2725
+ }
2726
+ },
2727
+ onDone: [{
2728
+ target: "#idCapture.capture.detecting",
2729
+ guard: "hasStream"
2730
+ }, { target: "#idCapture.capture" }]
2731
+ },
2732
+ backFinished: {
2733
+ entry: ["stopMediaRecording", "resetForFrontCapture"],
2734
+ type: "parallel",
2735
+ states: {
2736
+ cameraInit: {
2737
+ initial: "checking",
2738
+ states: {
2739
+ checking: { always: [{
2740
+ target: "ready",
2741
+ guard: "hasStream"
2742
+ }, { target: "initializingStream" }] },
2743
+ initializingStream: { invoke: {
2744
+ id: "backFinishedInitCamera",
2745
+ src: "initializeCamera",
2746
+ input: ({ context }) => ({
2747
+ config: context.config,
2748
+ deepsightService: context.deepsightService
2749
+ }),
2750
+ onDone: {
2751
+ target: "ready",
2752
+ actions: "setStreamAndCapturer"
2753
+ },
2754
+ onError: {
2755
+ target: "ready",
2756
+ actions: () => {
2757
+ console.warn("Camera initialization failed during flip transition");
2758
+ }
2759
+ }
2760
+ } },
2761
+ ready: { type: "final" }
2762
+ }
2763
+ },
2764
+ userIntent: {
2765
+ initial: "waiting",
2766
+ states: {
2767
+ waiting: { on: { CONTINUE_TO_FRONT: {
2768
+ target: "clicked",
2769
+ actions: assign({ currentMode: () => "front" })
2770
+ } } },
2771
+ clicked: { type: "final" }
2772
+ }
2773
+ }
2774
+ },
2775
+ onDone: [{
2776
+ target: "#idCapture.capture.detecting",
2777
+ guard: "hasStream"
2778
+ }, { target: "#idCapture.capture" }]
2779
+ },
2780
+ processing: {
2781
+ entry: "stopMediaStream",
2782
+ always: [{
2783
+ target: "finished",
2784
+ guard: "shouldSkipProcessId"
2785
+ }],
2786
+ invoke: {
2787
+ id: "processId",
2788
+ src: "processId",
2789
+ input: ({ context }) => ({ isSecondId: context.config.isSecondId ?? false }),
2790
+ onDone: [
2791
+ {
2792
+ target: "finished",
2793
+ guard: "forceFinishAfterProcessing"
2794
+ },
2795
+ {
2796
+ target: "expiredExhausted",
2797
+ guard: and([({ event }) => event.output.isDocumentExpired, "isProcessingExpiredExhausted"]),
2798
+ actions: ["incrementProcessingExpiredAttempts"]
2799
+ },
2800
+ {
2801
+ target: "expired",
2802
+ guard: ({ event }) => event.output.isDocumentExpired,
2803
+ actions: ["incrementProcessingExpiredAttempts", "clearExpiredFromUpload"]
2804
+ },
2805
+ { target: "finished" }
2806
+ ],
2807
+ onError: { target: "finished" }
2808
+ }
2809
+ },
2810
+ expired: { on: { RETRY_CAPTURE: [
2811
+ {
2812
+ target: "#idCapture.capture",
2813
+ guard: "wasExpiredFromUpload",
2814
+ actions: [
2815
+ "resetDetection",
2816
+ "clearExpiredFromUpload",
2817
+ "clearUploadFailure"
2818
+ ]
2819
+ },
2820
+ {
2821
+ target: "chooser",
2822
+ guard: "hasShowDocumentChooser",
2823
+ actions: ["resetContext"]
2824
+ },
2825
+ {
2826
+ target: "ageVerification",
2827
+ guard: "hasAgeAssurance",
2828
+ actions: "resetContext"
2829
+ },
2830
+ {
2831
+ target: "tutorial",
2832
+ guard: "hasShowTutorial",
2833
+ actions: "resetContext"
2834
+ },
2835
+ {
2836
+ target: "loading",
2837
+ actions: "resetContext"
2838
+ }
2839
+ ] } },
2840
+ expiredExhausted: { on: { CONTINUE_EXHAUSTED: [
2841
+ {
2842
+ target: "#idCapture.frontFinished",
2843
+ guard: "shouldForceBackOnExpired",
2844
+ actions: ["setSkipProcessId"]
2845
+ },
2846
+ {
2847
+ target: "#idCapture.processing",
2848
+ guard: "shouldProcessAfterExhaustion",
2849
+ actions: ["setForceFinishAfterProcessing"]
2850
+ },
2851
+ {
2852
+ target: "#idCapture.finished",
2853
+ actions: ["setSkipProcessId"]
2854
+ }
2855
+ ] } },
2856
+ finished: {
2857
+ entry: [
2858
+ "stopMediaRecording",
2859
+ "stopMediaStream",
2860
+ "disposeProvider",
2861
+ "cleanupDeepsight"
2862
+ ],
2863
+ type: "final"
2864
+ },
2865
+ closed: {
2866
+ entry: [
2867
+ "stopMediaStream",
2868
+ "disposeProvider",
2869
+ "cleanupDeepsight"
2870
+ ],
2871
+ type: "final"
2872
+ },
2873
+ error: {
2874
+ entry: [
2875
+ "stopMediaStream",
2876
+ "disposeProvider",
2877
+ "cleanupDeepsight"
2878
+ ],
2879
+ on: { RESET: {
2880
+ target: "idle",
2881
+ actions: "resetContext"
2882
+ } }
2883
+ },
2884
+ manualIdUpload: {
2885
+ invoke: {
2886
+ id: "manualIdUpload",
2887
+ src: "manualUploadMachine",
2888
+ input: ({ context }) => ({
2889
+ isSecondId: context.config.isSecondId ?? false,
2890
+ onlyFront: false,
2891
+ captureAttempts: context.config.captureAttempts
2892
+ }),
2893
+ onSnapshot: { actions: () => {} },
2894
+ onDone: [{
2895
+ guard: "isManualUploadExhausted",
2896
+ target: "#idCapture.finished"
2897
+ }, { target: "#idCapture.processing" }],
2898
+ onError: {
2899
+ target: "#idCapture.error",
2900
+ actions: assign({ error: ({ event }) => String(event.error) })
2901
+ }
2902
+ },
2903
+ on: {
2904
+ QUIT: { target: "closed" },
2905
+ MANUAL_UPLOAD_TAB_CHANGED: { actions: sendTo("manualIdUpload", ({ event }) => event) },
2906
+ MANUAL_UPLOAD_FILE_SELECTED: { actions: sendTo("manualIdUpload", ({ event }) => event) },
2907
+ MANUAL_UPLOAD_CONTINUE: { actions: sendTo("manualIdUpload", ({ event }) => event) },
2908
+ MANUAL_UPLOAD_RESET: { actions: sendTo("manualIdUpload", ({ event }) => event) }
2909
+ }
2910
+ },
2911
+ digitalIdUpload: {
2912
+ invoke: {
2913
+ id: "digitalIdUpload",
2914
+ src: "digitalUploadMachine",
2915
+ input: ({ context }) => ({
2916
+ showTutorial: context.config.showTutorial,
2917
+ captureAttempts: context.config.captureAttempts
2918
+ }),
2919
+ onSnapshot: { actions: () => {} },
2920
+ onDone: [
2921
+ {
2922
+ guard: "isDigitalUploadExhausted",
2923
+ target: "#idCapture.finished"
2924
+ },
2925
+ {
2926
+ guard: "isDigitalUploadClosed",
2927
+ target: "#idCapture.chooser"
2928
+ },
2929
+ {
2930
+ guard: "isDigitalUploadSuccessful",
2931
+ target: "#idCapture.processing",
2932
+ actions: ["storeDigitalUploadResponse"]
2933
+ },
2934
+ {
2935
+ target: "#idCapture.error",
2936
+ actions: assign({ error: () => "Digital upload finished without output" })
2937
+ }
2938
+ ],
2939
+ onError: {
2940
+ target: "#idCapture.error",
2941
+ actions: assign({ error: ({ event }) => String(event.error) })
2942
+ }
2943
+ },
2944
+ on: {
2945
+ QUIT: { target: "closed" },
2946
+ DIGITAL_UPLOAD_NEXT_STEP: { actions: sendTo("digitalIdUpload", { type: "NEXT_STEP" }) },
2947
+ DIGITAL_UPLOAD_FILE_PICKED: { actions: sendTo("digitalIdUpload", ({ event }) => ({
2948
+ type: "FILE_PICKED",
2949
+ file: event.file
2950
+ })) },
2951
+ DIGITAL_UPLOAD_CONFIRM: { actions: sendTo("digitalIdUpload", { type: "CONFIRM" }) },
2952
+ DIGITAL_UPLOAD_REPLACE: { actions: sendTo("digitalIdUpload", { type: "REPLACE" }) },
2953
+ DIGITAL_UPLOAD_RETRY: { actions: sendTo("digitalIdUpload", { type: "RETRY" }) },
2954
+ DIGITAL_UPLOAD_SCAN_INSTEAD: { actions: sendTo("digitalIdUpload", { type: "SCAN_INSTEAD" }) },
2955
+ DIGITAL_UPLOAD_CHOOSE_ANOTHER: { actions: sendTo("digitalIdUpload", { type: "CHOOSE_ANOTHER" }) }
2956
+ }
2957
+ }
2958
+ }
2959
+ });
2960
+ const idCaptureMachine = _idCaptureMachine;
2961
+
2962
+ //#endregion
2963
+ export { startRecordingSession as a, uploadIdImage as c, ID_ERROR_CODES as d, MANUAL_UPLOAD_EXHAUSTION_FORWARD_MS as f, mapDigitalIdScreenName as h, processId as i, uploadManualIdFile as l, MANUAL_UPLOAD_MAX_RETRIES as m, initializeIdCapture as n, stopRecording as o, MANUAL_UPLOAD_MAX_FILE_SIZE_BYTES as p, preloadIdRecordingProvider as r, stopStream as s, idCaptureMachine as t, validateUploadResponse as u };