@incodetech/core 2.4.0 → 2.4.1-agentic.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/dist/BrowserNetworkStatusProvider-BrDXBEDd.esm.js +21 -0
  2. package/dist/{multipartRecordingService-CLwrF5wD.esm.js → CameraCompositor-DN7NkJzV.esm.js} +7 -744
  3. package/dist/{FaceDetectionProvider-DcPOC2gS.esm.js → FaceDetectionProvider-CAY43vSI.esm.js} +28 -64
  4. package/dist/IBrowserEnvironmentCapability-D7JG7ML3.esm.js +16 -0
  5. package/dist/IGeolocationCapability-r49Qo7rR.d.ts +10 -0
  6. package/dist/{IWasmUtilCapability-GF2n7sfm.d.ts → IWasmUtilCapability-Cqiaxydi.d.ts} +31 -4
  7. package/dist/MultipartRecordingProvider-D9mauUdS.esm.js +146 -0
  8. package/dist/{PhoneValidationProvider-SZiOS0jB.esm.js → PhoneValidationProvider-Co4zk2en.esm.js} +7 -0
  9. package/dist/{StreamCanvasCapture-7JRf-2ck.d.ts → StreamCanvasCapture-C3xNfOsv.d.ts} +12 -3
  10. package/dist/StreamCanvasProcessingSession-CBnbTnOr.esm.js +42 -0
  11. package/dist/{WasmUtilProvider-DtJuBdt-.esm.js → WasmUtilProvider-Dp2V-Uct.esm.js} +75 -22
  12. package/dist/WorkerEncoderRecordingProvider-B1ODYtgN.esm.js +80 -0
  13. package/dist/addressSearch-DzbE9Ogt.esm.js +254 -0
  14. package/dist/{advanceableErrors-q_pfU3Cn.esm.js → advanceableErrors-k-U-cL5m.esm.js} +1 -2
  15. package/dist/ae-signature.esm.js +1 -1
  16. package/dist/antifraud.esm.js +2 -2
  17. package/dist/{antifraudManager-CaweCYnY.esm.js → antifraudManager-BObuHBjn.esm.js} +2 -2
  18. package/dist/{antifraudStateMachine-DRl0UVyA.esm.js → antifraudStateMachine-Dfrd2-26.esm.js} +1 -1
  19. package/dist/{api-Cz90EHyu.esm.js → api-CpP4PS4S.esm.js} +8 -5
  20. package/dist/{apiError-DPwFas2f.esm.js → apiError-DH-CH4Nz.esm.js} +1 -1
  21. package/dist/attemptCarry-WOkfvFMw.esm.js +45 -0
  22. package/dist/authentication.d.ts +3 -3
  23. package/dist/authentication.esm.js +2 -2
  24. package/dist/{authenticationManager-BIZC55Bi.d.ts → authenticationManager-CWmh7aSY.d.ts} +1 -1
  25. package/dist/{authenticationManager-2Lr5V_7p.esm.js → authenticationManager-DjX0XDyH.esm.js} +5 -5
  26. package/dist/{authenticationStateMachine-C99B0GFP.esm.js → authenticationStateMachine-BMbZL8wm.esm.js} +3 -3
  27. package/dist/backCameraLabel-yda5ugE4.esm.js +67 -0
  28. package/dist/{backCameraStream-CMvXj4X4.esm.js → backCameraStream-DS1oDiUq.esm.js} +12 -107
  29. package/dist/{browser-DlFgHpoC-DnyrCR8r.esm.js → browser-pQZA35G2-DtkAf6sn.esm.js} +161 -150
  30. package/dist/{camera-sIa9ceW2.esm.js → camera-E_Kcre4O.esm.js} +15 -23
  31. package/dist/camera.d.ts +2 -2
  32. package/dist/camera.esm.js +1 -1
  33. package/dist/certificate-issuance.esm.js +2 -2
  34. package/dist/{certificateIssuanceManager-BfeMv2PU.esm.js → certificateIssuanceManager-C1nETQos.esm.js} +2 -2
  35. package/dist/{certificateIssuanceStateMachine-Frgjbjw8.esm.js → certificateIssuanceStateMachine-DThXMDqr.esm.js} +2 -2
  36. package/dist/cnpj-Co1ottYN.esm.js +77 -0
  37. package/dist/connectivity-BCuEoQ-n.esm.js +114 -0
  38. package/dist/consent.d.ts +1 -1
  39. package/dist/consent.esm.js +2 -2
  40. package/dist/{consentManager-CvEu8h_W.esm.js → consentManager-DMlSL6Ax.esm.js} +4 -3
  41. package/dist/{consentManager-Cv_0QKLD.d.ts → consentManager-bjfVXO7p.d.ts} +9 -2
  42. package/dist/{consentStateMachine-DJTgN_-1.esm.js → consentStateMachine-DIYSMxKQ.esm.js} +20 -7
  43. package/dist/cross-document-data-match.esm.js +1 -1
  44. package/dist/{crossDocumentDataMatchManager-Cu141CE8.esm.js → crossDocumentDataMatchManager-BFTdiEDB.esm.js} +2 -2
  45. package/dist/curp-validation.d.ts +1 -1
  46. package/dist/curp-validation.esm.js +2 -2
  47. package/dist/{curpValidationManager-B-z9q5V3.esm.js → curpValidationManager-DNpC3wyf.esm.js} +3 -2
  48. package/dist/{curpValidationManager-C9sqoh9n.d.ts → curpValidationManager-z8428oCM.d.ts} +1 -1
  49. package/dist/{curpValidationStateMachine-vDEFLMPw.esm.js → curpValidationStateMachine-B3iVsDyt.esm.js} +28 -20
  50. package/dist/custom-fields.esm.js +1 -1
  51. package/dist/custom-watchlist.esm.js +2 -2
  52. package/dist/{customFieldsManager-D1ex2cFM.esm.js → customFieldsManager-CvI-pDT3.esm.js} +2 -2
  53. package/dist/{customWatchlistManager-CTI-SGk0.esm.js → customWatchlistManager-BuHtUb0y.esm.js} +2 -2
  54. package/dist/{customWatchlistStateMachine-hmRd0f2I.esm.js → customWatchlistStateMachine-CiVD9wyF.esm.js} +1 -1
  55. package/dist/{deepsightService-CKTYDIXD.esm.js → deepsightLoader-B7DEYoyY.esm.js} +40 -74
  56. package/dist/{createCameraCycleOwnership-Dj_LHUvN.esm.js → desktopCameraElection-BGMtYwk3.esm.js} +177 -40
  57. package/dist/device.esm.js +2 -2
  58. package/dist/document-capture.d.ts +3 -3
  59. package/dist/document-capture.esm.js +2 -2
  60. package/dist/{documentCaptureManager-DkyDtm3Y.d.ts → documentCaptureManager-CD5iQiUI.d.ts} +37 -4
  61. package/dist/{documentCaptureManager-DUJwpKC5.esm.js → documentCaptureManager-DLPqruXJ.esm.js} +27 -19
  62. package/dist/{documentCaptureStateMachine-B8i7GnLh.esm.js → documentCaptureStateMachine-DCvWQhFG.esm.js} +105 -56
  63. package/dist/dynamic-forms.d.ts +2 -2
  64. package/dist/dynamic-forms.esm.js +2 -2
  65. package/dist/{dynamicFormsManager-C0dHs1ty.d.ts → dynamicFormsManager-9kwY8Bf5.d.ts} +1 -1
  66. package/dist/{dynamicFormsManager-DiKYjcF3.esm.js → dynamicFormsManager-DfqCEPg9.esm.js} +2 -2
  67. package/dist/{dynamicFormsStateMachine-DEI45xYW.esm.js → dynamicFormsStateMachine-USQMB-uV.esm.js} +2 -2
  68. package/dist/ekyb.d.ts +4 -4
  69. package/dist/ekyb.esm.js +3 -3
  70. package/dist/{ekybManager-BaZ_7CEu.d.ts → ekybManager-BLOkwmWO.d.ts} +2 -2
  71. package/dist/{ekybManager-8WLkNcqg.esm.js → ekybManager-CR8YSYux.esm.js} +2 -2
  72. package/dist/{ekybStateMachine-BLRT45Ex.esm.js → ekybStateMachine-kHwdz6hm.esm.js} +28 -44
  73. package/dist/ekybUtils-Cw8Ta9Qi.esm.js +140 -0
  74. package/dist/ekyc.d.ts +4 -3
  75. package/dist/ekyc.esm.js +3 -3
  76. package/dist/{ekycManager-DW-ynodd.d.ts → ekycManager-DlGIn9wA.d.ts} +2 -1
  77. package/dist/{ekycManager-BO-Lui3t.esm.js → ekycManager-DymCvmVB.esm.js} +2 -2
  78. package/dist/ekycStateMachine-CoFCUJ2z.esm.js +7578 -0
  79. package/dist/ekycUtils-GRuMELYr.esm.js +1472 -0
  80. package/dist/electronic-signature.esm.js +1 -1
  81. package/dist/{electronicSignatureManager-CcIMOb_Y.esm.js → electronicSignatureManager-BCE3uA3z.esm.js} +4 -4
  82. package/dist/email.esm.js +2 -2
  83. package/dist/{emailManager-ButFktRm.esm.js → emailManager-CGoE3CUe.esm.js} +2 -2
  84. package/dist/{emailStateMachine-BXtlC0NV.esm.js → emailStateMachine-KgHfDNvM.esm.js} +32 -20
  85. package/dist/{events-Du2A4-Qr.esm.js → events-ggpBBaZ8.esm.js} +2 -2
  86. package/dist/events.esm.js +1 -1
  87. package/dist/extensibility.d.ts +37 -22
  88. package/dist/extensibility.esm.js +36 -35
  89. package/dist/{externalFetch-DrR9xshk.esm.js → externalFetch-CQY41QT1.esm.js} +4 -1
  90. package/dist/face-match.d.ts +1 -1
  91. package/dist/face-match.esm.js +2 -2
  92. package/dist/{faceCaptureManagerFactory-1hzeS_rB.d.ts → faceCaptureManagerFactory-DV2ULUYS.d.ts} +71 -66
  93. package/dist/{faceCaptureManagerFactory-BlGvXzXA.esm.js → faceCaptureManagerFactory-Dp90bedH.esm.js} +4 -4
  94. package/dist/{faceCaptureSetup-TY8RXc2N.esm.js → faceCaptureSetup-ZfiWg0fo.esm.js} +84 -457
  95. package/dist/{faceMatchManager-DWFUQjMQ.esm.js → faceMatchManager-D2xKPjjQ.esm.js} +2 -2
  96. package/dist/{faceMatchManager-DIgG-UFS.d.ts → faceMatchManager-Z4UDLwAv.d.ts} +16 -7
  97. package/dist/{faceMatchStateMachine-CUCvlydD.esm.js → faceMatchStateMachine-CUvwiQi9.esm.js} +40 -27
  98. package/dist/{feature-management-B5rR10uS.esm.js → feature-management-BbCIA4og.esm.js} +35 -21
  99. package/dist/feature-management.esm.js +1 -1
  100. package/dist/field-comparison.esm.js +1 -1
  101. package/dist/{fieldComparisonManager-v3knTYV_.esm.js → fieldComparisonManager-DgDbEeFZ.esm.js} +2 -2
  102. package/dist/fiscal-qr.esm.js +1 -1
  103. package/dist/{fiscalQrManager-Dt9fHG7h.esm.js → fiscalQrManager-BZeklojR.esm.js} +4 -4
  104. package/dist/flow-events.d.ts +1 -1
  105. package/dist/flow.d.ts +10 -10
  106. package/dist/flow.esm.js +10 -9
  107. package/dist/{flowCompletionService-BDI5QpfR.esm.js → flowCompletionService-CcCnPs_T.esm.js} +2 -2
  108. package/dist/{flowServices-roD0oIQL.esm.js → flowServices-Dmnc8Rye.esm.js} +69 -185
  109. package/dist/geolocation.d.ts +1 -1
  110. package/dist/geolocation.esm.js +2 -2
  111. package/dist/{geolocationManager-Dn24g1fl.d.ts → geolocationManager-6e1i9UIR.d.ts} +15 -17
  112. package/dist/{geolocationManager-DnONzWL5.esm.js → geolocationManager-BJJ3m_I8.esm.js} +6 -8
  113. package/dist/{geolocationStateMachine-eWy_G4Os.esm.js → geolocationStateMachine-CTI3m4Ie.esm.js} +12 -8
  114. package/dist/{getDeviceClass-bsWdEDxP.esm.js → getDeviceClass-DoIWuKI8.esm.js} +1 -1
  115. package/dist/government-validation.esm.js +2 -2
  116. package/dist/{governmentValidationManager-BtXWHICu.esm.js → governmentValidationManager-CjChjZ3C.esm.js} +2 -2
  117. package/dist/{governmentValidationStateMachine-COL-Vs48.esm.js → governmentValidationStateMachine-AEbn3Afi.esm.js} +1 -1
  118. package/dist/home.d.ts +1 -1
  119. package/dist/home.esm.js +1 -1
  120. package/dist/http.esm.js +1 -1
  121. package/dist/id-ocr.d.ts +1 -1
  122. package/dist/id-ocr.esm.js +2 -2
  123. package/dist/id-selfie-flow.d.ts +1 -1
  124. package/dist/id-selfie-flow.esm.js +10 -9
  125. package/dist/id-verification.esm.js +2 -2
  126. package/dist/id.d.ts +3 -16
  127. package/dist/id.esm.js +4 -4
  128. package/dist/{idCaptureDefaults-BGsG2OAs.esm.js → idCaptureDefaults-Dszuq9ng.esm.js} +3 -3
  129. package/dist/{idCaptureManager-BrfYjCm_.esm.js → idCaptureManager-B3oR4RnA.esm.js} +64 -17
  130. package/dist/{idCaptureManager-0M02hSuC.d.ts → idCaptureManager-CCA2D1Ah.d.ts} +68 -5
  131. package/dist/{idCaptureServices-BSj6EH2l.esm.js → idCaptureServices-DK0QboqT.esm.js} +29 -198
  132. package/dist/{idCaptureStateMachine-dXKBYHQp.esm.js → idCaptureStateMachine-zzar9MPy.esm.js} +914 -536
  133. package/dist/{idOcrManager-DT3kPIB3.d.ts → idOcrManager-BTdHlJ9D.d.ts} +1 -1
  134. package/dist/{idOcrManager-D3-HNMXP.esm.js → idOcrManager-xyEZNOBa.esm.js} +2 -2
  135. package/dist/{idOcrStateMachine-DyENX6Ki.esm.js → idOcrStateMachine-DNKXh4Rn.esm.js} +2 -2
  136. package/dist/{idVerificationManager-iWz7Avkr.esm.js → idVerificationManager-DdnvYfgN.esm.js} +2 -2
  137. package/dist/{idVerificationStateMachine-CL1kUdBe.esm.js → idVerificationStateMachine-DtIBCa32.esm.js} +1 -1
  138. package/dist/identity-reuse.esm.js +2 -2
  139. package/dist/{identityReuseManager-CD1ucp1d.esm.js → identityReuseManager-CcpovlfD.esm.js} +2 -2
  140. package/dist/{identityReuseStateMachine-DfV81wQC.esm.js → identityReuseStateMachine-DxZFWy47.esm.js} +1 -1
  141. package/dist/{index-CKQ9QBZP.d.ts → index-DC0P2Vzw.d.ts} +1 -1
  142. package/dist/{index-BKOWUhxG.d.ts → index-DEfwds5y.d.ts} +55 -8
  143. package/dist/index.d.ts +1 -1
  144. package/dist/index.esm.js +1 -1
  145. package/dist/{invokeOnCaptureCallback-DYrkOXO6.esm.js → invokeOnCaptureCallback-BJ0GVHGr.esm.js} +1 -1
  146. package/dist/kyb-checks.d.ts +3 -0
  147. package/dist/kyb-checks.esm.js +3 -0
  148. package/dist/kybChecksManager-CblEL97E.d.ts +95 -0
  149. package/dist/kybChecksManager-DpGOp4Su.esm.js +89 -0
  150. package/dist/kybChecksStateMachine-B43NAnv7.esm.js +718 -0
  151. package/dist/mandatory-consent.d.ts +2 -2
  152. package/dist/mandatory-consent.esm.js +2 -2
  153. package/dist/{mandatoryConsentManager-Cwqx1nK7.esm.js → mandatoryConsentManager-B4vCYslr.esm.js} +4 -3
  154. package/dist/{mandatoryConsentManager-BQ43yndC.d.ts → mandatoryConsentManager-B88Sm5nd.d.ts} +10 -3
  155. package/dist/{mandatoryConsentStateMachine-pXWqAHo_.esm.js → mandatoryConsentStateMachine-DWslYPA3.esm.js} +20 -7
  156. package/dist/mediaRecorderOptions-B9-IEVtV.esm.js +70 -0
  157. package/dist/multipartRecordingService-BTqkHGG9.esm.js +407 -0
  158. package/dist/nationalIds-B91f_RuB.esm.js +99 -0
  159. package/dist/{permissionGuards-gcy3U0SL.esm.js → permissionGuards-DFV-Ws0a.esm.js} +1 -1
  160. package/dist/{permissionServices-Ca-tSNhT.esm.js → permissionServices-D190ATGD.esm.js} +11 -9
  161. package/dist/phone-number.d.ts +7 -1
  162. package/dist/phone-number.esm.js +15 -2
  163. package/dist/phone.d.ts +1 -1
  164. package/dist/phone.esm.js +2 -2
  165. package/dist/phoneFormat-JJNaWthV.esm.js +75 -0
  166. package/dist/{phoneManager-BO-LTih5.d.ts → phoneManager-6nrJkvkG.d.ts} +5 -0
  167. package/dist/{phoneManager-KKUq-Vgo.esm.js → phoneManager-Dy5tODCU.esm.js} +3 -3
  168. package/dist/phoneServices-DJgyOzU2.esm.js +77 -0
  169. package/dist/{phoneStateMachine-D2QWS2cu.esm.js → phoneStateMachine-DnlPhnw7.esm.js} +54 -82
  170. package/dist/{phoneValidation-DnBcNUNh.esm.js → phoneValidation-OggtfjRt.esm.js} +1 -2
  171. package/dist/{platform-DkcRc9JV.esm.js → platform-aPh7gTWh.esm.js} +15 -1
  172. package/dist/processFaceMatch-Bst83HaS.esm.js +21 -0
  173. package/dist/qe-signature.esm.js +1 -1
  174. package/dist/recordingService-CTko6Cjn.esm.js +397 -0
  175. package/dist/redirect-to-mobile.d.ts +2 -2
  176. package/dist/redirect-to-mobile.esm.js +2 -2
  177. package/dist/{redirectToMobileManager-uHW3dyuQ.esm.js → redirectToMobileManager-CgGaT2NP.esm.js} +5 -4
  178. package/dist/{redirectToMobileManager-CVsvpVbQ.d.ts → redirectToMobileManager-Dm9ctRCC.d.ts} +3 -1
  179. package/dist/{redirectToMobileStateMachine-b-H-ipGM.esm.js → redirectToMobileStateMachine-CbhN8uVN.esm.js} +65 -26
  180. package/dist/resolveForm-O7-r79VA.esm.js +351 -0
  181. package/dist/{runChildModule-BF_atgNx.esm.js → runChildModule-BffFArwl.esm.js} +3 -3
  182. package/dist/{sdkVersion-CsIbltJF.esm.js → sdkVersion-CDd_gaR7.esm.js} +1 -1
  183. package/dist/selfie.d.ts +4 -4
  184. package/dist/selfie.esm.js +10 -10
  185. package/dist/{selfieErrorUtils-BY0-YbPW.esm.js → selfieErrorUtils-f4MgAG2A.esm.js} +1 -1
  186. package/dist/{selfieManager-BJdNu_nd.d.ts → selfieManager-DmZFzs1-.d.ts} +1 -1
  187. package/dist/{selfieManager-vAAwzsHk.esm.js → selfieManager-hopelYEk.esm.js} +5 -5
  188. package/dist/{selfieStateMachine-BFVp3ElQ.esm.js → selfieStateMachine-DaZIVv3Q.esm.js} +3 -3
  189. package/dist/{session-CpwfoVdH.esm.js → session-CdSX4wsZ.esm.js} +77 -9
  190. package/dist/session.d.ts +96 -10
  191. package/dist/session.esm.js +7 -6
  192. package/dist/{sessionInitializer-BTjYgE-V.esm.js → sessionInitializer-DsL7X2j9.esm.js} +465 -206
  193. package/dist/{setup-YPKTUCY5.d.ts → setup-D9qt8YVU.d.ts} +2 -2
  194. package/dist/{setup-BInNAvQw.esm.js → setup-DDahygZs.esm.js} +44 -30
  195. package/dist/signature.esm.js +2 -2
  196. package/dist/{signatureManager-f_dPAGXn.esm.js → signatureManager-CwqjcxPg.esm.js} +2 -2
  197. package/dist/{signatureStateMachine-C-nUq_oq.esm.js → signatureStateMachine-DBVDd1Eu.esm.js} +1 -1
  198. package/dist/{stats-BEvexnKC.esm.js → stats-CatA2dea.esm.js} +1 -1
  199. package/dist/stats.esm.js +1 -1
  200. package/dist/textRules-D4NRinKY.d.ts +41 -0
  201. package/dist/{tri-xzRLIIMN.esm.js → tri-DG6priFa.esm.js} +142 -8
  202. package/dist/tri.d.ts +1 -1
  203. package/dist/tri.esm-CzTNi5Q_.esm.js +3826 -0
  204. package/dist/tri.esm.js +1 -1
  205. package/dist/{trueSightService-BMT-TubT.esm.js → trueSightService-GuLthUVK.esm.js} +19 -10
  206. package/dist/trust-graph.esm.js +1 -1
  207. package/dist/types-B9C8W01q.d.ts +34 -0
  208. package/dist/{types-yPH8lAH-.d.ts → types-BEVHQbbC.d.ts} +2 -2
  209. package/dist/{types-BAxn7MpY.d.ts → types-BPm1JSu7.d.ts} +123 -48
  210. package/dist/{types-0L-eFDmr.d.ts → types-BgRHw-dR.d.ts} +1 -1
  211. package/dist/{types-B6HsSzpk.d.ts → types-CRaFu6wS.d.ts} +6 -3
  212. package/dist/types-CTaL0XJz.d.ts +80 -0
  213. package/dist/{types-Ckir_BEs.d.ts → types-Cd0J0F9D.d.ts} +1 -1
  214. package/dist/{types-CK8Jbjkp.d.ts → types-Csh8vzPo.d.ts} +1 -1
  215. package/dist/types-CuMJ2M7D.d.ts +210 -0
  216. package/dist/{types-DUnFZ08M.d.ts → types-CyNndVAT.d.ts} +16 -8
  217. package/dist/{types-DPIDuhut.d.ts → types-DNVzoRvi.d.ts} +2 -1
  218. package/dist/types-J6g6iKe_.d.ts +6 -0
  219. package/dist/{urlUtils-6jsE6rKp.esm.js → urlUtils-eYiyWjh0.esm.js} +4 -1
  220. package/dist/video-selfie.d.ts +8 -8
  221. package/dist/video-selfie.esm.js +97 -22
  222. package/dist/{videoSelfieCameraWarmer-D1xA0u8y.esm.js → videoSelfieCameraWarmer-e3irGfcO.esm.js} +18 -21
  223. package/dist/{videoSelfieStepDetector-CGsTltqB.d.ts → videoSelfieStepDetector-Dv3Mgws-.d.ts} +9 -4
  224. package/dist/virtualCameraCheck-eFOm2C9q.esm.js +27 -0
  225. package/dist/{warmup-BElYWRh7.esm.js → warmup-DtB0DJpl.esm.js} +198 -27
  226. package/dist/wasm.d.ts +2 -2
  227. package/dist/wasm.esm.js +3 -3
  228. package/dist/{wasmDsFlagSync-CYj5LL9z.esm.js → wasmDsFlagSync-BtiR5pig.esm.js} +1 -1
  229. package/dist/wasmMetadataVersionSync-U8EFUr1T.esm.js +27 -0
  230. package/dist/{wasmWebClient-BjZw_7OB.esm.js → wasmWebClient-BDrax6Eu.esm.js} +55 -26
  231. package/dist/watchlist-for-business.d.ts +2 -1
  232. package/dist/watchlist-for-business.esm.js +2 -2
  233. package/dist/watchlist.esm.js +2 -2
  234. package/dist/{watchlistForBusinessManager-B3GDPZrr.d.ts → watchlistForBusinessManager-DX2AyM4Y.d.ts} +54 -18
  235. package/dist/{watchlistForBusinessManager-CZZOFkGl.esm.js → watchlistForBusinessManager-DqUpAEj_.esm.js} +37 -7
  236. package/dist/watchlistForBusinessStateMachine-DdaPl2PS.esm.js +166 -0
  237. package/dist/{watchlistManager-DXtX94SN.esm.js → watchlistManager-CdpXzT4B.esm.js} +2 -2
  238. package/dist/{watchlistStateMachine-McALifag.esm.js → watchlistStateMachine-ofHW_lPk.esm.js} +1 -1
  239. package/dist/workflow.d.ts +5 -2
  240. package/dist/workflow.esm.js +60 -50
  241. package/package.json +12 -5
  242. package/dist/IBrowserEnvironmentCapability-DEaRRk-R.esm.js +0 -9
  243. package/dist/addressSearch-DPjIKJrX.esm.js +0 -563
  244. package/dist/deepsightLoader-DeNvGU3c.esm.js +0 -55
  245. package/dist/ekycStateMachine-CDnI_NRq.esm.js +0 -1443
  246. package/dist/ekycUtils-zY8CdKJL.esm.js +0 -300
  247. package/dist/thumbmark.esm-CRc0cYvz.esm.js +0 -1242
  248. package/dist/tri.esm-BIjHhBJ2.esm.js +0 -2620
  249. package/dist/types-BvLo3U4u.d.ts +0 -134
  250. package/dist/types-zOgZqMni.d.ts +0 -6
  251. package/dist/watchlistForBusinessStateMachine-B66E7jud.esm.js +0 -78
  252. /package/dist/{types-BSBzhHRH2.d.ts → types-BSBzhHRH.d.ts} +0 -0
@@ -1,33 +1,34 @@
1
- import { n as revokeObjectURL, t as getTimestamp } from "./IBrowserEnvironmentCapability-DEaRRk-R.esm.js";
2
- import { l as isGoogleWalletSignedRequestsEnabled, u as BrowserStorageProvider } from "./setup-BInNAvQw.esm.js";
3
- import { t as WasmUtilProvider } from "./WasmUtilProvider-DtJuBdt-.esm.js";
4
- import { n as eventModuleNames, o as createManagerInstrumentation, s as recordExperimentAssignmentOnce, y as addEvent } from "./events-Du2A4-Qr.esm.js";
5
- import { r as getToken, t as api, u as endpoints } from "./api-Cz90EHyu.esm.js";
6
- import { l as trueSightHintTransition, r as noteTrueSightCaptureActivity, u as trueSightLog, y as isTrueSightTesting } from "./trueSightService-BMT-TubT.esm.js";
7
- import { t as getDisableIpify } from "./sessionInitializer-BTjYgE-V.esm.js";
1
+ import { n as getTimestamp, r as revokeObjectURL } from "./IBrowserEnvironmentCapability-D7JG7ML3.esm.js";
2
+ import { l as isGoogleWalletSignedRequestsEnabled, t as ensureWasmPipelines, u as BrowserStorageProvider } from "./setup-DDahygZs.esm.js";
3
+ import { t as WasmUtilProvider } from "./WasmUtilProvider-Dp2V-Uct.esm.js";
4
+ import { n as eventModuleNames, o as createManagerInstrumentation, s as recordExperimentAssignmentOnce, y as addEvent } from "./events-ggpBBaZ8.esm.js";
5
+ import { r as getToken, t as api, u as endpoints } from "./api-CpP4PS4S.esm.js";
6
+ import { l as trueSightHintTransition, r as noteTrueSightCaptureActivity, u as trueSightLog, y as isTrueSightTesting } from "./trueSightService-GuLthUVK.esm.js";
7
+ import { n as getDisableIpify } from "./sessionInitializer-DsL7X2j9.esm.js";
8
8
  import { t as BrowserTimerProvider } from "./BrowserTimerProvider-BXhgNxLt.esm.js";
9
- import { s as exposeExperimentOnce } from "./feature-management-B5rR10uS.esm.js";
10
- import { t as addDeviceStats } from "./stats-BEvexnKC.esm.js";
11
- import { a as isIOS, s as isIPad, t as isAndroid, u as isMacOsSafari } from "./platform-DkcRc9JV.esm.js";
12
- import "./session-CpwfoVdH.esm.js";
9
+ import { s as exposeExperimentOnce } from "./feature-management-BbCIA4og.esm.js";
10
+ import { t as addDeviceStats } from "./stats-CatA2dea.esm.js";
11
+ import { a as isIOS, c as isIPhone14OrHigher, f as isSamsungDevice, s as isIPad, t as isAndroid, u as isMacOsSafari } from "./platform-aPh7gTWh.esm.js";
12
+ import "./session-CdSX4wsZ.esm.js";
13
13
  import { c as not, i as assign, l as raise, n as enqueueActions, o as and, r as sendTo, s as createActor, t as setup, u as createManager } from "./xstate.esm-DSajW7CJ.esm.js";
14
14
  import { n as fromPromise, t as fromCallback } from "./xstate-actors.esm-8Gzepa_A.esm.js";
15
- import { n as getUrlSearchParam, t as buildUrlWithSearchParams } from "./urlUtils-6jsE6rKp.esm.js";
16
- import { r as getCameraReacquisitionConstraints } from "./camera-sIa9ceW2.esm.js";
17
- import { i as requestMotionPermission, n as invokeRequestPermissionActor, o as requiresMotionPermissionUserGesture, t as checkPermission } from "./permissionServices-Ca-tSNhT.esm.js";
18
- import { a as flagIdManualReview, n as runProtectedAttempt, o as PROTECTED_CAPTURE_TARGET, r as cameraCycleProvider, t as createCameraCycleOwnership } from "./createCameraCycleOwnership-Dj_LHUvN.esm.js";
15
+ import { n as getUrlSearchParam, t as buildUrlWithSearchParams } from "./urlUtils-eYiyWjh0.esm.js";
16
+ import { s as isCameraDenialErrorName } from "./camera-E_Kcre4O.esm.js";
17
+ import { i as requestMotionPermission, n as invokeRequestPermissionActor, o as requiresMotionPermissionUserGesture, t as checkPermission, u as queryPermission } from "./permissionServices-D190ATGD.esm.js";
18
+ import { i as cameraCycleProvider, n as createCameraCycleOwnership, o as flagIdManualReview, r as runProtectedAttempt, s as PROTECTED_CAPTURE_TARGET, t as electDesktopCameraDevice } from "./desktopCameraElection-BGMtYwk3.esm.js";
19
19
  import { t as IncodeCanvas } from "./canvas-BxFzWTt-.esm.js";
20
- import { n as needsMotionPrimeOnlyFromPermission, r as resolveStoredPermissionResult, t as isReadyForCaptureFromPermission } from "./permissionGuards-gcy3U0SL.esm.js";
21
- import { o as StreamCanvasProcessingSession } from "./multipartRecordingService-CLwrF5wD.esm.js";
20
+ import { n as needsMotionPrimeOnlyFromPermission, r as resolveStoredPermissionResult, t as isReadyForCaptureFromPermission } from "./permissionGuards-DFV-Ws0a.esm.js";
21
+ import { t as carryAttempts } from "./attemptCarry-WOkfvFMw.esm.js";
22
+ import { t as StreamCanvasProcessingSession } from "./StreamCanvasProcessingSession-CBnbTnOr.esm.js";
22
23
  import { t as sleep } from "./ITimerCapability-DgdDzp8G.esm.js";
23
24
  import { t as getBrowser } from "./getBrowser-Cbe1C4Tn.esm.js";
24
- import { a as isBackCameraLabel } from "./backCameraStream-CMvXj4X4.esm.js";
25
+ import { t as isBackCameraLabel } from "./backCameraLabel-yda5ugE4.esm.js";
25
26
  import { n as getWindowDimensions } from "./getDeviceClass-CeBiEayS.esm.js";
26
- import { n as frameSources, r as runVirtualCameraCheck } from "./deepsightService-CKTYDIXD.esm.js";
27
- import { t as getDeviceClass } from "./getDeviceClass-bsWdEDxP.esm.js";
28
- import { n as DEFAULT_ID_CAPTURE_THRESHOLDS, r as IdCaptureProvider } from "./idCaptureDefaults-BGsG2OAs.esm.js";
29
- import { C as getIdCameraStream, S as OPTIMIZING_WATCHDOG_MARGIN_MS, _ as ID_ERROR_CODES, a as getRealQualityValue, b as resolveIdCaptureThresholds, c as pauseRecordingForAttempt, d as resumeRecordingAfterPause, f as startRecordingSession, g as validateUploadResponse, h as uploadIdImage, i as finalizeRecordingSession, l as prepareRecordingForCameraRetry, m as stopStream, o as initializeIdCapture, p as stopRecording, r as disposeRecordingSession, s as isSuspendableRecordingSession, t as addBarcode, u as processId, x as CAPTURE_OPTIMIZING, y as resolveCountdownStepMs } from "./idCaptureServices-BSj6EH2l.esm.js";
27
+ import { t as getDeviceClass } from "./getDeviceClass-DoIWuKI8.esm.js";
28
+ import { n as DEFAULT_ID_CAPTURE_THRESHOLDS, r as IdCaptureProvider } from "./idCaptureDefaults-Dszuq9ng.esm.js";
29
+ import { C as OPTIMIZING_WATCHDOG_MARGIN_MS, S as CAPTURE_OPTIMIZING, _ as validateUploadResponse, a as finalizeRecordingSession, b as resolveCountdownStepMs, c as isSuspendableRecordingSession, d as processId, f as resumeRecordingAfterPause, g as uploadIdImage, h as stopStream, i as disposeRecordingSession, l as pauseRecordingForAttempt, m as stopRecording, n as addBarcode, o as getRealQualityValue, p as startRecordingSession, s as initializeIdCapture, u as prepareRecordingForCameraRetry, v as ID_ERROR_CODES, w as getIdCameraStream, x as resolveIdCaptureThresholds } from "./idCaptureServices-DK0QboqT.esm.js";
30
30
  import { t as StreamCanvasCapture } from "./StreamCanvasCapture-C9jtgBdT.esm.js";
31
+ import { n as runVirtualCameraCheck, t as frameSources } from "./virtualCameraCheck-eFOm2C9q.esm.js";
31
32
  //#region src/modules/id/digitalUpload/digitalUploadErrors.ts
32
33
  const TERMINAL_FAIL_REASONS = /* @__PURE__ */ new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
33
34
  function isKnownFailReason(reason) {
@@ -550,7 +551,36 @@ const deviceWalletMachine = setup({
550
551
  function resolveWalletPlatform(provider) {
551
552
  if (provider === "apple_web") return "ios";
552
553
  if (provider === "google") return "android";
553
- return isIOS() || isMacOsSafari() || isIPad() ? "ios" : "android";
554
+ return isApplePlatform() ? "ios" : "android";
555
+ }
556
+ /** iOS / iPadOS / macOS Safari — the only platforms Apple Wallet web runs on. */
557
+ function isApplePlatform() {
558
+ return isIOS() || isMacOsSafari() || isIPad();
559
+ }
560
+ /**
561
+ * The wallet family this device *certainly* reaches, for naming it in the UI:
562
+ * `apple` on the Apple platform, `samsung` on a detectable Samsung Android
563
+ * device, `android` on any other Android device. `undefined` when the OS gives
564
+ * no certain answer (desktop Chrome, Windows, Linux). Unlike
565
+ * `resolveWalletPlatform`, which must pick a handshake and so maps every
566
+ * non-Apple browser to Google, this does not guess.
567
+ */
568
+ function resolveWalletDevice() {
569
+ if (isApplePlatform()) return "apple";
570
+ if (isAndroid()) return isSamsungDevice() ? "samsung" : "android";
571
+ }
572
+ /**
573
+ * The device facts the digital-ID funnel filters wallets on: Credentials API
574
+ * availability, the OS wallet the device reaches (the same answer the
575
+ * handshake later launches with) and whether it is a Samsung device.
576
+ * No injected capability reads as "no Credentials API".
577
+ */
578
+ function getDigitalIdPlatformSupport(credentials) {
579
+ return {
580
+ credentialsAvailable: credentials?.isAvailable() ?? false,
581
+ walletPlatform: resolveWalletPlatform(),
582
+ samsungDevice: isSamsungDevice()
583
+ };
554
584
  }
555
585
  //#endregion
556
586
  //#region src/modules/id/deviceWallet/instrumentation.ts
@@ -769,6 +799,580 @@ function renderWallet({ onSuccess, onError, ...actorOptions }) {
769
799
  });
770
800
  }
771
801
  //#endregion
802
+ //#region src/modules/id/digitalIdCountry.ts
803
+ /** Longest the chooser waits for country signals before rendering. */
804
+ const DIGITAL_ID_COUNTRY_DETECTION_TIMEOUT_MS = 1e3;
805
+ /** Upper-cased ISO 3166-1 alpha-2, or `undefined` for anything else. */
806
+ function normalizeCountryCode(value) {
807
+ if (typeof value !== "string") return;
808
+ const code = value.trim().toUpperCase();
809
+ return /^[A-Z]{2}$/.test(code) ? code : void 0;
810
+ }
811
+ /**
812
+ * The region subtags of BCP 47 language tags, in order, deduped. Tags without
813
+ * an explicit alpha-2 region (`sv`, `es-419`) or that do not parse contribute
814
+ * nothing — a bare language is not a country.
815
+ */
816
+ function getLocaleRegions(tags) {
817
+ const regions = [];
818
+ for (const tag of tags) {
819
+ let region;
820
+ try {
821
+ region = new Intl.Locale(tag).region;
822
+ } catch {
823
+ region = void 0;
824
+ }
825
+ const code = normalizeCountryCode(region);
826
+ if (code && !regions.includes(code)) regions.push(code);
827
+ }
828
+ return regions;
829
+ }
830
+ /** Whether any signal is wired at all (otherwise detection is a no-op). */
831
+ function hasCountrySignals(dependencies) {
832
+ if (!dependencies) return false;
833
+ return dependencies.ipCountry !== void 0 || dependencies.locale !== void 0 || dependencies.geolocation !== void 0 && dependencies.reverseGeocodeCountry !== void 0;
834
+ }
835
+ async function detectGpsCountry(dependencies, signal) {
836
+ const { geolocation, reverseGeocodeCountry } = dependencies;
837
+ if (!geolocation || !reverseGeocodeCountry) return;
838
+ if (await queryPermission("geolocation") !== "granted") return;
839
+ return reverseGeocodeCountry(await geolocation.getCurrentPosition(), signal);
840
+ }
841
+ /**
842
+ * Region subtags of the browser languages. A locale capability that throws
843
+ * (e.g. a custom one) is dropped like any other failing signal, so detection
844
+ * still never rejects.
845
+ */
846
+ function readLocaleRegions(locale) {
847
+ if (!locale) return [];
848
+ try {
849
+ return getLocaleRegions(locale.getPreferredLanguages());
850
+ } catch {
851
+ return [];
852
+ }
853
+ }
854
+ /**
855
+ * Collects the country signals and returns their countries, strongest first,
856
+ * deduped (see the module doc for the order). Never rejects: a failing or
857
+ * late signal is dropped.
858
+ */
859
+ async function detectDigitalIdCountries(dependencies, options = {}) {
860
+ const { timeoutMs = DIGITAL_ID_COUNTRY_DETECTION_TIMEOUT_MS, signal } = options;
861
+ const timer = BrowserTimerProvider.getInstance();
862
+ let deadlineHandle;
863
+ const deadline = new Promise((resolve) => {
864
+ deadlineHandle = timer.setTimeout(() => resolve(void 0), timeoutMs);
865
+ });
866
+ const settle = (run) => Promise.race([Promise.resolve().then(run).catch(() => void 0), deadline]);
867
+ try {
868
+ const [gpsCountry, ipCountry] = await Promise.all([settle(() => detectGpsCountry(dependencies, signal)), settle(() => dependencies.ipCountry ? dependencies.ipCountry(signal) : Promise.resolve(void 0))]);
869
+ const localeRegions = readLocaleRegions(dependencies.locale);
870
+ const countries = [];
871
+ for (const candidate of [
872
+ gpsCountry,
873
+ ipCountry,
874
+ ...localeRegions
875
+ ]) {
876
+ const code = normalizeCountryCode(candidate);
877
+ if (code && !countries.includes(code)) countries.push(code);
878
+ }
879
+ return countries;
880
+ } finally {
881
+ if (deadlineHandle !== void 0) timer.clearTimeout(deadlineHandle);
882
+ }
883
+ }
884
+ //#endregion
885
+ //#region src/modules/id/digitalIdRegistry.ts
886
+ /**
887
+ * True when a digital-ID method uses a full-page web-redirect flow (Trinsic
888
+ * iDIN, FTN, itsme, …). Accepts both the module `FlowType` value (`REDIRECT`) and the
889
+ * backend value (`WEB_REDIRECT`). (Lives here rather than in
890
+ * `idCaptureHelpers` to keep the registry free of circular imports; the
891
+ * helpers re-export it.)
892
+ */
893
+ function isRedirectFlowType(flowType) {
894
+ return flowType === "REDIRECT" || flowType === "WEB_REDIRECT";
895
+ }
896
+ const DIGITAL_ID_REGISTRY = {
897
+ mDL: [{
898
+ kind: "incodeWallet",
899
+ documentType: "digitalId"
900
+ }, {
901
+ kind: "trinsicRedirect",
902
+ documentType: "digitalIdRedirect",
903
+ providerId: "trinsic_mdl_placeholder",
904
+ method: "MDL"
905
+ }],
906
+ iDIN: [{
907
+ kind: "trinsicRedirect",
908
+ documentType: "digitalIdRedirect",
909
+ providerId: "trinsic_netherlands_idin",
910
+ method: "IDIN",
911
+ countries: ["NL"]
912
+ }],
913
+ FTN: [{
914
+ kind: "trinsicRedirect",
915
+ documentType: "digitalIdRedirect",
916
+ providerId: "trinsic_finnish_trust_network",
917
+ method: "FTN",
918
+ countries: ["FI"]
919
+ }],
920
+ itsme: [{
921
+ kind: "trinsicRedirect",
922
+ documentType: "digitalIdRedirect",
923
+ providerId: "trinsic_belgium_itsme",
924
+ method: "ITSME",
925
+ countries: ["BE"]
926
+ }],
927
+ SPID: [{
928
+ kind: "trinsicRedirect",
929
+ documentType: "digitalIdRedirect",
930
+ providerId: "trinsic_italy_spid",
931
+ method: "SPID",
932
+ countries: ["IT"]
933
+ }],
934
+ MitID: [{
935
+ kind: "trinsicRedirect",
936
+ documentType: "digitalIdRedirect",
937
+ providerId: "trinsic_denmark_mitid",
938
+ method: "MITID",
939
+ countries: ["DK"]
940
+ }],
941
+ BankIDSweden: [{
942
+ kind: "trinsicRedirect",
943
+ documentType: "digitalIdRedirect",
944
+ providerId: "trinsic_sweden_bankid",
945
+ method: "BANKID_SWEDEN",
946
+ countries: ["SE"]
947
+ }],
948
+ FranceIdentite: [{
949
+ kind: "trinsicRedirect",
950
+ documentType: "digitalIdRedirect",
951
+ providerId: "trinsic_france_identite",
952
+ method: "FRANCE_IDENTITE",
953
+ countries: ["FR"]
954
+ }],
955
+ IdentiteNumerique: [{
956
+ kind: "trinsicRedirect",
957
+ documentType: "digitalIdRedirect",
958
+ providerId: "trinsic_france_identite_numerique",
959
+ method: "IDENTITE_NUMERIQUE",
960
+ countries: ["FR"]
961
+ }],
962
+ LAWallet: [{
963
+ kind: "trinsicRedirect",
964
+ documentType: "digitalIdRedirect",
965
+ providerId: "trinsic_usa_louisiana_wallet",
966
+ method: "LA_WALLET",
967
+ countries: ["US"]
968
+ }],
969
+ DigiLocker: [{
970
+ kind: "trinsicRedirect",
971
+ documentType: "digitalIdRedirect",
972
+ providerId: "trinsic_india_digilocker_aadhaar",
973
+ method: "DIGILOCKER",
974
+ countries: ["IN"]
975
+ }]
976
+ };
977
+ const DIGITAL_ID_DOCUMENT_TYPES = Object.keys(DIGITAL_ID_REGISTRY);
978
+ /**
979
+ * Single place that widens `config.digitalIds` to the shapes the backend
980
+ * actually sends — the mapped array or the raw `{ enabled, methods }` object.
981
+ * Shared so the cast is written once.
982
+ */
983
+ function asDigitalIdsConfig(config) {
984
+ return config.digitalIds;
985
+ }
986
+ /**
987
+ * TODO(test-only): the identity network's test-environment mock providers, one per
988
+ * integration type, for E2E testing — remove before production. Persisted method →
989
+ * provider id only: they are standalone redirect cards, never part of a wallet
990
+ * funnel, so they need no `DigitalIdDocumentType` / `DIGITAL_ID_REGISTRY` entry and
991
+ * stay off the public API. Like every redirect method they render a card only
992
+ * when a flow enables the method in `digitalIds.methods`.
993
+ */
994
+ const TEST_MOCK_REDIRECT_PROVIDER_BY_METHOD = {
995
+ TRINSIC_TEST_REDIRECT: "trinsic_trinsic_test_redirect",
996
+ TRINSIC_TEST_DELAYED_RESULTS: "trinsic_trinsic_test_delayed_results",
997
+ TRINSIC_TEST_SUB_PROVIDERS: "trinsic_trinsic_test_sub_providers",
998
+ TRINSIC_TEST_DEEPLINK: "trinsic_trinsic_test_deeplink",
999
+ TRINSIC_TEST_DEEPLINK_REFRESH: "trinsic_trinsic_test_deeplink_refresh",
1000
+ TRINSIC_TEST_SHOW_CONTENT: "trinsic_trinsic_test_show_content",
1001
+ TRINSIC_TEST_SHOW_CONTENT_REFRESH: "trinsic_trinsic_test_show_content_refresh",
1002
+ TRINSIC_TEST_HANDOFF: "trinsic_trinsic_test_handoff",
1003
+ TRINSIC_TEST_OFFLINE: "trinsic_trinsic_test_offline",
1004
+ TRINSIC_MOCK_OUTPUT: "trinsic_trinsic_mock_output"
1005
+ };
1006
+ /**
1007
+ * Persisted method name → catalog provider id, derived from the registry's
1008
+ * Trinsic entries (single source of truth). Lets the SDK launch iDIN / FTN
1009
+ * from a backend that does not yet send `providerId` on each method.
1010
+ * TODO(roadmap: fully-catalog-driven): remove once every backend enriches
1011
+ * `digitalIds.methods[]` with `providerId` + `flowType`.
1012
+ */
1013
+ const REDIRECT_PROVIDER_BY_METHOD = (() => {
1014
+ const map = { ...TEST_MOCK_REDIRECT_PROVIDER_BY_METHOD };
1015
+ for (const docType of DIGITAL_ID_DOCUMENT_TYPES) for (const entry of DIGITAL_ID_REGISTRY[docType]) if (entry.kind === "trinsicRedirect") map[entry.method] = entry.providerId;
1016
+ return map;
1017
+ })();
1018
+ /**
1019
+ * Catalog provider id → the countries it serves, from the registry. Lets the
1020
+ * chooser rank redirect providers by country even when the backend does not enrich
1021
+ * `digitalIds.methods[]` with `countries`.
1022
+ */
1023
+ const REDIRECT_PROVIDER_COUNTRIES = Object.fromEntries(DIGITAL_ID_DOCUMENT_TYPES.flatMap((docType) => DIGITAL_ID_REGISTRY[docType].flatMap((entry) => entry.kind === "trinsicRedirect" && entry.countries ? [[entry.providerId, entry.countries]] : [])));
1024
+ /**
1025
+ * Redirect providers that are the fallback leg of a wallet-first funnel
1026
+ * (mDL): they are reached through the `digitalId` tile's funnel resolution,
1027
+ * not offered as a standalone chooser card.
1028
+ */
1029
+ const WALLET_FUNNEL_REDIRECT_PROVIDER_IDS = new Set(DIGITAL_ID_DOCUMENT_TYPES.flatMap((docType) => {
1030
+ const entries = DIGITAL_ID_REGISTRY[docType];
1031
+ if (!entries.some((entry) => entry.kind === "incodeWallet")) return [];
1032
+ return entries.flatMap((entry) => entry.kind === "trinsicRedirect" ? [entry.providerId] : []);
1033
+ }));
1034
+ /**
1035
+ * True for a redirect provider that gets its own chooser card (iDIN, FTN, any
1036
+ * catalog-enriched redirect method) — as opposed to the mDL wallet fallback,
1037
+ * which only surfaces through the Digital ID tile.
1038
+ */
1039
+ function isStandaloneRedirectProvider(providerId) {
1040
+ return !WALLET_FUNNEL_REDIRECT_PROVIDER_IDS.has(providerId);
1041
+ }
1042
+ /**
1043
+ * The provider id a configured method launches with, when it is a
1044
+ * web-redirect method; `undefined` for wallets / other flow shapes.
1045
+ *
1046
+ * Resolution order:
1047
+ * 1. an explicit redirect `flowType` with a `provider` (mapped shape) or
1048
+ * `providerId` (catalog-enriched raw shape) — backend-authoritative;
1049
+ * 2. otherwise the persisted method name via the registry (legacy raw shape).
1050
+ */
1051
+ function resolveRedirectProviderId(method) {
1052
+ if (method.flowType) {
1053
+ if (!isRedirectFlowType(method.flowType)) return;
1054
+ const explicit = method.provider ?? method.providerId;
1055
+ if (explicit) return explicit;
1056
+ }
1057
+ return method.method ? REDIRECT_PROVIDER_BY_METHOD[method.method.toUpperCase()] : void 0;
1058
+ }
1059
+ /**
1060
+ * Tolerant view over `config.digitalIds`: accepts both the mapped array
1061
+ * (`IdCaptureDigitalIdMethod[]`) and the raw backend object
1062
+ * (`{ enabled, methods: [...] }`). Extracted from the old
1063
+ * `getDigitalIdRedirectMethod` cast so every consumer parses it the same way.
1064
+ *
1065
+ * Honors both dashboard toggles: a raw object with `enabled: false` yields no
1066
+ * methods, and individual methods with `enabled: false` are dropped (absent
1067
+ * `enabled` counts as on). This is what "enabled for the flow / workflow"
1068
+ * means — for the redirect chooser cards as much as for the wallet tile.
1069
+ */
1070
+ function normalizeDigitalIdMethods(config) {
1071
+ const raw = asDigitalIdsConfig(config);
1072
+ if (!Array.isArray(raw) && raw?.enabled === false) return [];
1073
+ return (Array.isArray(raw) ? raw : raw?.methods ?? []).filter((method) => method.enabled !== false);
1074
+ }
1075
+ /**
1076
+ * Persisted method names of the Incode-native device wallets — the backend
1077
+ * `DigitalIdMethodCatalog` entries of type `MDL`. A catalog-enriched method
1078
+ * carries `type: 'MDL'` instead of relying on the name; both are honoured.
1079
+ *
1080
+ * `SAMSUNG_WALLET` is listed by name because the onboarding catalog does not
1081
+ * enrich it yet: it arrives as a bare `{ method: 'SAMSUNG_WALLET' }`. Without
1082
+ * the name it would fall through to the unfiltered `deviceWallet` flag and
1083
+ * skip `WALLET_PLATFORM_RULES`' Samsung-only rule.
1084
+ */
1085
+ const DEVICE_WALLET_METHODS = /* @__PURE__ */ new Set([
1086
+ "APPLE_WALLET",
1087
+ "GOOGLE_WALLET",
1088
+ "CA_DMV_WALLET",
1089
+ "SAMSUNG_WALLET"
1090
+ ]);
1091
+ /**
1092
+ * True for a configured method the native device-wallet handshake can fulfil.
1093
+ * Redirect methods (iDIN, FTN) never count, whatever their name or type — they
1094
+ * must not surface a wallet tile with no wallet behind it.
1095
+ *
1096
+ * Classifies by *kind* only. Whether a method is switched on is already
1097
+ * settled by `normalizeDigitalIdMethods`, which drops disabled methods before
1098
+ * any caller walks the list.
1099
+ */
1100
+ function isDeviceWalletMethod(method) {
1101
+ if (method.flowType && isRedirectFlowType(method.flowType)) return false;
1102
+ if (method.type?.toUpperCase() === "MDL") return true;
1103
+ return method.method !== void 0 && DEVICE_WALLET_METHODS.has(method.method.toUpperCase());
1104
+ }
1105
+ /**
1106
+ * Device-level hard filter per wallet method: a wallet the device cannot reach
1107
+ * is never offered. Apple Wallet needs the Apple platform, Google Wallet any
1108
+ * other, and Samsung Wallet a Samsung device. Methods without a rule (CA DMV
1109
+ * Wallet, an unknown catalog `MDL` method) run on either platform.
1110
+ *
1111
+ * A rule only rejects on a known platform fact, so a caller that omits
1112
+ * `walletPlatform` / `samsungDevice` gets no filtering.
1113
+ */
1114
+ const WALLET_PLATFORM_RULES = {
1115
+ APPLE_WALLET: (platform) => platform.walletPlatform !== "android",
1116
+ GOOGLE_WALLET: (platform) => platform.walletPlatform !== "ios",
1117
+ SAMSUNG_WALLET: (platform) => platform.walletPlatform !== "ios" && platform.samsungDevice !== false
1118
+ };
1119
+ function isDeviceWalletMethodEligible(method, platform) {
1120
+ const rule = method.method !== void 0 ? WALLET_PLATFORM_RULES[method.method.toUpperCase()] : void 0;
1121
+ return rule ? rule(platform) : true;
1122
+ }
1123
+ /**
1124
+ * Whether a device wallet can run for this config on this device: an enabled
1125
+ * wallet method that passes `WALLET_PLATFORM_RULES`, or, when the config lists
1126
+ * no wallet method at all, the legacy `deviceWallet` flag (which names no
1127
+ * wallet, so there is nothing to filter).
1128
+ *
1129
+ * The method list is the authority. The dashboard persists a wallet only in
1130
+ * `digitalIds.methods` and leaves the legacy `deviceWallet` / `appleWallet`
1131
+ * booleans at their stored `false`; the workflow-node response historically
1132
+ * shipped them raw, so reading the list is what keeps the tile visible there
1133
+ * (and matches SDK 1). It also means a config whose only wallet is Apple
1134
+ * Wallet yields `false` on Android even when `deviceWallet` is `true`. Unlike
1135
+ * the backend's `deriveDeviceWalletFlag`, an unrecognised method does not
1136
+ * count as a wallet: it must not launch a handshake that cannot know what to
1137
+ * request.
1138
+ */
1139
+ function hasEligibleDeviceWallet(config, platform) {
1140
+ const walletMethods = normalizeDigitalIdMethods(config).filter(isDeviceWalletMethod);
1141
+ if (walletMethods.length > 0) return walletMethods.some((method) => isDeviceWalletMethodEligible(method, platform));
1142
+ return config.deviceWallet === true;
1143
+ }
1144
+ /** Whether a funnel entry is activated by config + platform capabilities. */
1145
+ function isEntryActive(entry, config, platform) {
1146
+ if (entry.kind === "incodeWallet") return platform.credentialsAvailable && hasEligibleDeviceWallet(config, platform);
1147
+ return findConfiguredMethod(entry, config) !== void 0;
1148
+ }
1149
+ /**
1150
+ * The configured `digitalIds` method matching a Trinsic funnel entry — by
1151
+ * persisted method name, or (mapped shape) by provider id on a redirect
1152
+ * flowType. First match wins; disabled methods are already dropped by
1153
+ * `normalizeDigitalIdMethods`.
1154
+ */
1155
+ function findConfiguredMethod(entry, config) {
1156
+ return normalizeDigitalIdMethods(config).find((method) => method.method?.toUpperCase() === entry.method || method.provider === entry.providerId && !!method.flowType && isRedirectFlowType(method.flowType));
1157
+ }
1158
+ /** Normalizes a raw configured method into the mapped shape for the child input. */
1159
+ function toMappedMethod(entry, method) {
1160
+ if (method.flowType && isRedirectFlowType(method.flowType)) return method;
1161
+ return {
1162
+ method: method.method,
1163
+ provider: entry.providerId,
1164
+ flowType: "WEB_REDIRECT",
1165
+ country: method.country ?? method.countries?.[0],
1166
+ displayName: method.displayName,
1167
+ logoUrl: method.logoUrl
1168
+ };
1169
+ }
1170
+ /**
1171
+ * Resolves the implementation that should fulfil a digital-ID document type:
1172
+ * the first funnel entry that is active under the given config and platform.
1173
+ * `undefined` when nothing can run it (the chooser then shows no tile for it).
1174
+ */
1175
+ function resolveDigitalIdImplementation(docType, config, platform) {
1176
+ for (const entry of DIGITAL_ID_REGISTRY[docType]) {
1177
+ if (!isEntryActive(entry, config, platform)) continue;
1178
+ if (entry.kind === "incodeWallet") return { kind: "incodeWallet" };
1179
+ const method = findConfiguredMethod(entry, config);
1180
+ return {
1181
+ kind: "trinsicRedirect",
1182
+ providerId: entry.providerId,
1183
+ method: method ? toMappedMethod(entry, method) : void 0
1184
+ };
1185
+ }
1186
+ }
1187
+ //#endregion
1188
+ //#region src/modules/id/idCaptureHelpers.ts
1189
+ /**
1190
+ * Normalizes a configured method into the mapped redirect shape for a
1191
+ * resolved provider. The already-mapped shape is returned as-is; the raw
1192
+ * backend shape gets `provider` + `WEB_REDIRECT` filled in.
1193
+ */
1194
+ function toRedirectMethod(method, provider) {
1195
+ if (method.provider && method.flowType) return method;
1196
+ return {
1197
+ method: method.method,
1198
+ provider,
1199
+ flowType: "WEB_REDIRECT",
1200
+ country: method.country ?? method.countries?.[0],
1201
+ displayName: method.displayName,
1202
+ logoUrl: method.logoUrl
1203
+ };
1204
+ }
1205
+ /**
1206
+ * The enabled web-redirect digital-ID method to launch — the one matching
1207
+ * `providerId` when given (a chooser card was picked), else the first
1208
+ * configured redirect method — or `undefined` when none is configured.
1209
+ * Drives the provider and country passed to the `digitalIdRedirectMachine`.
1210
+ *
1211
+ * Accepts both the mapped array (`IdCaptureDigitalIdMethod[]`) and the raw
1212
+ * backend `configuration.digitalIds` object (`{ enabled, methods: [...] }`);
1213
+ * for the raw shape the provider comes from the backend-enriched
1214
+ * `providerId`/`flowType` when present, else from the persisted method name
1215
+ * via the digital-ID registry (`IDIN` → `trinsic_netherlands_idin`).
1216
+ */
1217
+ function getDigitalIdRedirectMethod(config, providerId) {
1218
+ for (const method of normalizeDigitalIdMethods(config)) {
1219
+ const provider = resolveRedirectProviderId(method);
1220
+ if (!provider || providerId !== void 0 && provider !== providerId) continue;
1221
+ return toRedirectMethod(method, provider);
1222
+ }
1223
+ }
1224
+ function collectDigitalIdRedirectOptions(config) {
1225
+ const entries = [];
1226
+ for (const method of normalizeDigitalIdMethods(config)) {
1227
+ const providerId = resolveRedirectProviderId(method);
1228
+ if (!providerId || !isStandaloneRedirectProvider(providerId) || entries.some((entry) => entry.option.providerId === providerId)) continue;
1229
+ const countries = (method.countries ?? (method.country ? [method.country] : void 0) ?? REDIRECT_PROVIDER_COUNTRIES[providerId] ?? []).flatMap((country) => normalizeCountryCode(country) ?? []);
1230
+ entries.push({
1231
+ option: {
1232
+ providerId,
1233
+ method: method.method,
1234
+ displayName: method.displayName,
1235
+ logoUrl: method.logoUrl,
1236
+ country: method.country ?? method.countries?.[0] ?? countries[0]
1237
+ },
1238
+ countries
1239
+ });
1240
+ }
1241
+ return entries;
1242
+ }
1243
+ /**
1244
+ * Rank of an option against the detected countries: the index of the
1245
+ * strongest detected country it serves, `Infinity` when it serves none.
1246
+ */
1247
+ function countryRank(countries, preferredCountries) {
1248
+ const ranks = countries.map((country) => preferredCountries.indexOf(country)).filter((index) => index >= 0);
1249
+ return ranks.length > 0 ? Math.min(...ranks) : Number.POSITIVE_INFINITY;
1250
+ }
1251
+ /**
1252
+ * The digital-ID web-redirect providers that get their own chooser card: one
1253
+ * per enabled redirect method in `config.digitalIds`, deduped by provider.
1254
+ * Wallet-funnel fallbacks (the Trinsic mDL leg) are excluded — they surface
1255
+ * through the Digital ID tile instead.
1256
+ *
1257
+ * Order: providers serving the strongest detected country first
1258
+ * (`preferredCountries`, see `detectDigitalIdCountries`), then those serving
1259
+ * weaker ones, then the rest. Country only ranks — nothing is hidden — and
1260
+ * ties keep backend (dashboard) order. With no detected country this is plain
1261
+ * backend order.
1262
+ *
1263
+ * Card display data (`displayName`, `logoUrl`, `country`) is whatever the
1264
+ * backend enriched the method with; the UI falls back to generic copy / icon
1265
+ * when absent.
1266
+ */
1267
+ function getAvailableDigitalIdRedirectOptions(config, preferredCountries = []) {
1268
+ const entries = collectDigitalIdRedirectOptions(config);
1269
+ if (preferredCountries.length === 0) return entries.map((entry) => entry.option);
1270
+ return entries.map((entry) => ({
1271
+ entry,
1272
+ rank: countryRank(entry.countries, preferredCountries)
1273
+ })).sort((a, b) => a.rank - b.rank).map(({ entry }) => entry.option);
1274
+ }
1275
+ /**
1276
+ * Re-orders the given redirect options for `preferredCountries` without
1277
+ * changing the set: same ranking as `getAvailableDigitalIdRedirectOptions`,
1278
+ * ties in backend order. Each option's countries come from its configured
1279
+ * method (all of them), falling back to the option's own `country`.
1280
+ */
1281
+ function rankDigitalIdRedirectOptions(options, config, preferredCountries) {
1282
+ const entries = collectDigitalIdRedirectOptions(config);
1283
+ const backendIndex = (option) => {
1284
+ const index = entries.findIndex((entry) => entry.option.providerId === option.providerId);
1285
+ return index >= 0 ? index : entries.length;
1286
+ };
1287
+ const countriesOf = (option) => {
1288
+ const configured = entries.find((entry) => entry.option.providerId === option.providerId);
1289
+ const own = normalizeCountryCode(option.country);
1290
+ return configured?.countries ?? (own ? [own] : []);
1291
+ };
1292
+ return options.map((option, position) => ({
1293
+ option,
1294
+ rank: countryRank(countriesOf(option), preferredCountries),
1295
+ order: backendIndex(option),
1296
+ position
1297
+ })).sort((a, b) => a.rank - b.rank || a.order - b.order || a.position - b.position).map(({ option }) => option);
1298
+ }
1299
+ /**
1300
+ * Whether country ranking can change the order of the redirect options: at
1301
+ * least two options serving different countries. When it cannot, the chooser
1302
+ * skips country detection entirely (no request, no wait).
1303
+ */
1304
+ function canRankDigitalIdRedirectOptionsByCountry(config) {
1305
+ const entries = collectDigitalIdRedirectOptions(config);
1306
+ if (entries.length < 2) return false;
1307
+ return new Set(entries.map((entry) => [...entry.countries].sort().join(","))).size > 1;
1308
+ }
1309
+ /**
1310
+ * Map of config properties received from the backend to adjusted, internal document types.
1311
+ */
1312
+ const DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP = [
1313
+ ["enableId", "id"],
1314
+ ["enablePassport", "passport"],
1315
+ ["digitalIdsUpload", "digitalIdUpload"]
1316
+ ];
1317
+ /**
1318
+ * Returns the list of document types enabled by config for the chooser screen, in display order.
1319
+ * Used to populate chooser state so UI and headless consumers can render the correct options.
1320
+ *
1321
+ * Digital-ID document types (device wallet, Trinsic web-redirect) come from
1322
+ * the digital-ID registry funnel: each registry document type contributes the
1323
+ * tile of its first active implementation. A `deviceWallet: true` config on a
1324
+ * platform without the Credentials API therefore shows the Trinsic fallback
1325
+ * tile when one is configured — or no tile at all, instead of a dead-end one.
1326
+ *
1327
+ * @param config - ID capture configuration (from flow or init)
1328
+ * @param platform - Platform capabilities consulted by the digital-ID funnel.
1329
+ * Defaults to no Credentials API for pure-node callers; the machine passes
1330
+ * the real capability check.
1331
+ * @returns Array of IdDocumentType values that should be shown in the document type chooser
1332
+ */
1333
+ function getAvailableDocumentTypes(config, platform = { credentialsAvailable: false }) {
1334
+ const adjustedDocumentTypes = [];
1335
+ for (const [configProperty, adjustedType] of DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP) if (config[configProperty]) adjustedDocumentTypes.push(adjustedType);
1336
+ for (const docType of DIGITAL_ID_DOCUMENT_TYPES) {
1337
+ const route = resolveDigitalIdImplementation(docType, config, platform);
1338
+ if (!route) continue;
1339
+ const documentType = route.kind === "incodeWallet" ? "digitalId" : "digitalIdRedirect";
1340
+ if (!adjustedDocumentTypes.includes(documentType)) adjustedDocumentTypes.push(documentType);
1341
+ }
1342
+ if (!adjustedDocumentTypes.includes("digitalIdRedirect") && getAvailableDigitalIdRedirectOptions(config).length > 0) adjustedDocumentTypes.push("digitalIdRedirect");
1343
+ return adjustedDocumentTypes;
1344
+ }
1345
+ /**
1346
+ * Computes `idCaptureMachine`'s terminal output — the downstream module-skip
1347
+ * signal read by the Flow orchestrator (via `runChildModule`'s `MODULE_COMPLETE`).
1348
+ *
1349
+ * `skipFaceMatch` is set ONLY for the US Smart Capture *camera back-only* path:
1350
+ * a back image was captured on-device (`capturedImages.back`) and no front was
1351
+ * (`!capturedImages.front`) — "no front, no ID face, no match".
1352
+ *
1353
+ * Requiring a captured back is deliberate and load-bearing: the digital-ID
1354
+ * upload path submits a full ID (front face present) but does NOT
1355
+ * populate `capturedImages` (only the camera path does). Gating on a captured
1356
+ * back excludes those upload paths so a real ID-vs-selfie match is never
1357
+ * silently skipped. `capturedImages.front`/`forceFrontIdCapture` alone are not
1358
+ * enough (a later front upload clears the request; uploads set neither field).
1359
+ *
1360
+ * Always `false` outside US Smart Capture. The selfie/face capture itself is
1361
+ * unaffected — only the ID-vs-selfie match is skipped.
1362
+ *
1363
+ * Also `true` on the Digital ID web-redirect (Trinsic iDIN/FTN) COMPLETED path
1364
+ * when the scheme returned no portrait (`isDigitalIdRedirect && !portraitPresent`,
1365
+ * FM-1/FM-2): there is no ID face to match the selfie against.
1366
+ */
1367
+ function computeIdCaptureOutput(context) {
1368
+ const frontIdCaptured = Boolean(context.capturedImages.front);
1369
+ const backIdCaptured = Boolean(context.capturedImages.back);
1370
+ return {
1371
+ frontIdCaptured,
1372
+ skipFaceMatch: context.isDigitalIdRedirect === true && context.portraitPresent !== true || context.config.usSmartCapture === true && backIdCaptured && !frontIdCaptured
1373
+ };
1374
+ }
1375
+ //#endregion
772
1376
  //#region src/modules/id/idCaptureGuards.ts
773
1377
  function getPermissionOutput(event) {
774
1378
  if (!("output" in event)) return;
@@ -874,6 +1478,13 @@ const supportsOptimizingStatusGuard = ({ context }) => context.config.supportsOp
874
1478
  const isDeepsightEnabledGuard = ({ context }) => context.dependencies !== void 0;
875
1479
  const isDeepsightReadyGuard = ({ context }) => context.deepsightService !== void 0;
876
1480
  const needsDeepsightInitGuard = ({ context }) => context.dependencies !== void 0 && context.deepsightService === void 0 && !context.deepsightInitAttempted;
1481
+ /**
1482
+ * Route into the chooser through `detectingCountry`: detection has not run
1483
+ * yet, a country signal is wired, and the ranking could actually reorder the
1484
+ * redirect options (two or more serving different countries). Otherwise the
1485
+ * chooser opens at once, with no request and no spinner.
1486
+ */
1487
+ const needsCountryDetectionGuard = ({ context }) => context.detectedCountries === void 0 && hasCountrySignals(context.dependencies?.countryDetection) && canRankDigitalIdRedirectOptionsByCountry(context.config);
877
1488
  /** No capture option is enabled — the ID module is misconfigured. */
878
1489
  const hasNoDocumentTypesAvailableGuard = ({ context }) => context.availableDocumentTypes.length === 0;
879
1490
  const isDigitalIdUploadSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "digitalIdUpload";
@@ -1420,7 +2031,7 @@ fromPromise(async ({ input }) => {
1420
2031
  });
1421
2032
  fromPromise(async ({ input }) => {
1422
2033
  if (!input.dependencies) return;
1423
- const { loadDeepsightSession } = await import("./deepsightLoader-DeNvGU3c.esm.js");
2034
+ const { loadDeepsightSession } = await import("./deepsightLoader-B7DEYoyY.esm.js");
1424
2035
  return loadDeepsightSession({
1425
2036
  ds: input.ds,
1426
2037
  storage: input.dependencies.storage,
@@ -1863,21 +2474,28 @@ function cleanup(service) {
1863
2474
  service.cleanup();
1864
2475
  } catch {}
1865
2476
  }
1866
- function createIdMetadataPreparationCoordinator(load = async (input) => (await import("./deepsightLoader-DeNvGU3c.esm.js")).loadDeepsightSession(input)) {
2477
+ function createIdMetadataPreparationCoordinator(load = async (input) => (await import("./deepsightLoader-B7DEYoyY.esm.js")).loadDeepsightSession(input)) {
1867
2478
  let disposed = false;
1868
2479
  let preparation;
1869
2480
  let service;
2481
+ let failure;
1870
2482
  const prepare = (input) => {
1871
2483
  if (disposed) return Promise.reject(/* @__PURE__ */ new Error("ID metadata coordinator is disposed"));
1872
- preparation ??= (async () => {
1873
- const prepared = await load(input);
1874
- if (disposed) {
1875
- cleanup(prepared);
1876
- throw new Error("ID metadata coordinator is disposed");
1877
- }
1878
- service = prepared;
1879
- return prepared;
1880
- })();
2484
+ if (!preparation) {
2485
+ const pending = (async () => {
2486
+ const prepared = await load(input);
2487
+ if (disposed) {
2488
+ cleanup(prepared);
2489
+ throw new Error("ID metadata coordinator is disposed");
2490
+ }
2491
+ service = prepared;
2492
+ return prepared;
2493
+ })();
2494
+ preparation = pending;
2495
+ pending.catch((error) => {
2496
+ if (preparation === pending) failure = { error };
2497
+ });
2498
+ }
1881
2499
  return preparation;
1882
2500
  };
1883
2501
  return {
@@ -1885,10 +2503,19 @@ function createIdMetadataPreparationCoordinator(load = async (input) => (await i
1885
2503
  prepare(input).catch(() => void 0);
1886
2504
  },
1887
2505
  prepare,
2506
+ /**
2507
+ * The memoized preparation's rejection once it has settled. `undefined`
2508
+ * while it is pending or after it succeeded. Preparation is never retried,
2509
+ * so a failure here fails every later attempt of this capture too.
2510
+ */
2511
+ settledFailure() {
2512
+ return failure;
2513
+ },
1888
2514
  dispose() {
1889
2515
  if (disposed) return;
1890
2516
  disposed = true;
1891
2517
  preparation = void 0;
2518
+ failure = void 0;
1892
2519
  const prepared = service;
1893
2520
  service = void 0;
1894
2521
  if (prepared) cleanup(prepared);
@@ -1981,18 +2608,18 @@ function streamUsesBackCamera(stream) {
1981
2608
  if (isBackCameraLabel(label)) return true;
1982
2609
  if (label.includes("front") || label.includes("user")) return false;
1983
2610
  }
2611
+ /** The tutorial pre-acquire's default work: have the ID pipeline loaded. */
2612
+ const warmupIdPipeline = () => ensureWasmPipelines(["idCapture"]);
1984
2613
  function createIdProtectedCaptureController(dependencies = {}) {
1985
2614
  const metadataCoordinator = createIdMetadataPreparationCoordinator(dependencies.loadMetadata);
1986
2615
  let disposed = false;
1987
2616
  let visible = true;
1988
2617
  let preAcquired;
1989
2618
  let preAcquirePromise;
1990
- let preAcquireGeneration = 0;
1991
2619
  let provider;
1992
2620
  let displayStream;
1993
2621
  let frameCapturer;
1994
2622
  let captureResolution;
1995
- let cameraFallbackLevel;
1996
2623
  let usingBackCamera;
1997
2624
  let previewImageUrl;
1998
2625
  let pendingPreviewCanvas;
@@ -2042,23 +2669,21 @@ function createIdProtectedCaptureController(dependencies = {}) {
2042
2669
  releasePreAcquired();
2043
2670
  preAcquired = value;
2044
2671
  captureResolution = streamResolution(value.stream);
2045
- cameraFallbackLevel = value.fallbackLevel;
2046
2672
  usingBackCamera = streamUsesBackCamera(value.stream);
2047
2673
  return true;
2048
2674
  };
2675
+ /**
2676
+ * Overlaps the ID pipeline warm-up with the tutorial so the attempt's
2677
+ * `configureWorkflow` finds it loaded. Nothing here opens a camera: since
2678
+ * ml-wasm-kit v2.14.52 the kit acquires it inside the protected camera step.
2679
+ * In-flight calls are deduplicated; the warm-up itself is idempotent.
2680
+ */
2049
2681
  const preAcquire = () => {
2050
2682
  if (disposed) return Promise.reject(/* @__PURE__ */ new Error("ID protected capture controller is disposed"));
2051
- if (preAcquired) return Promise.resolve();
2052
2683
  if (preAcquirePromise) return preAcquirePromise;
2053
- const generation = preAcquireGeneration;
2054
2684
  const pending = (async () => {
2055
- const value = await (dependencies.acquireCamera ?? getIdCameraStream)();
2056
- if (disposed || generation !== preAcquireGeneration) {
2057
- stopStream(value.stream);
2058
- if (disposed) throw new Error("ID protected capture controller is disposed");
2059
- return;
2060
- }
2061
- acceptPreAcquired(value);
2685
+ await (dependencies.warmupPipelines ?? warmupIdPipeline)();
2686
+ if (disposed) throw new Error("ID protected capture controller is disposed");
2062
2687
  })();
2063
2688
  preAcquirePromise = pending;
2064
2689
  pending.then(() => {
@@ -2148,6 +2773,7 @@ function createIdProtectedCaptureController(dependencies = {}) {
2148
2773
  beginAttempt(context, send, getLiveContext) {
2149
2774
  if (disposed) throw new Error("ID protected capture controller is disposed");
2150
2775
  clearAttempt();
2776
+ usingBackCamera = getDeviceClass() !== "desktop";
2151
2777
  if (stepRecording.session && stepRecording.scope !== recordingScopeFor(context)) completeStepRecording();
2152
2778
  diagnosticAttempt = {
2153
2779
  attempt: ++protectedIdAttemptSequence,
@@ -2158,7 +2784,6 @@ function createIdProtectedCaptureController(dependencies = {}) {
2158
2784
  attemptSend = send;
2159
2785
  getAttemptLiveContext = getLiveContext;
2160
2786
  provider = (dependencies.createProvider ?? createProtectedIdProvider)(context.config, context.currentMode);
2161
- cycleOwnership = createCameraCycleOwnership(cameraCycleProvider);
2162
2787
  logDiagnostic("attempt-start", { aggregationMs: context.config?.thresholds?.framesAggregationInterval ?? DEFAULT_ID_CAPTURE_THRESHOLDS.framesAggregationInterval });
2163
2788
  noteTrueSightCaptureActivity(true);
2164
2789
  },
@@ -2171,6 +2796,9 @@ function createIdProtectedCaptureController(dependencies = {}) {
2171
2796
  disableIpify: context.disableIpify
2172
2797
  });
2173
2798
  },
2799
+ settledMetadataFailure() {
2800
+ return metadataCoordinator.settledFailure();
2801
+ },
2174
2802
  prepareMetadata(context) {
2175
2803
  const storage = context.dependencies?.storage;
2176
2804
  if (!storage) return Promise.reject(/* @__PURE__ */ new Error("ID metadata storage is unavailable"));
@@ -2184,7 +2812,6 @@ function createIdProtectedCaptureController(dependencies = {}) {
2184
2812
  dispose() {
2185
2813
  if (disposed) return;
2186
2814
  disposed = true;
2187
- preAcquireGeneration += 1;
2188
2815
  metadataCoordinator.dispose();
2189
2816
  releasePreAcquired();
2190
2817
  clearAttempt();
@@ -2218,27 +2845,26 @@ function createIdProtectedCaptureController(dependencies = {}) {
2218
2845
  return visible;
2219
2846
  },
2220
2847
  storePreAcquiredStream(value) {
2221
- preAcquireGeneration += 1;
2222
2848
  return acceptPreAcquired(value);
2223
2849
  },
2224
2850
  takePreAcquiredStream() {
2225
2851
  const value = preAcquired;
2226
2852
  preAcquired = void 0;
2227
- if (value) cameraFallbackLevel = value.fallbackLevel;
2228
2853
  return value;
2229
2854
  },
2230
2855
  getProvider() {
2231
2856
  return provider;
2232
2857
  },
2233
2858
  getCycleOwnership() {
2234
- if (!cycleOwnership) throw new Error("Protected ID cycle ownership is unavailable");
2859
+ if (!attemptContext) throw new Error("Protected ID cycle ownership is unavailable");
2860
+ cycleOwnership ??= createCameraCycleOwnership(cameraCycleProvider);
2235
2861
  return cycleOwnership;
2236
2862
  },
2237
2863
  getProjection() {
2238
2864
  return {
2239
2865
  stream: displayStream,
2240
2866
  captureResolution,
2241
- cameraFallbackLevel,
2867
+ cameraFallbackLevel: void 0,
2242
2868
  usingBackCamera
2243
2869
  };
2244
2870
  },
@@ -2287,14 +2913,12 @@ function createIdProtectedCaptureController(dependencies = {}) {
2287
2913
  type,
2288
2914
  qualityElements: context.qualityElements,
2289
2915
  onProgress,
2290
- deepsightService: void 0,
2291
2916
  stream: displayStream,
2292
2917
  isSecondId: context.config.isSecondId ?? false,
2293
2918
  onlyFront: type === "front" && (context.config.onlyFront ?? false),
2294
2919
  ageAssurance: context.config.ageAssurance,
2295
2920
  dependencies: context.dependencies,
2296
2921
  captureResolution,
2297
- cameraFallbackLevel,
2298
2922
  extractIdFace: context.config.extractIdFace,
2299
2923
  croppedCanvas: provider?.getCapturedCanvas() ?? null
2300
2924
  };
@@ -2313,12 +2937,18 @@ function createIdProtectedCaptureController(dependencies = {}) {
2313
2937
  },
2314
2938
  async deliverCaptureOnly(signal) {
2315
2939
  if (!dependencies.finalizeCaptureOnly || !attemptContext || !attemptSend) throw new Error(ID_ERROR_CODES.UPLOAD_ERROR);
2316
- return dependencies.finalizeCaptureOnly(controller.buildCaptureOnlyUpload(attemptContext, (progress) => {
2940
+ const upload = controller.buildCaptureOnlyUpload(attemptContext, (progress) => {
2317
2941
  attemptSend?.({
2318
2942
  type: "UPLOAD_PROGRESS",
2319
2943
  progress
2320
2944
  });
2321
- }), signal);
2945
+ });
2946
+ const deepsightService = await controller.prepareMetadata(attemptContext).catch(() => void 0);
2947
+ if (signal.aborted) throw new DOMException("Aborted", "AbortError");
2948
+ return dependencies.finalizeCaptureOnly({
2949
+ ...upload,
2950
+ deepsightService
2951
+ }, signal);
2322
2952
  },
2323
2953
  resourceSink: {
2324
2954
  ready(stream) {
@@ -2327,10 +2957,7 @@ function createIdProtectedCaptureController(dependencies = {}) {
2327
2957
  return;
2328
2958
  }
2329
2959
  replaceDisplayStream(stream);
2330
- logDiagnostic("protected-camera-ready", {
2331
- ...getIdCameraTrackDiagnosticFields(stream.getVideoTracks()[0]),
2332
- fallbackLevel: cameraFallbackLevel
2333
- });
2960
+ logDiagnostic("protected-camera-ready", getIdCameraTrackDiagnosticFields(stream.getVideoTracks()[0]));
2334
2961
  },
2335
2962
  autoCommitted: storeCommit,
2336
2963
  manualCommitted: storeCommit,
@@ -2775,48 +3402,34 @@ function createProtectedIdAttemptInput(input) {
2775
3402
  const target = resolveProtectedIdTarget(context.config, context.currentMode);
2776
3403
  const callbackSession = createProtectedIdCallbackSession(input);
2777
3404
  let wasmUtil;
2778
- const preAcquired = controller.takePreAcquiredStream();
2779
- let selectedVideoTrack = preAcquired?.stream.getVideoTracks()[0];
2780
- const constraints = getCameraReacquisitionConstraints(selectedVideoTrack, preAcquired?.constraints);
2781
3405
  const captureOnly = hasOnCaptureCallback(context.config);
2782
3406
  const diagnosticAttempt = controller.getDiagnosticAttempt();
2783
3407
  const isAttemptActive = () => !controller.disposed && controller.getProvider() === provider && controller.getDiagnosticAttempt() === diagnosticAttempt;
2784
- const logSelectedCamera = (stream, fallbackLevel, reacquisitionConstraints, preAcquiredStream) => {
2785
- if (!diagnosticAttempt) return;
2786
- logIdCameraDiagnostic("selected-camera", {
2787
- attempt: diagnosticAttempt.attempt,
2788
- side: diagnosticAttempt.side,
2789
- elapsedMs: Math.round(getTimestamp() - diagnosticAttempt.startedAt),
2790
- ...getIdCameraTrackDiagnosticFields(stream.getVideoTracks()[0]),
2791
- preAcquired: preAcquiredStream,
2792
- fallbackLevel,
2793
- workflow: String(workflow),
2794
- devicePinned: reacquisitionConstraints?.deviceId !== void 0
2795
- });
2796
- };
2797
- if (preAcquired) logSelectedCamera(preAcquired.stream, preAcquired.fallbackLevel, constraints, true);
3408
+ let cameraStepFacts = {};
2798
3409
  return {
2799
3410
  attemptId: `protected-id-${diagnosticAttempt?.attempt ?? ++protectedIdAttemptSequence}`,
2800
3411
  target,
2801
3412
  workflow,
2802
- streamSource: preAcquired ? {
2803
- kind: "preAcquired",
2804
- stream: preAcquired.stream,
2805
- constraints
2806
- } : {
2807
- kind: "acquire",
2808
- async acquire() {
2809
- await controller.preAcquire();
2810
- const adopted = controller.takePreAcquiredStream();
2811
- if (!adopted) throw new Error("Protected ID stream acquisition was cancelled");
2812
- selectedVideoTrack = adopted.stream.getVideoTracks()[0];
2813
- const reacquisitionConstraints = getCameraReacquisitionConstraints(selectedVideoTrack, adopted.constraints);
2814
- logSelectedCamera(adopted.stream, adopted.fallbackLevel, reacquisitionConstraints, false);
2815
- return {
2816
- stream: adopted.stream,
2817
- constraints: reacquisitionConstraints
2818
- };
2819
- }
3413
+ preflight: captureOnly ? void 0 : () => {
3414
+ const failure = controller.settledMetadataFailure();
3415
+ if (failure) throw failure.error;
3416
+ },
3417
+ cameraStep: async () => {
3418
+ const di = await electDesktopCameraDevice("environment");
3419
+ const hs = controller.takePreAcquiredStream()?.stream;
3420
+ cameraStepFacts = {
3421
+ preAcquired: hs !== void 0,
3422
+ devicePinned: di !== ""
3423
+ };
3424
+ return {
3425
+ vs: "environment",
3426
+ di,
3427
+ ew: 0,
3428
+ eh: 0,
3429
+ i14: isIPhone14OrHigher(),
3430
+ pa: false,
3431
+ hs
3432
+ };
2820
3433
  },
2821
3434
  initiallyBackgrounded: !controller.isVisible(),
2822
3435
  resourceSink: controller.resourceSink,
@@ -2830,13 +3443,11 @@ function createProtectedIdAttemptInput(input) {
2830
3443
  enabled: !captureOnly,
2831
3444
  stepRecording: controller.getStepRecording()
2832
3445
  }),
2833
- releaseUnadoptedStream: stopStream,
2834
- beforeAdopt: captureOnly ? void 0 : async (stream) => {
2835
- const track = stream.getVideoTracks()[0];
2836
- if (!track) throw new Error("Protected ID camera has no selected video track");
3446
+ afterReady: captureOnly ? void 0 : async (displayStream) => {
2837
3447
  const metadata = await controller.prepareMetadata(context);
2838
3448
  if (!isAttemptActive()) return;
2839
- await metadata.checkVirtualCamera(track);
3449
+ const track = displayStream.getVideoTracks()[0];
3450
+ if (track) await metadata.checkVirtualCamera(track);
2840
3451
  },
2841
3452
  onStartupTiming(timing) {
2842
3453
  if (!diagnosticAttempt) return;
@@ -2844,6 +3455,8 @@ function createProtectedIdAttemptInput(input) {
2844
3455
  attempt: diagnosticAttempt.attempt,
2845
3456
  side: diagnosticAttempt.side,
2846
3457
  elapsedMs: Math.round(getTimestamp() - diagnosticAttempt.startedAt),
3458
+ workflow: String(workflow),
3459
+ ...cameraStepFacts,
2847
3460
  ...timing
2848
3461
  });
2849
3462
  },
@@ -2862,12 +3475,6 @@ function createProtectedIdAttemptInput(input) {
2862
3475
  callbacks: callbackSession.callbacks
2863
3476
  });
2864
3477
  },
2865
- async runPrc() {
2866
- if (!isAttemptActive()) return;
2867
- wasmUtil = await (input.getWasmUtil ?? WasmUtilProvider.getInstance)();
2868
- if (!isAttemptActive()) return;
2869
- await wasmUtil.prc();
2870
- },
2871
3478
  async runPoc() {
2872
3479
  if (captureOnly) return;
2873
3480
  if (!isAttemptActive()) return;
@@ -2911,385 +3518,53 @@ function createProtectedIdAttemptInput(input) {
2911
3518
  if (isAttemptActive()) trueSightLog("warning", "deepsight", "idScan", "protected capture diagnostics failed");
2912
3519
  }
2913
3520
  }
2914
- }
2915
- };
2916
- }
2917
- function protectedIdResultToCaptureResponse(result) {
2918
- const regulationType = result.regulationType === "US" || result.regulationType === "Worldwide" || result.regulationType === "Other" || result.regulationType === "US_Illinois" || result.regulationType === "US_Texas" || result.regulationType === "US_California" || result.regulationType === "US_Washington" ? result.regulationType : void 0;
2919
- return {
2920
- sharpness: result.sharpness ?? 0,
2921
- correctSharpness: result.sharpness != null && result.sharpness >= 10,
2922
- glare: result.glare ?? 0,
2923
- correctGlare: result.glare != null && result.glare >= 10,
2924
- horizontalResolution: 0,
2925
- classification: result.classification === true,
2926
- readability: result.readability === true,
2927
- typeOfId: result.typeOfId ?? "",
2928
- issueYear: 0,
2929
- issueName: "",
2930
- sessionStatus: result.sessionStatus ?? "",
2931
- countryCode: result.countryCode ?? "",
2932
- skipBackIdCapture: result.skipBackIdCapture,
2933
- skipGlareFront: result.skipGlareFront,
2934
- skipGlareBack: result.skipGlareBack,
2935
- acceptedDocuments: result.acceptedDocuments ? [...result.acceptedDocuments] : void 0,
2936
- forceFrontIdCapture: result.forceFrontIdCapture,
2937
- idValidationCompleted: result.idValidationCompleted,
2938
- showMandatoryConsent: result.showMandatoryConsent,
2939
- regulationType,
2940
- failReason: result.failReason,
2941
- side: result.side,
2942
- idQualityAttemptApproved: result.idQualityAttemptApproved,
2943
- isDocumentExpired: result.isDocumentExpired,
2944
- success: result.success
2945
- };
2946
- }
2947
- function getProtectedIdUploadRequest(context, sessionToken = getToken()) {
2948
- const target = resolveProtectedIdTarget(context.config, context.currentMode);
2949
- const front = context.currentMode !== "back";
2950
- const params = { captureType: context.manualCaptureTriggered ? "MANUAL" : "AUTO" };
2951
- if (front && context.config.onlyFront === true) params.onlyFront = true;
2952
- if (front && context.config.extractIdFace === false) params.extractIdFace = false;
2953
- const sharpness = context.qualityElements?.sharpness;
2954
- if (sharpness !== void 0 && sharpness !== 0 && Number.isFinite(sharpness)) params.sharpness = getRealQualityValue(sharpness);
2955
- return {
2956
- target,
2957
- config: {
2958
- ...sessionToken ? { headers: { "X-Incode-Hardware-Id": sessionToken } } : {},
2959
- params
2960
- }
2961
- };
2962
- }
2963
- //#endregion
2964
- //#region src/modules/id/digitalIdRegistry.ts
2965
- /**
2966
- * True when a digital-ID method uses a full-page web-redirect flow (Trinsic
2967
- * iDIN/FTN). Accepts both the module `FlowType` value (`REDIRECT`) and the
2968
- * backend value (`WEB_REDIRECT`). (Lives here rather than in
2969
- * `idCaptureHelpers` to keep the registry free of circular imports; the
2970
- * helpers re-export it.)
2971
- */
2972
- function isRedirectFlowType(flowType) {
2973
- return flowType === "REDIRECT" || flowType === "WEB_REDIRECT";
2974
- }
2975
- const DIGITAL_ID_REGISTRY = {
2976
- mDL: [{
2977
- kind: "incodeWallet",
2978
- documentType: "digitalId"
2979
- }, {
2980
- kind: "trinsicRedirect",
2981
- documentType: "digitalIdRedirect",
2982
- providerId: "trinsic_mdl_placeholder",
2983
- method: "MDL"
2984
- }],
2985
- iDIN: [{
2986
- kind: "trinsicRedirect",
2987
- documentType: "digitalIdRedirect",
2988
- providerId: "trinsic_netherlands_idin",
2989
- method: "IDIN"
2990
- }],
2991
- FTN: [{
2992
- kind: "trinsicRedirect",
2993
- documentType: "digitalIdRedirect",
2994
- providerId: "trinsic_finnish_trust_network",
2995
- method: "FTN"
2996
- }]
2997
- };
2998
- const DIGITAL_ID_DOCUMENT_TYPES = Object.keys(DIGITAL_ID_REGISTRY);
2999
- /**
3000
- * Single place that widens `config.digitalIds` to the shapes the backend
3001
- * actually sends — the mapped array or the raw `{ enabled, methods }` object.
3002
- * Shared so the cast is written once.
3003
- */
3004
- function asDigitalIdsConfig(config) {
3005
- return config.digitalIds;
3006
- }
3007
- /**
3008
- * Persisted method name → catalog provider id, derived from the registry's
3009
- * Trinsic entries (single source of truth). Lets the SDK launch iDIN / FTN
3010
- * from a backend that does not yet send `providerId` on each method.
3011
- * TODO(roadmap: fully-catalog-driven): remove once every backend enriches
3012
- * `digitalIds.methods[]` with `providerId` + `flowType`.
3013
- */
3014
- const REDIRECT_PROVIDER_BY_METHOD = (() => {
3015
- const map = {};
3016
- for (const docType of DIGITAL_ID_DOCUMENT_TYPES) for (const entry of DIGITAL_ID_REGISTRY[docType]) if (entry.kind === "trinsicRedirect") map[entry.method] = entry.providerId;
3017
- return map;
3018
- })();
3019
- /**
3020
- * Redirect providers that are the fallback leg of a wallet-first funnel
3021
- * (mDL): they are reached through the `digitalId` tile's funnel resolution,
3022
- * not offered as a standalone chooser card.
3023
- */
3024
- const WALLET_FUNNEL_REDIRECT_PROVIDER_IDS = new Set(DIGITAL_ID_DOCUMENT_TYPES.flatMap((docType) => {
3025
- const entries = DIGITAL_ID_REGISTRY[docType];
3026
- if (!entries.some((entry) => entry.kind === "incodeWallet")) return [];
3027
- return entries.flatMap((entry) => entry.kind === "trinsicRedirect" ? [entry.providerId] : []);
3028
- }));
3029
- /**
3030
- * True for a redirect provider that gets its own chooser card (iDIN, FTN, any
3031
- * catalog-enriched redirect method) — as opposed to the mDL wallet fallback,
3032
- * which only surfaces through the Digital ID tile.
3033
- */
3034
- function isStandaloneRedirectProvider(providerId) {
3035
- return !WALLET_FUNNEL_REDIRECT_PROVIDER_IDS.has(providerId);
3036
- }
3037
- /**
3038
- * The provider id a configured method launches with, when it is a
3039
- * web-redirect method; `undefined` for wallets / other flow shapes.
3040
- *
3041
- * Resolution order:
3042
- * 1. an explicit redirect `flowType` with a `provider` (mapped shape) or
3043
- * `providerId` (catalog-enriched raw shape) — backend-authoritative;
3044
- * 2. otherwise the persisted method name via the registry (legacy raw shape).
3045
- */
3046
- function resolveRedirectProviderId(method) {
3047
- if (method.flowType) {
3048
- if (!isRedirectFlowType(method.flowType)) return;
3049
- const explicit = method.provider ?? method.providerId;
3050
- if (explicit) return explicit;
3051
- }
3052
- return method.method ? REDIRECT_PROVIDER_BY_METHOD[method.method.toUpperCase()] : void 0;
3053
- }
3054
- /**
3055
- * Tolerant view over `config.digitalIds`: accepts both the mapped array
3056
- * (`IdCaptureDigitalIdMethod[]`) and the raw backend object
3057
- * (`{ enabled, methods: [...] }`). Extracted from the old
3058
- * `getDigitalIdRedirectMethod` cast so every consumer parses it the same way.
3059
- *
3060
- * Honors both dashboard toggles: a raw object with `enabled: false` yields no
3061
- * methods, and individual methods with `enabled: false` are dropped (absent
3062
- * `enabled` counts as on). This is what "enabled for the flow / workflow"
3063
- * means — for the redirect chooser cards as much as for the wallet tile.
3064
- */
3065
- function normalizeDigitalIdMethods(config) {
3066
- const raw = asDigitalIdsConfig(config);
3067
- if (!Array.isArray(raw) && raw?.enabled === false) return [];
3068
- return (Array.isArray(raw) ? raw : raw?.methods ?? []).filter((method) => method.enabled !== false);
3069
- }
3070
- /**
3071
- * Persisted method names of the Incode-native device wallets — the backend
3072
- * `DigitalIdMethodCatalog` entries of type `MDL`. A catalog-enriched method
3073
- * carries `type: 'MDL'` instead of relying on the name; both are honoured.
3074
- */
3075
- const DEVICE_WALLET_METHODS = /* @__PURE__ */ new Set([
3076
- "APPLE_WALLET",
3077
- "GOOGLE_WALLET",
3078
- "CA_DMV_WALLET"
3079
- ]);
3080
- /**
3081
- * True for a configured method the native device-wallet handshake can fulfil.
3082
- * Redirect methods (iDIN, FTN) never count, whatever their name or type — they
3083
- * must not surface a wallet tile with no wallet behind it.
3084
- *
3085
- * Classifies by *kind* only. Whether a method is switched on is already
3086
- * settled by `normalizeDigitalIdMethods`, which drops disabled methods before
3087
- * any caller walks the list.
3088
- */
3089
- function isDeviceWalletMethod(method) {
3090
- if (method.flowType && isRedirectFlowType(method.flowType)) return false;
3091
- if (method.type?.toUpperCase() === "MDL") return true;
3092
- return method.method !== void 0 && DEVICE_WALLET_METHODS.has(method.method.toUpperCase());
3093
- }
3094
- /**
3095
- * Whether a device wallet is enabled for this ID-capture config: the coarse
3096
- * `deviceWallet` flag, or an enabled wallet method in `config.digitalIds`.
3097
- *
3098
- * The dashboard persists a wallet only in `digitalIds.methods` and leaves the
3099
- * legacy `deviceWallet` / `appleWallet` booleans at their stored `false`. The
3100
- * backend derives the booleans from `digitalIds` for the flow response, but
3101
- * the workflow-node response historically shipped them raw — so a workflow
3102
- * with Apple Wallet enabled arrived here as `deviceWallet: false`, and the
3103
- * tile was dropped while SDK 1 (which reads `digitalIds` itself) showed it.
3104
- * Mirrors the backend's own `deriveDeviceWalletFlag`, minus its "unknown
3105
- * method counts as a wallet" fallback: an unrecognised method must not
3106
- * launch a handshake that cannot know what to request.
3107
- */
3108
- function isDeviceWalletEnabled(config) {
3109
- if (config.deviceWallet === true) return true;
3110
- return hasEnabledDeviceWalletMethod(config);
3111
- }
3112
- /** Whether a funnel entry is activated by config + platform capabilities. */
3113
- function isEntryActive(entry, config, platform) {
3114
- if (entry.kind === "incodeWallet") return isDeviceWalletEnabled(config) && platform.credentialsAvailable;
3115
- return findConfiguredMethod(entry, config) !== void 0;
3116
- }
3117
- /**
3118
- * The configured `digitalIds` method matching a Trinsic funnel entry — by
3119
- * persisted method name, or (mapped shape) by provider id on a redirect
3120
- * flowType. First match wins; disabled methods are already dropped by
3121
- * `normalizeDigitalIdMethods`.
3122
- */
3123
- function findConfiguredMethod(entry, config) {
3124
- return normalizeDigitalIdMethods(config).find((method) => method.method?.toUpperCase() === entry.method || method.provider === entry.providerId && !!method.flowType && isRedirectFlowType(method.flowType));
3125
- }
3126
- /** Normalizes a raw configured method into the mapped shape for the child input. */
3127
- function toMappedMethod(entry, method) {
3128
- if (method.flowType && isRedirectFlowType(method.flowType)) return method;
3129
- return {
3130
- method: method.method,
3131
- provider: entry.providerId,
3132
- flowType: "WEB_REDIRECT",
3133
- country: method.country ?? method.countries?.[0],
3134
- displayName: method.displayName,
3135
- logoUrl: method.logoUrl
3521
+ }
3136
3522
  };
3137
3523
  }
3138
- /**
3139
- * True when `config.digitalIds` carries a device-wallet method that is switched
3140
- * on, honouring both dashboard toggles: the `digitalIds.enabled` master switch
3141
- * and each method's own `enabled` flag. An absent `enabled` counts as on, the
3142
- * tolerant reading the rest of this module uses.
3143
- *
3144
- * Both toggles are applied by `normalizeDigitalIdMethods`, so this only has to
3145
- * ask whether any surviving method is a wallet.
3146
- */
3147
- function hasEnabledDeviceWalletMethod(config) {
3148
- return normalizeDigitalIdMethods(config).some(isDeviceWalletMethod);
3149
- }
3150
- /**
3151
- * Resolves the implementation that should fulfil a digital-ID document type:
3152
- * the first funnel entry that is active under the given config and platform.
3153
- * `undefined` when nothing can run it (the chooser then shows no tile for it).
3154
- */
3155
- function resolveDigitalIdImplementation(docType, config, platform) {
3156
- for (const entry of DIGITAL_ID_REGISTRY[docType]) {
3157
- if (!isEntryActive(entry, config, platform)) continue;
3158
- if (entry.kind === "incodeWallet") return { kind: "incodeWallet" };
3159
- const method = findConfiguredMethod(entry, config);
3160
- return {
3161
- kind: "trinsicRedirect",
3162
- providerId: entry.providerId,
3163
- method: method ? toMappedMethod(entry, method) : void 0
3164
- };
3165
- }
3166
- }
3167
- //#endregion
3168
- //#region src/modules/id/idCaptureHelpers.ts
3169
- /**
3170
- * Normalizes a configured method into the mapped redirect shape for a
3171
- * resolved provider. The already-mapped shape is returned as-is; the raw
3172
- * backend shape gets `provider` + `WEB_REDIRECT` filled in.
3173
- */
3174
- function toRedirectMethod(method, provider) {
3175
- if (method.provider && method.flowType) return method;
3524
+ function protectedIdResultToCaptureResponse(result) {
3525
+ const regulationType = result.regulationType === "US" || result.regulationType === "Worldwide" || result.regulationType === "Other" || result.regulationType === "US_Illinois" || result.regulationType === "US_Texas" || result.regulationType === "US_California" || result.regulationType === "US_Washington" ? result.regulationType : void 0;
3176
3526
  return {
3177
- method: method.method,
3178
- provider,
3179
- flowType: "WEB_REDIRECT",
3180
- country: method.country ?? method.countries?.[0],
3181
- displayName: method.displayName,
3182
- logoUrl: method.logoUrl
3527
+ sharpness: result.sharpness ?? 0,
3528
+ correctSharpness: result.sharpness != null && result.sharpness >= 10,
3529
+ glare: result.glare ?? 0,
3530
+ correctGlare: result.glare != null && result.glare >= 10,
3531
+ horizontalResolution: 0,
3532
+ classification: result.classification === true,
3533
+ readability: result.readability === true,
3534
+ typeOfId: result.typeOfId ?? "",
3535
+ issueYear: 0,
3536
+ issueName: "",
3537
+ sessionStatus: result.sessionStatus ?? "",
3538
+ countryCode: result.countryCode ?? "",
3539
+ skipBackIdCapture: result.skipBackIdCapture,
3540
+ skipGlareFront: result.skipGlareFront,
3541
+ skipGlareBack: result.skipGlareBack,
3542
+ acceptedDocuments: result.acceptedDocuments ? [...result.acceptedDocuments] : void 0,
3543
+ forceFrontIdCapture: result.forceFrontIdCapture,
3544
+ idValidationCompleted: result.idValidationCompleted,
3545
+ showMandatoryConsent: result.showMandatoryConsent,
3546
+ regulationType,
3547
+ failReason: result.failReason,
3548
+ side: result.side,
3549
+ idQualityAttemptApproved: result.idQualityAttemptApproved,
3550
+ isDocumentExpired: result.isDocumentExpired,
3551
+ success: result.success
3183
3552
  };
3184
3553
  }
3185
- /**
3186
- * The enabled web-redirect digital-ID method to launch — the one matching
3187
- * `providerId` when given (a chooser card was picked), else the first
3188
- * configured redirect method — or `undefined` when none is configured.
3189
- * Drives the provider and country passed to the `digitalIdRedirectMachine`.
3190
- *
3191
- * Accepts both the mapped array (`IdCaptureDigitalIdMethod[]`) and the raw
3192
- * backend `configuration.digitalIds` object (`{ enabled, methods: [...] }`);
3193
- * for the raw shape the provider comes from the backend-enriched
3194
- * `providerId`/`flowType` when present, else from the persisted method name
3195
- * via the digital-ID registry (`IDIN` → `trinsic_netherlands_idin`).
3196
- */
3197
- function getDigitalIdRedirectMethod(config, providerId) {
3198
- for (const method of normalizeDigitalIdMethods(config)) {
3199
- const provider = resolveRedirectProviderId(method);
3200
- if (!provider || providerId !== void 0 && provider !== providerId) continue;
3201
- return toRedirectMethod(method, provider);
3202
- }
3203
- }
3204
- /**
3205
- * The digital-ID web-redirect providers that get their own chooser card: one
3206
- * per enabled redirect method in `config.digitalIds`, in backend (dashboard)
3207
- * order, deduped by provider. Wallet-funnel fallbacks (the Trinsic mDL leg)
3208
- * are excluded — they surface through the Digital ID tile instead.
3209
- *
3210
- * Card display data (`displayName`, `logoUrl`, `country`) is whatever the
3211
- * backend enriched the method with; the UI falls back to generic copy / icon
3212
- * when absent.
3213
- */
3214
- function getAvailableDigitalIdRedirectOptions(config) {
3215
- const options = [];
3216
- for (const method of normalizeDigitalIdMethods(config)) {
3217
- const providerId = resolveRedirectProviderId(method);
3218
- if (!providerId || !isStandaloneRedirectProvider(providerId) || options.some((option) => option.providerId === providerId)) continue;
3219
- options.push({
3220
- providerId,
3221
- method: method.method,
3222
- displayName: method.displayName,
3223
- logoUrl: method.logoUrl,
3224
- country: method.country ?? method.countries?.[0]
3225
- });
3226
- }
3227
- return options;
3228
- }
3229
- /**
3230
- * Map of config properties received from the backend to adjusted, internal document types.
3231
- */
3232
- const DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP = [
3233
- ["enableId", "id"],
3234
- ["enablePassport", "passport"],
3235
- ["digitalIdsUpload", "digitalIdUpload"]
3236
- ];
3237
- /**
3238
- * Returns the list of document types enabled by config for the chooser screen, in display order.
3239
- * Used to populate chooser state so UI and headless consumers can render the correct options.
3240
- *
3241
- * Digital-ID document types (device wallet, Trinsic web-redirect) come from
3242
- * the digital-ID registry funnel: each registry document type contributes the
3243
- * tile of its first active implementation. A `deviceWallet: true` config on a
3244
- * platform without the Credentials API therefore shows the Trinsic fallback
3245
- * tile when one is configured — or no tile at all, instead of a dead-end one.
3246
- *
3247
- * @param config - ID capture configuration (from flow or init)
3248
- * @param platform - Platform capabilities consulted by the digital-ID funnel.
3249
- * Defaults to no Credentials API for pure-node callers; the machine passes
3250
- * the real capability check.
3251
- * @returns Array of IdDocumentType values that should be shown in the document type chooser
3252
- */
3253
- function getAvailableDocumentTypes(config, platform = { credentialsAvailable: false }) {
3254
- const adjustedDocumentTypes = [];
3255
- for (const [configProperty, adjustedType] of DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP) if (config[configProperty]) adjustedDocumentTypes.push(adjustedType);
3256
- for (const docType of DIGITAL_ID_DOCUMENT_TYPES) {
3257
- const route = resolveDigitalIdImplementation(docType, config, platform);
3258
- if (!route) continue;
3259
- const documentType = route.kind === "incodeWallet" ? "digitalId" : "digitalIdRedirect";
3260
- if (!adjustedDocumentTypes.includes(documentType)) adjustedDocumentTypes.push(documentType);
3261
- }
3262
- if (!adjustedDocumentTypes.includes("digitalIdRedirect") && getAvailableDigitalIdRedirectOptions(config).length > 0) adjustedDocumentTypes.push("digitalIdRedirect");
3263
- return adjustedDocumentTypes;
3264
- }
3265
- /**
3266
- * Computes `idCaptureMachine`'s terminal output — the downstream module-skip
3267
- * signal read by the Flow orchestrator (via `runChildModule`'s `MODULE_COMPLETE`).
3268
- *
3269
- * `skipFaceMatch` is set ONLY for the US Smart Capture *camera back-only* path:
3270
- * a back image was captured on-device (`capturedImages.back`) and no front was
3271
- * (`!capturedImages.front`) — "no front, no ID face, no match".
3272
- *
3273
- * Requiring a captured back is deliberate and load-bearing: the digital-ID
3274
- * upload path submits a full ID (front face present) but does NOT
3275
- * populate `capturedImages` (only the camera path does). Gating on a captured
3276
- * back excludes those upload paths so a real ID-vs-selfie match is never
3277
- * silently skipped. `capturedImages.front`/`forceFrontIdCapture` alone are not
3278
- * enough (a later front upload clears the request; uploads set neither field).
3279
- *
3280
- * Always `false` outside US Smart Capture. The selfie/face capture itself is
3281
- * unaffected — only the ID-vs-selfie match is skipped.
3282
- *
3283
- * Also `true` on the Digital ID web-redirect (Trinsic iDIN/FTN) COMPLETED path
3284
- * when the scheme returned no portrait (`isDigitalIdRedirect && !portraitPresent`,
3285
- * FM-1/FM-2): there is no ID face to match the selfie against.
3286
- */
3287
- function computeIdCaptureOutput(context) {
3288
- const frontIdCaptured = Boolean(context.capturedImages.front);
3289
- const backIdCaptured = Boolean(context.capturedImages.back);
3554
+ function getProtectedIdUploadRequest(context, sessionToken = getToken()) {
3555
+ const target = resolveProtectedIdTarget(context.config, context.currentMode);
3556
+ const front = context.currentMode !== "back";
3557
+ const params = { captureType: context.manualCaptureTriggered ? "MANUAL" : "AUTO" };
3558
+ if (front && context.config.onlyFront === true) params.onlyFront = true;
3559
+ if (front && context.config.extractIdFace === false) params.extractIdFace = false;
3560
+ const sharpness = context.qualityElements?.sharpness;
3561
+ if (sharpness !== void 0 && sharpness !== 0 && Number.isFinite(sharpness)) params.sharpness = getRealQualityValue(sharpness);
3290
3562
  return {
3291
- frontIdCaptured,
3292
- skipFaceMatch: context.isDigitalIdRedirect === true && context.portraitPresent !== true || context.config.usSmartCapture === true && backIdCaptured && !frontIdCaptured
3563
+ target,
3564
+ config: {
3565
+ ...sessionToken ? { headers: { "X-Incode-Hardware-Id": sessionToken } } : {},
3566
+ params
3567
+ }
3293
3568
  };
3294
3569
  }
3295
3570
  //#endregion
@@ -3834,12 +4109,8 @@ const idCaptureMachine = setup({
3834
4109
  digitalUploadMachine,
3835
4110
  digitalIdRedirectMachine,
3836
4111
  deviceWalletMachine,
3837
- readPendingDigitalIdRedirect: fromPromise(async ({ input }) => {
3838
- const pending = await readPendingRedirect(input.storage);
3839
- if (!pending) return null;
3840
- await clearPendingRedirect(input.storage);
3841
- return pending;
3842
- })
4112
+ readPendingDigitalIdRedirect: fromPromise(({ input }) => readPendingRedirect(input.storage)),
4113
+ detectCountries: fromPromise(({ input, signal }) => detectDigitalIdCountries(input.dependencies, { signal }))
3843
4114
  },
3844
4115
  actions: {
3845
4116
  attachProtectedController: assign(({ self }) => {
@@ -3847,7 +4118,7 @@ const idCaptureMachine = setup({
3847
4118
  return {};
3848
4119
  }),
3849
4120
  startProtectedMetadataPreparation: ({ context, self }) => {
3850
- if (!hasOnCaptureCallback(context.config)) getIdProtectedCaptureController(self).startMetadataPreparation(context);
4121
+ getIdProtectedCaptureController(self).startMetadataPreparation(context);
3851
4122
  },
3852
4123
  bindProtectedControllerLifetime: sendTo("protectedControllerLifetime", ({ self }) => ({
3853
4124
  type: "BIND_PROTECTED_ID_CONTROLLER",
@@ -4229,7 +4500,35 @@ const idCaptureMachine = setup({
4229
4500
  * it runs inside the tile click's `send()`, preserving the transient
4230
4501
  * user activation `navigator.credentials.get()` needs on iOS Safari.
4231
4502
  */
4232
- resolveDigitalIdRoute: assign(({ context }) => ({ digitalIdRoute: resolveDigitalIdImplementation("mDL", context.config, { credentialsAvailable: context.dependencies?.credentials?.isAvailable() ?? false }) })),
4503
+ resolveDigitalIdRoute: assign(({ context }) => ({ digitalIdRoute: resolveDigitalIdImplementation("mDL", context.config, getDigitalIdPlatformSupport(context.dependencies?.credentials)) })),
4504
+ /**
4505
+ * Stores the detected countries and re-ranks the redirect options by them
4506
+ * (`getAvailableDigitalIdRedirectOptions`). The option *set* is unchanged —
4507
+ * country only reorders.
4508
+ */
4509
+ storeDetectedCountries: assign(({ context, event }) => {
4510
+ const countries = event.output ?? [];
4511
+ return {
4512
+ detectedCountries: countries,
4513
+ digitalIdRedirectOptions: getAvailableDigitalIdRedirectOptions(context.config, countries)
4514
+ };
4515
+ }),
4516
+ /**
4517
+ * The user picked a country on the chooser: it becomes the strongest
4518
+ * country, the detected ones stay behind it as tiebreakers, and the
4519
+ * redirect options are re-ranked. An invalid code is ignored.
4520
+ */
4521
+ setChooserCountry: assign(({ context, event }) => {
4522
+ const country = event.type === "SET_CHOOSER_COUNTRY" ? normalizeCountryCode(event.country) : void 0;
4523
+ if (!country) return {};
4524
+ const countries = [country, ...(context.detectedCountries ?? []).filter((detected) => detected !== country)];
4525
+ return {
4526
+ detectedCountries: countries,
4527
+ digitalIdRedirectOptions: rankDigitalIdRedirectOptions(context.digitalIdRedirectOptions, context.config, countries)
4528
+ };
4529
+ }),
4530
+ /** Detection failed outright: mark it done so it is not retried. */
4531
+ markCountryDetectionFailed: assign({ detectedCountries: () => [] }),
4233
4532
  /**
4234
4533
  * Records a completed device-wallet (mDL) handshake from the child's
4235
4534
  * `onDone` output. Wallet credentials are single-side; the verified
@@ -4271,6 +4570,13 @@ const idCaptureMachine = setup({
4271
4570
  digitalIdResumeProviderId: () => void 0,
4272
4571
  digitalIdRoute: () => void 0
4273
4572
  }),
4573
+ /**
4574
+ * Drops the persisted return-leg record once the digital-ID attempt ends.
4575
+ * Fire-and-forget: a stale record is only read on the host's return route.
4576
+ */
4577
+ clearPendingDigitalIdRedirect: ({ context }) => {
4578
+ clearPendingRedirect(resolveIdCaptureDependencies(context.dependencies).storage).catch(() => void 0);
4579
+ },
4274
4580
  incrementProcessingExpiredAttempts: assign(({ context }) => ({ processingExpiredAttempts: context.processingExpiredAttempts + 1 })),
4275
4581
  setSkipProcessId: assign({ skipProcessId: () => true }),
4276
4582
  setExpiredFromUpload: assign({ expiredFromUpload: () => true }),
@@ -4283,10 +4589,15 @@ const idCaptureMachine = setup({
4283
4589
  isCaptureOnlyDelivery: ({ context }) => hasOnCaptureCallback(context.config),
4284
4590
  isProtectedUploadFailure: ({ event }) => protectedFailure(event)?.failure.stage === "upload",
4285
4591
  isProtectedManualRefusal: ({ event }) => protectedFailure(event)?.failure.stage === "manualCommit",
4592
+ isProtectedAcquireDenied: ({ event }) => {
4593
+ const failure = protectedFailure(event)?.failure;
4594
+ return failure?.stage === "acquire" && isCameraDenialErrorName(failure.errorName);
4595
+ },
4286
4596
  canCaptureManuallyDuringDetection: ({ context }) => context.config.showCaptureButtonInAuto === true && context.detectionStatus !== "capturing",
4287
4597
  hasShowTutorial: hasShowTutorialGuard,
4288
4598
  hasAgeAssurance: hasAgeAssuranceGuard,
4289
4599
  hasShowDocumentChooser: hasShowDocumentChooserGuard,
4600
+ needsCountryDetection: needsCountryDetectionGuard,
4290
4601
  isPermissionGranted: ({ event }) => isPermissionGrantedGuard({ event: asPublicIdEvent(event) }),
4291
4602
  isReadyForCapture: ({ context, event }) => isReadyForCaptureGuard({
4292
4603
  context,
@@ -4383,9 +4694,22 @@ const idCaptureMachine = setup({
4383
4694
  },
4384
4695
  context: ({ input, self }) => {
4385
4696
  attachIdProtectedCaptureController(self, createIdProtectedCaptureController());
4697
+ const carried = carryAttempts(input.config.isSecondId ? "secondIdCapture" : "idCapture", self, (s, previous) => {
4698
+ const c = s.context;
4699
+ const child = s.children.digitalIdUpload?.getSnapshot()?.context;
4700
+ const left = Math.min(previous.attemptsRemaining ?? Infinity, c.attemptsRemaining, child?.attemptsRemaining ?? Infinity);
4701
+ return {
4702
+ attemptsRemaining: s.matches("expiredExhausted") || left <= 0 && left < c.config.captureAttempts ? -1 : left,
4703
+ expiredAttempts: Math.max(previous.expiredAttempts ?? 0, c.expiredAttempts),
4704
+ expiredRedirected: c.expiredRedirected,
4705
+ processingExpiredAttempts: c.processingExpiredAttempts,
4706
+ skipProcessId: previous.skipProcessId === true || c.skipProcessId || s.matches("expiredExhausted") && !shouldProcessAfterExhaustionGuard({ context: c })
4707
+ };
4708
+ });
4709
+ const configured = input.config.captureAttempts ?? 1;
4386
4710
  const config = {
4387
4711
  ...input.config,
4388
- captureAttempts: input.config.captureAttempts ?? 1
4712
+ captureAttempts: Math.max(0, Math.min(configured, carried.attemptsRemaining ?? configured))
4389
4713
  };
4390
4714
  const currentMode = input.config.onlyBack ? "back" : !input.config.enableId && input.config.enablePassport ? "passport" : input.config.usSmartCapture ? "back" : "front";
4391
4715
  return {
@@ -4409,11 +4733,11 @@ const idCaptureMachine = setup({
4409
4733
  barcodeFastPathAttempted: false,
4410
4734
  barcodeFastPathCaptured: false,
4411
4735
  recordingSession: void 0,
4412
- attemptsRemaining: config.captureAttempts,
4413
- expiredAttempts: 0,
4414
- expiredRedirected: false,
4415
- processingExpiredAttempts: 0,
4416
- skipProcessId: input.config.skipProcessId === true,
4736
+ attemptsRemaining: Math.min(config.captureAttempts, carried.attemptsRemaining ?? Infinity),
4737
+ expiredAttempts: carried.expiredAttempts ?? 0,
4738
+ expiredRedirected: carried.expiredRedirected ?? false,
4739
+ processingExpiredAttempts: carried.processingExpiredAttempts ?? 0,
4740
+ skipProcessId: input.config.skipProcessId === true || (carried.attemptsRemaining ?? 0) < 0 && carried.skipProcessId === true,
4417
4741
  expiredFromUpload: false,
4418
4742
  isDigitalUpload: false,
4419
4743
  isDigitalIdRedirect: false,
@@ -4442,8 +4766,10 @@ const idCaptureMachine = setup({
4442
4766
  dependencies: resolveIdCaptureDependencies(input.dependencies),
4443
4767
  disableIpify: getDisableIpify(),
4444
4768
  deepsightInitAttempted: false,
4445
- availableDocumentTypes: getAvailableDocumentTypes(input.config, { credentialsAvailable: input.dependencies?.credentials?.isAvailable() ?? false }),
4769
+ availableDocumentTypes: getAvailableDocumentTypes(input.config, getDigitalIdPlatformSupport(input.dependencies?.credentials)),
4446
4770
  digitalIdRedirectOptions: getAvailableDigitalIdRedirectOptions(input.config),
4771
+ detectedCountries: void 0,
4772
+ walletDevice: resolveWalletDevice(),
4447
4773
  selectedDigitalIdProviderId: void 0,
4448
4774
  captureResolution: void 0,
4449
4775
  cameraFallbackLevel: void 0,
@@ -4460,11 +4786,20 @@ const idCaptureMachine = setup({
4460
4786
  target: "digitalIdRedirectReturning",
4461
4787
  guard: "hasDigitalIdReturn"
4462
4788
  },
4789
+ {
4790
+ target: "processing",
4791
+ guard: ({ context }) => context.attemptsRemaining < 0,
4792
+ actions: ["flagIdManualReview", "setForceFinishAfterProcessing"]
4793
+ },
4463
4794
  {
4464
4795
  target: "error",
4465
4796
  guard: "hasNoDocumentTypesAvailable",
4466
4797
  actions: [() => console.error(ID_CAPTURE_NO_DOCUMENT_TYPES_ERROR), assign({ error: () => ID_CAPTURE_NO_DOCUMENT_TYPES_ERROR })]
4467
4798
  },
4799
+ {
4800
+ target: "detectingCountry",
4801
+ guard: and(["hasShowDocumentChooser", "needsCountryDetection"])
4802
+ },
4468
4803
  {
4469
4804
  target: "chooser",
4470
4805
  guard: "hasShowDocumentChooser"
@@ -4479,37 +4814,53 @@ const idCaptureMachine = setup({
4479
4814
  },
4480
4815
  { target: "loading" }
4481
4816
  ] } },
4482
- chooser: { on: { SELECT_DOCUMENT: [
4483
- {
4484
- target: "digitalIdRouting",
4485
- guard: "isDigitalIdSelected",
4486
- actions: ["setSelectedDocument", "resolveDigitalIdRoute"]
4487
- },
4488
- {
4489
- target: "digitalIdRedirect",
4490
- guard: "isDigitalIdRedirectSelected",
4491
- actions: ["setSelectedDocument"]
4492
- },
4493
- {
4494
- target: "digitalIdUpload",
4495
- guard: "isDigitalIdUploadSelected",
4496
- actions: ["setSelectedDocument"]
4497
- },
4498
- {
4499
- target: "ageVerification",
4500
- guard: "hasAgeAssurance",
4501
- actions: ["setSelectedDocument", "setCurrentMode"]
4502
- },
4503
- {
4504
- target: "tutorial",
4505
- guard: "hasShowTutorial",
4506
- actions: ["setSelectedDocument", "setCurrentMode"]
4817
+ detectingCountry: { invoke: {
4818
+ id: "detectCountries",
4819
+ src: "detectCountries",
4820
+ input: ({ context }) => ({ dependencies: context.dependencies?.countryDetection ?? {} }),
4821
+ onDone: {
4822
+ target: "chooser",
4823
+ actions: "storeDetectedCountries"
4507
4824
  },
4508
- {
4509
- target: "loading",
4510
- actions: ["setSelectedDocument", "setCurrentMode"]
4825
+ onError: {
4826
+ target: "chooser",
4827
+ actions: "markCountryDetectionFailed"
4511
4828
  }
4512
- ] } },
4829
+ } },
4830
+ chooser: { on: {
4831
+ SET_CHOOSER_COUNTRY: { actions: "setChooserCountry" },
4832
+ SELECT_DOCUMENT: [
4833
+ {
4834
+ target: "digitalIdRouting",
4835
+ guard: "isDigitalIdSelected",
4836
+ actions: ["setSelectedDocument", "resolveDigitalIdRoute"]
4837
+ },
4838
+ {
4839
+ target: "digitalIdRedirect",
4840
+ guard: "isDigitalIdRedirectSelected",
4841
+ actions: ["setSelectedDocument"]
4842
+ },
4843
+ {
4844
+ target: "digitalIdUpload",
4845
+ guard: "isDigitalIdUploadSelected",
4846
+ actions: ["setSelectedDocument"]
4847
+ },
4848
+ {
4849
+ target: "ageVerification",
4850
+ guard: "hasAgeAssurance",
4851
+ actions: ["setSelectedDocument", "setCurrentMode"]
4852
+ },
4853
+ {
4854
+ target: "tutorial",
4855
+ guard: "hasShowTutorial",
4856
+ actions: ["setSelectedDocument", "setCurrentMode"]
4857
+ },
4858
+ {
4859
+ target: "loading",
4860
+ actions: ["setSelectedDocument", "setCurrentMode"]
4861
+ }
4862
+ ]
4863
+ } },
4513
4864
  ageVerification: {
4514
4865
  entry: "startProtectedMetadataPreparation",
4515
4866
  on: { NEXT_STEP: [{
@@ -4824,6 +5175,11 @@ const idCaptureMachine = setup({
4824
5175
  guard: "isProtectedUploadFailure",
4825
5176
  actions: "setProtectedUploadFailure"
4826
5177
  },
5178
+ {
5179
+ target: "#idCapture.permissions.denied",
5180
+ guard: "isProtectedAcquireDenied",
5181
+ actions: assign({ permissionResult: () => "denied" })
5182
+ },
4827
5183
  {
4828
5184
  target: "#idCapture.error",
4829
5185
  actions: "setProtectedFailure"
@@ -5475,6 +5831,11 @@ const idCaptureMachine = setup({
5475
5831
  target: "digitalIdRedirect",
5476
5832
  actions: ["storePendingDigitalIdRedirect"]
5477
5833
  },
5834
+ {
5835
+ target: "detectingCountry",
5836
+ guard: and(["hasShowDocumentChooser", "needsCountryDetection"]),
5837
+ actions: ["clearDigitalIdAttempt"]
5838
+ },
5478
5839
  {
5479
5840
  target: "chooser",
5480
5841
  guard: "hasShowDocumentChooser",
@@ -5485,14 +5846,22 @@ const idCaptureMachine = setup({
5485
5846
  actions: ["clearDigitalIdAttempt"]
5486
5847
  }
5487
5848
  ],
5488
- onError: [{
5489
- target: "chooser",
5490
- guard: "hasShowDocumentChooser",
5491
- actions: ["clearDigitalIdAttempt"]
5492
- }, {
5493
- target: "loading",
5494
- actions: ["clearDigitalIdAttempt"]
5495
- }]
5849
+ onError: [
5850
+ {
5851
+ target: "detectingCountry",
5852
+ guard: and(["hasShowDocumentChooser", "needsCountryDetection"]),
5853
+ actions: ["clearDigitalIdAttempt"]
5854
+ },
5855
+ {
5856
+ target: "chooser",
5857
+ guard: "hasShowDocumentChooser",
5858
+ actions: ["clearDigitalIdAttempt"]
5859
+ },
5860
+ {
5861
+ target: "loading",
5862
+ actions: ["clearDigitalIdAttempt"]
5863
+ }
5864
+ ]
5496
5865
  },
5497
5866
  on: { QUIT: { target: "closed" } }
5498
5867
  },
@@ -5525,17 +5894,26 @@ const idCaptureMachine = setup({
5525
5894
  {
5526
5895
  guard: "isDigitalIdRedirectCompleted",
5527
5896
  target: "#idCapture.finished",
5528
- actions: ["storeDigitalIdRedirectResult"]
5897
+ actions: ["storeDigitalIdRedirectResult", "clearPendingDigitalIdRedirect"]
5898
+ },
5899
+ {
5900
+ target: "detectingCountry",
5901
+ guard: and(["hasShowDocumentChooser", "needsCountryDetection"]),
5902
+ actions: ["clearPendingDigitalIdRedirect"]
5529
5903
  },
5530
5904
  {
5531
5905
  target: "chooser",
5532
- guard: "hasShowDocumentChooser"
5906
+ guard: "hasShowDocumentChooser",
5907
+ actions: ["clearPendingDigitalIdRedirect"]
5533
5908
  },
5534
- { target: "closed" }
5909
+ {
5910
+ target: "closed",
5911
+ actions: ["clearPendingDigitalIdRedirect"]
5912
+ }
5535
5913
  ],
5536
5914
  onError: {
5537
5915
  target: "#idCapture.error",
5538
- actions: assign({ error: ({ event }) => String(event.error) })
5916
+ actions: [assign({ error: ({ event }) => String(event.error) }), "clearPendingDigitalIdRedirect"]
5539
5917
  }
5540
5918
  },
5541
5919
  on: {
@@ -5615,4 +5993,4 @@ function provideIdProtectedCaptureController(machine, controller) {
5615
5993
  });
5616
5994
  }
5617
5995
  //#endregion
5618
- export { mapDeviceWalletScreenName as _, isRedirectFlowType as a, createIdCaptureOnlyDeliveryActor as c, captureOnlyNeedsBack as d, hasOnCaptureCallback as f, BrowserDigitalCredentialsProvider as g, createDeviceWalletManager as h, DIGITAL_ID_REGISTRY as i, createIdProtectedCaptureController as l, renderWallet as m, provideIdProtectedCaptureController as n, resolveDigitalIdImplementation as o, pickIdCaptureOnlyConfig as p, DIGITAL_ID_DOCUMENT_TYPES as r, attachIdProtectedCaptureController as s, idCaptureMachine as t, findIdProtectedCaptureController as u, resolveWalletPlatform as v };
5996
+ export { mapDeviceWalletScreenName as _, createIdProtectedCaptureController as a, hasOnCaptureCallback as c, DIGITAL_ID_REGISTRY as d, isRedirectFlowType as f, BrowserDigitalCredentialsProvider as g, createDeviceWalletManager as h, createIdCaptureOnlyDeliveryActor as i, pickIdCaptureOnlyConfig as l, renderWallet as m, provideIdProtectedCaptureController as n, findIdProtectedCaptureController as o, resolveDigitalIdImplementation as p, attachIdProtectedCaptureController as r, captureOnlyNeedsBack as s, idCaptureMachine as t, DIGITAL_ID_DOCUMENT_TYPES as u, resolveWalletPlatform as v };