@incodetech/core 2.3.2 → 2.4.0-rc.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.
- package/THIRD_PARTY_NOTICES.txt +1243 -3
- package/dist/Actor-DpTj5PFb.d.ts +1 -0
- package/dist/{BaseWasmProvider-Dyi6dKp1.d.ts → BaseWasmProvider-Bq3OHo7P.d.ts} +2 -2
- package/dist/BrowserDiagnosticsEnvelopeProvider-BQca6KPG.esm.js +43 -0
- package/dist/{FaceDetectionProvider-DtmtCKa9.esm.js → FaceDetectionProvider-BIImDZrc.esm.js} +125 -10
- package/dist/HttpRequestError-Bh0pNGSC.esm.js +35 -0
- package/dist/{IIdCaptureCapability-RNiFhvXR.d.ts → IIdCaptureCapability-CGcEt2Cw.d.ts} +2 -2
- package/dist/{IWasmUtilCapability-CNWRl7jr.d.ts → IWasmUtilCapability-GF2n7sfm.d.ts} +28 -5
- package/dist/{Manager-CQQ99QOI.d.ts → Manager-C9T5amUN.d.ts} +7 -1
- package/dist/{MotionSensorProvider-DyhbM4Si.esm.js → MotionSensorProvider-DYxh8TjR.esm.js} +1 -1
- package/dist/{ekycStateMachine-UeJRO8_p.esm.js → PhoneValidationProvider-SZiOS0jB.esm.js} +232 -827
- package/dist/{StreamCanvasCapture-_8gdW5Lk.d.ts → StreamCanvasCapture-7JRf-2ck.d.ts} +2 -2
- package/dist/{safeStorage-BdU9_m2E.esm.js → WasmUtilProvider-DtJuBdt-.esm.js} +111 -49
- package/dist/{addressSearch-DyHGgeX8.esm.js → addressSearch-DPjIKJrX.esm.js} +142 -4
- package/dist/{advanceableErrors-CpF2cBy6.esm.js → advanceableErrors-q_pfU3Cn.esm.js} +5 -4
- package/dist/ae-signature.d.ts +2 -2
- package/dist/ae-signature.esm.js +1 -1
- package/dist/antifraud.d.ts +1 -1
- package/dist/antifraud.esm.js +2 -2
- package/dist/{antifraudManager-DNkw66oW.esm.js → antifraudManager-CaweCYnY.esm.js} +3 -3
- package/dist/{antifraudManager-BY36bS12.d.ts → antifraudManager-DbGCvlJs.d.ts} +2 -2
- package/dist/{antifraudStateMachine-DBeq47D2.esm.js → antifraudStateMachine-DRl0UVyA.esm.js} +3 -4
- package/dist/{endpoints-B-3Q-LUw.esm.js → api-Cz90EHyu.esm.js} +151 -1
- package/dist/{apiError-CmGEmaGU.esm.js → apiError-D5u6HIDG.esm.js} +2 -1
- package/dist/authentication.d.ts +3 -3
- package/dist/authentication.esm.js +2 -2
- package/dist/{authenticationManager-CboRCl_N.d.ts → authenticationManager-BIZC55Bi.d.ts} +2 -8
- package/dist/{authenticationManager-BFjSjtQ_.esm.js → authenticationManager-CB3YW6EK.esm.js} +6 -6
- package/dist/{authenticationStateMachine-Dfo34ZiI.esm.js → authenticationStateMachine-BJJhLmdH.esm.js} +5 -6
- package/dist/avatar.d.ts +1 -1
- package/dist/{backCameraStream-B0-YgP_y.esm.js → backCameraStream-CMvXj4X4.esm.js} +1 -1
- package/dist/camera.esm.js +1 -1
- package/dist/certificate-issuance.d.ts +1 -1
- package/dist/certificate-issuance.esm.js +2 -2
- package/dist/{certificateIssuanceManager-C3-CI0_s.esm.js → certificateIssuanceManager-BfeMv2PU.esm.js} +3 -3
- package/dist/{certificateIssuanceManager-DCgEidHz.d.ts → certificateIssuanceManager-Dr8A4Lgr.d.ts} +2 -3
- package/dist/{certificateIssuanceStateMachine-CxqS_nD-.esm.js → certificateIssuanceStateMachine-Frgjbjw8.esm.js} +4 -5
- package/dist/consent.d.ts +1 -1
- package/dist/consent.esm.js +2 -2
- package/dist/{consentManager-B6E1XJDw.esm.js → consentManager-CvEu8h_W.esm.js} +3 -3
- package/dist/{consentManager-2h_w6wFc.d.ts → consentManager-Cv_0QKLD.d.ts} +7 -8
- package/dist/{consentStateMachine-DTSfdGiW.esm.js → consentStateMachine-DJTgN_-1.esm.js} +3 -4
- package/dist/{createCameraCycleOwnership-DnwTl1ad.esm.js → createCameraCycleOwnership-Dj_LHUvN.esm.js} +71 -66
- package/dist/{createFaceAvatar-BlcTYgJv.d.ts → createFaceAvatar-lYX0VTYs.d.ts} +1 -1
- package/dist/cross-document-data-match.d.ts +1 -1
- package/dist/cross-document-data-match.esm.js +1 -1
- package/dist/{crossDocumentDataMatchManager-9XhFVZ5S.esm.js → crossDocumentDataMatchManager-Cu141CE8.esm.js} +4 -5
- package/dist/{crossDocumentDataMatchManager-Dq8Z3SOg.d.ts → crossDocumentDataMatchManager-yCWCOzcU.d.ts} +2 -2
- package/dist/curp-validation.d.ts +1 -1
- package/dist/curp-validation.esm.js +2 -2
- package/dist/{curpValidationManager-DbIMYFcJ.esm.js → curpValidationManager-B-z9q5V3.esm.js} +15 -22
- package/dist/{curpValidationManager-DNuZn9fn.d.ts → curpValidationManager-C9sqoh9n.d.ts} +3 -3
- package/dist/{curpValidationStateMachine-g5kMfuLj.esm.js → curpValidationStateMachine-vDEFLMPw.esm.js} +4 -5
- package/dist/custom-fields.d.ts +1 -1
- package/dist/custom-fields.esm.js +1 -1
- package/dist/custom-watchlist.d.ts +1 -1
- package/dist/custom-watchlist.esm.js +2 -2
- package/dist/{customFieldsManager-8-W2KY4n.d.ts → customFieldsManager-CF-cO8ap.d.ts} +2 -2
- package/dist/{customFieldsManager-CzWZTkW-.esm.js → customFieldsManager-D1ex2cFM.esm.js} +4 -5
- package/dist/{customWatchlistManager-DWTED5Ur.esm.js → customWatchlistManager-CTI-SGk0.esm.js} +3 -3
- package/dist/{customWatchlistManager-PBWHr_oM.d.ts → customWatchlistManager-DolUswyR.d.ts} +2 -2
- package/dist/{customWatchlistStateMachine-DOQou6TW.esm.js → customWatchlistStateMachine-hmRd0f2I.esm.js} +3 -4
- package/dist/deepsightLoader-DZMdYSl-.esm.js +55 -0
- package/dist/{deepsightLoader-v-dLejS-.esm.js → deepsightService-tGP53cSS.esm.js} +51 -56
- package/dist/device.esm.js +1 -1
- package/dist/document-capture.d.ts +2 -2
- package/dist/document-capture.esm.js +2 -2
- package/dist/{documentCaptureManager-BRPxqYD2.esm.js → documentCaptureManager-DUJwpKC5.esm.js} +17 -18
- package/dist/{documentCaptureManager-lEtCM320.d.ts → documentCaptureManager-DkyDtm3Y.d.ts} +11 -34
- package/dist/{documentCaptureStateMachine-D312sSIu.esm.js → documentCaptureStateMachine-B8i7GnLh.esm.js} +55 -59
- package/dist/dynamic-forms.d.ts +2 -2
- package/dist/dynamic-forms.esm.js +2 -2
- package/dist/{dynamicFormsManager-C-9Jhnd3.esm.js → dynamicFormsManager-Bxmv_9PB.esm.js} +3 -3
- package/dist/{dynamicFormsManager-D5R_uxLQ.d.ts → dynamicFormsManager-C0dHs1ty.d.ts} +3 -3
- package/dist/{dynamicFormsStateMachine-DGI_F2PP.esm.js → dynamicFormsStateMachine-CoOWTzyM.esm.js} +4 -5
- package/dist/ekyb.d.ts +5 -5
- package/dist/ekyb.esm.js +3 -3
- package/dist/{ekybManager-DeoMcZEz.esm.js → ekybManager-BBkdPxUY.esm.js} +23 -27
- package/dist/{ekybManager-BwRuGAwt.d.ts → ekybManager-BaZ_7CEu.d.ts} +4 -4
- package/dist/{ekybStateMachine-D1IJ1Z72.esm.js → ekybStateMachine-n4Iz9iLc.esm.js} +338 -14
- package/dist/ekyc.d.ts +2 -2
- package/dist/ekyc.esm.js +3 -3
- package/dist/{ekycManager-BX2d46FY.esm.js → ekycManager-BO-Lui3t.esm.js} +29 -36
- package/dist/{ekycManager-DLzDuBzI.d.ts → ekycManager-DW-ynodd.d.ts} +3 -3
- package/dist/ekycStateMachine-CDnI_NRq.esm.js +1443 -0
- package/dist/{ekycUtils-D6wfSpPN.esm.js → ekycUtils-zY8CdKJL.esm.js} +53 -3
- package/dist/electronic-signature.d.ts +1 -1
- package/dist/electronic-signature.esm.js +1 -1
- package/dist/{electronicSignatureManager-yYUc30na.esm.js → electronicSignatureManager-BtWCrz5_.esm.js} +10 -11
- package/dist/{electronicSignatureManager-Ds-KEVTq.d.ts → electronicSignatureManager-DTSLOvKR.d.ts} +2 -3
- package/dist/email.d.ts +1 -1
- package/dist/email.esm.js +2 -2
- package/dist/{emailManager-bR1N5rV_.esm.js → emailManager-ButFktRm.esm.js} +20 -26
- package/dist/{emailManager-CADXW_9X.d.ts → emailManager-Dy6omJVp.d.ts} +2 -2
- package/dist/{emailStateMachine-Bc_6oIYw.esm.js → emailStateMachine-BXtlC0NV.esm.js} +3 -4
- package/dist/{events-ijlbX_Wx.esm.js → events-Du2A4-Qr.esm.js} +203 -8
- package/dist/events.d.ts +3 -2
- package/dist/events.esm.js +1 -1
- package/dist/extensibility.d.ts +38 -38
- package/dist/extensibility.esm.js +36 -36
- package/dist/{externalFetch-BKBThAUC.esm.js → externalFetch-DrR9xshk.esm.js} +3 -2
- package/dist/face-match.d.ts +1 -1
- package/dist/face-match.esm.js +2 -2
- package/dist/{faceCaptureManagerFactory-m-7ae67q.d.ts → faceCaptureManagerFactory-1hzeS_rB.d.ts} +11 -51
- package/dist/{faceCaptureManagerFactory-B6i9QcAk.esm.js → faceCaptureManagerFactory-CwZUeYfq.esm.js} +19 -54
- package/dist/{faceCaptureSetup-DU1mjRr6.esm.js → faceCaptureSetup-CYbdKNlI.esm.js} +104 -396
- package/dist/{faceMatchManager-BnvrZM2F.d.ts → faceMatchManager-DIgG-UFS.d.ts} +1 -2
- package/dist/{faceMatchManager-Bmv0HzuY.esm.js → faceMatchManager-DWFUQjMQ.esm.js} +3 -3
- package/dist/{faceMatchStateMachine-mRIHQ3dA.esm.js → faceMatchStateMachine-CUCvlydD.esm.js} +6 -5
- package/dist/{feature-management-C8CuN0os.esm.js → feature-management-rTfjzdDa.esm.js} +3 -3
- package/dist/feature-management.esm.js +1 -1
- package/dist/field-comparison.d.ts +2 -2
- package/dist/field-comparison.esm.js +1 -1
- package/dist/{fieldComparisonManager-CBvEGxFx.d.ts → fieldComparisonManager-CUX4gza2.d.ts} +6 -3
- package/dist/{fieldComparisonManager-CC-klG0h.esm.js → fieldComparisonManager-v3knTYV_.esm.js} +35 -18
- package/dist/fiscal-qr.d.ts +1 -1
- package/dist/fiscal-qr.esm.js +1 -1
- package/dist/{fiscalQrManager-B1STmT6z.d.ts → fiscalQrManager-D0Iy7EKR.d.ts} +2 -2
- package/dist/fiscalQrManager-Dt9fHG7h.esm.js +6798 -0
- package/dist/flow-events.d.ts +1 -1
- package/dist/flow.d.ts +14 -13
- package/dist/flow.esm.js +14 -14
- package/dist/{flowCompletionService-DccgtDnm.esm.js → flowCompletionService-oiK1PjPr.esm.js} +2 -3
- package/dist/{flowServices-CdsWsppG.esm.js → flowServices-CTc-zqfN.esm.js} +11 -8
- package/dist/geolocation.d.ts +1 -1
- package/dist/geolocation.esm.js +2 -2
- package/dist/{geolocationManager-CGHBxtMb.esm.js → geolocationManager-BOdtVuR8.esm.js} +6 -7
- package/dist/{geolocationManager-Cz744E5S.d.ts → geolocationManager-Dn24g1fl.d.ts} +2 -3
- package/dist/{geolocationStateMachine-CdEb1Gn0.esm.js → geolocationStateMachine-BnGuZ3hn.esm.js} +4 -5
- package/dist/{getDeviceClass-5NYZg9s6.esm.js → getDeviceClass-bsWdEDxP.esm.js} +1 -1
- package/dist/{getParsedUserAgent-B2iFDql1.esm.js → getParsedUserAgent-DhQPeKqw.esm.js} +1 -1
- package/dist/government-validation.d.ts +1 -1
- package/dist/government-validation.esm.js +2 -2
- package/dist/{governmentValidationManager-D02vT4yY.d.ts → governmentValidationManager-B82zOut8.d.ts} +3 -3
- package/dist/{governmentValidationManager-CacFOtKO.esm.js → governmentValidationManager-BtXWHICu.esm.js} +3 -3
- package/dist/{governmentValidationStateMachine-CoaZOSTP.esm.js → governmentValidationStateMachine-COL-Vs48.esm.js} +3 -4
- package/dist/home.d.ts +3 -26
- package/dist/home.esm.js +2 -2
- package/dist/http.esm.js +1 -1
- package/dist/id-ocr.d.ts +1 -1
- package/dist/id-ocr.esm.js +2 -2
- package/dist/id-selfie-flow.d.ts +6 -9
- package/dist/id-selfie-flow.esm.js +23 -28
- package/dist/id-verification.d.ts +1 -1
- package/dist/id-verification.esm.js +2 -2
- package/dist/id.d.ts +4 -4
- package/dist/id.esm.js +4 -205
- package/dist/{idCaptureDefaults-Dl64Trv5.esm.js → idCaptureDefaults-BGsG2OAs.esm.js} +7 -5
- package/dist/{idCaptureManager-BHwL2Z0V.d.ts → idCaptureManager-0M02hSuC.d.ts} +242 -98
- package/dist/{idCaptureManager-BNmVJQkd.esm.js → idCaptureManager-BKedt48Y.esm.js} +276 -210
- package/dist/{idCaptureServices-dtDG2HXS.esm.js → idCaptureServices-D0p_RFqk.esm.js} +21 -40
- package/dist/{idCaptureStateMachine-BbiZD3uf.esm.js → idCaptureStateMachine-CxwoN5ff.esm.js} +992 -872
- package/dist/{idOcrManager-ByWuQ4ej.esm.js → idOcrManager-D3-HNMXP.esm.js} +3 -3
- package/dist/{idOcrManager-CFlDwUvN.d.ts → idOcrManager-DT3kPIB3.d.ts} +3 -4
- package/dist/{idOcrStateMachine-Bt_abXQQ.esm.js → idOcrStateMachine-DyENX6Ki.esm.js} +3 -4
- package/dist/{idVerificationManager-BB4Pj_N6.d.ts → idVerificationManager-BJapZfpy.d.ts} +2 -3
- package/dist/{idVerificationManager-DT42c77H.esm.js → idVerificationManager-iWz7Avkr.esm.js} +3 -3
- package/dist/{idVerificationStateMachine-DbDVIh9t.esm.js → idVerificationStateMachine-CL1kUdBe.esm.js} +3 -4
- package/dist/identity-reuse.d.ts +2 -2
- package/dist/identity-reuse.esm.js +2 -2
- package/dist/{identityReuseManager-BXEBBI3N.d.ts → identityReuseManager-B1birg5X.d.ts} +162 -44
- package/dist/{identityReuseManager-yG3acUrQ.esm.js → identityReuseManager-CD1ucp1d.esm.js} +26 -13
- package/dist/{identityReuseStateMachine-BhAkuIra.esm.js → identityReuseStateMachine-DfV81wQC.esm.js} +89 -24
- package/dist/{index-CeaC32qI.d.ts → index-CKQ9QBZP.d.ts} +2 -2
- package/dist/index-DpTj5PFb.d.ts +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/{invokeOnCaptureCallback-BjzPjJ_p.esm.js → invokeOnCaptureCallback-DYrkOXO6.esm.js} +1 -1
- package/dist/lamejs-B6TzhU5q.esm.js +10 -0
- package/dist/mandatory-consent.d.ts +2 -2
- package/dist/mandatory-consent.esm.js +2 -2
- package/dist/{mandatoryConsentManager-7dI0D08q.esm.js → mandatoryConsentManager-Cwqx1nK7.esm.js} +3 -3
- package/dist/{mandatoryConsentManager-DFVm_i2B.d.ts → mandatoryConsentManager-okPILEru.d.ts} +8 -9
- package/dist/{mandatoryConsentStateMachine-DC5Mo6M1.esm.js → mandatoryConsentStateMachine-pXWqAHo_.esm.js} +3 -4
- package/dist/{multipartRecordingService-mwKFTlhR.esm.js → multipartRecordingService-CLwrF5wD.esm.js} +1 -2
- package/dist/{permissionGuards-D6TfVop2.esm.js → permissionGuards-gcy3U0SL.esm.js} +1 -1
- package/dist/{permissionServices-EY3_Vx6c.esm.js → permissionServices-Ca-tSNhT.esm.js} +34 -3
- package/dist/phone-number.d.ts +24 -0
- package/dist/phone-number.esm.js +1922 -0
- package/dist/phone.d.ts +1 -1
- package/dist/phone.esm.js +2 -2
- package/dist/{phoneManager-BBU8Lq0O.d.ts → phoneManager-BO-LTih5.d.ts} +16 -3
- package/dist/{phoneManager-IjhSv5XS.esm.js → phoneManager-KKUq-Vgo.esm.js} +31 -22
- package/dist/{phoneStateMachine-CXdXufKg.esm.js → phoneStateMachine-D2QWS2cu.esm.js} +38 -20
- package/dist/phoneValidation-DnBcNUNh.esm.js +48 -0
- package/dist/qe-signature.d.ts +2 -2
- package/dist/qe-signature.esm.js +1 -1
- package/dist/redirect-to-mobile.d.ts +1 -1
- package/dist/redirect-to-mobile.esm.js +2 -2
- package/dist/{redirectToMobileManager-BD2PvT5B.d.ts → redirectToMobileManager-CVsvpVbQ.d.ts} +2 -2
- package/dist/{redirectToMobileManager-FLEWJtv8.esm.js → redirectToMobileManager-uHW3dyuQ.esm.js} +4 -4
- package/dist/{redirectToMobileStateMachine-CSWWgUTO.esm.js → redirectToMobileStateMachine-b-H-ipGM.esm.js} +4 -5
- package/dist/{rolldown-runtime-FDOR9p9I.esm.js → rolldown-runtime-B-1-B7_t.esm.js} +10 -1
- package/dist/{runChildModule-B2Y_hlix.esm.js → runChildModule-CPa0i2_C.esm.js} +13 -12
- package/dist/safeStorage-UxDrnjwa.esm.js +35 -0
- package/dist/{sdkVersion-N1UiyFiY.esm.js → sdkVersion-BtROs6OA.esm.js} +1 -1
- package/dist/selfie.d.ts +4 -4
- package/dist/selfie.esm.js +12 -12
- package/dist/selfieErrorUtils-sMc0MaNh.esm.js +21 -0
- package/dist/{selfieManager-BSZG891S.d.ts → selfieManager-BJdNu_nd.d.ts} +2 -8
- package/dist/{selfieManager-AS6wfUvZ.esm.js → selfieManager-Ch9xJbWJ.esm.js} +6 -6
- package/dist/selfieStateMachine-DT8QCfKR.esm.js +41 -0
- package/dist/{session-BESZc05k.esm.js → session-CNNTckUS.esm.js} +5 -6
- package/dist/session.d.ts +15 -3
- package/dist/session.esm.js +30 -5
- package/dist/sessionInitializer-DVWMJh25.esm.js +973 -0
- package/dist/{setup-BuPbxpwF.esm.js → setup-B7ehQ-lf.esm.js} +155 -140
- package/dist/{setup-Cyko6cAn.d.ts → setup-YPKTUCY5.d.ts} +42 -15
- package/dist/signature.d.ts +1 -1
- package/dist/signature.esm.js +2 -2
- package/dist/{signatureManager-DGBSWz2_.d.ts → signatureManager-BpVt_Jv7.d.ts} +2 -2
- package/dist/{signatureManager-B72np4ZO.esm.js → signatureManager-f_dPAGXn.esm.js} +7 -11
- package/dist/{signatureStateMachine-ce_XMA3l.esm.js → signatureStateMachine-C-nUq_oq.esm.js} +3 -4
- package/dist/splitTrackedName-3zJRd2RD.esm.js +19 -0
- package/dist/{src-35ekGRzK.esm.js → src-DJAJjRYQ.esm.js} +1 -1
- package/dist/{stats-CZcy2J53.esm.js → stats-BEvexnKC.esm.js} +1 -2
- package/dist/stats.esm.js +1 -1
- package/dist/{sessionInitializer-CnhAkMUN.esm.js → thumbmark.esm-CRc0cYvz.esm.js} +33 -776
- package/dist/{trueSightService-M5VpCo96.esm.js → trueSightService-BzLdXpmJ.esm.js} +1391 -709
- package/dist/trust-graph.d.ts +1 -2
- package/dist/trust-graph.esm.js +2 -2
- package/dist/{types-C0oWGUzg.d.ts → types-0L-eFDmr.d.ts} +1 -1
- package/dist/{types-C1g9itHE.d.ts → types-B6HsSzpk.d.ts} +6 -7
- package/dist/{types-DEGVXwsk2.d.ts → types-BAxn7MpY.d.ts} +110 -62
- package/dist/{types-BfgmV7s7.d.ts → types-BQA7lRDV.d.ts} +1 -1
- package/dist/{types-Cx-1zo-i.d.ts → types-BvLo3U4u.d.ts} +1 -1
- package/dist/{types-Bx-BWveD.d.ts → types-CK8Jbjkp.d.ts} +1 -1
- package/dist/{types-CxGdmzxa.d.ts → types-Ckir_BEs.d.ts} +1 -1
- package/dist/{types-BjSly8cp.d.ts → types-DUnFZ08M.d.ts} +1 -1
- package/dist/{types-ESdtnHtg.d.ts → types-yPH8lAH-.d.ts} +3 -4
- package/dist/types-zOgZqMni.d.ts +6 -0
- package/dist/{urlUtils-D6phjq1-.esm.js → urlUtils-6jsE6rKp.esm.js} +9 -1
- package/dist/video-selfie.d.ts +6 -9
- package/dist/video-selfie.esm.js +1390 -1349
- package/dist/{videoSelfieCameraWarmer-q9ZjvXu9.esm.js → videoSelfieCameraWarmer-DWoFBJAn.esm.js} +10 -11
- package/dist/{videoSelfieFlowModuleMachine-BUe2uACW.esm.js → videoSelfieFlowModuleMachine-BCFVHBQ1.esm.js} +1 -1
- package/dist/{videoSelfieStepDetector-ChYgFM15.d.ts → videoSelfieStepDetector-CGsTltqB.d.ts} +4 -4
- package/dist/videoTrimByCopy-BFfAiNpv.esm.js +15901 -0
- package/dist/{warmup-ChDwHSel.esm.js → warmup-BElYWRh7.esm.js} +348 -11
- package/dist/{warmup-Cis2p6O0.d.ts → warmup-BO57syF6.d.ts} +8 -0
- package/dist/wasm.d.ts +2 -2
- package/dist/wasm.esm.js +3 -4
- package/dist/{wasmDsFlagSync-DYrLUEII.esm.js → wasmDsFlagSync-CYj5LL9z.esm.js} +1 -1
- package/dist/{wasmWebClient-B7baE-Wf.esm.js → wasmWebClient-BjZw_7OB.esm.js} +570 -33
- package/dist/watchlist-for-business.d.ts +1 -1
- package/dist/watchlist-for-business.esm.js +2 -2
- package/dist/watchlist.d.ts +1 -1
- package/dist/watchlist.esm.js +2 -2
- package/dist/{watchlistForBusinessManager-CsnJnG-C.d.ts → watchlistForBusinessManager-B3GDPZrr.d.ts} +2 -2
- package/dist/{watchlistForBusinessManager-CIMkpEhu.esm.js → watchlistForBusinessManager-CZZOFkGl.esm.js} +7 -5
- package/dist/{watchlistForBusinessStateMachine-CJ-MvUre.esm.js → watchlistForBusinessStateMachine-B66E7jud.esm.js} +3 -4
- package/dist/{watchlistManager-DLXef90v.d.ts → watchlistManager-DJQOd8Pw.d.ts} +2 -2
- package/dist/{watchlistManager-CixcLNDT.esm.js → watchlistManager-DXtX94SN.esm.js} +3 -3
- package/dist/{watchlistStateMachine-CBqk2w-h.esm.js → watchlistStateMachine-McALifag.esm.js} +3 -4
- package/dist/workflow.d.ts +34 -5
- package/dist/workflow.esm.js +64 -47
- package/dist/{xstate-actors.esm-BXeQ-Ucz.esm.js → xstate-actors.esm-8Gzepa_A.esm.js} +1 -1
- package/dist/{xstate.esm-BuFLFuzz.esm.js → xstate.esm-DSajW7CJ.esm.js} +24 -10
- package/package.json +13 -5
- package/dist/Actor-iTq7YY48.d.ts +0 -1
- package/dist/BrowserDiagnosticsCryptoProvider-BuzqvbhN.esm.js +0 -77
- package/dist/StateMachine-EDpYWy0i.d.ts +0 -6
- package/dist/api-Bx3gKW_y.esm.js +0 -129
- package/dist/fiscalQrManager-DbCVMIBx.esm.js +0 -34143
- package/dist/index-B8weJxmL.d.ts +0 -1
- package/dist/selfieErrorUtils-UiQ46EBa.esm.js +0 -116
- package/dist/selfieStateMachine-DY7vJVNY.esm.js +0 -71
- package/dist/types-BN5RPPIZ.esm.js +0 -34
- package/dist/types-Bt9RuRqt.d.ts +0 -6
- package/dist/virtualCameraCheck-Cjab7FTI.esm.js +0 -48
- /package/dist/{types-BSBzhHRH.d.ts → types-BSBzhHRH2.d.ts} +0 -0
package/dist/{idCaptureStateMachine-BbiZD3uf.esm.js → idCaptureStateMachine-CxwoN5ff.esm.js}
RENAMED
|
@@ -1,31 +1,32 @@
|
|
|
1
|
-
import { c as trueSightHintTransition, l as trueSightLog, m as isTrueSightTesting, r as noteTrueSightCaptureActivity } from "./trueSightService-M5VpCo96.esm.js";
|
|
2
|
-
import { r as WasmUtilProvider } from "./safeStorage-BdU9_m2E.esm.js";
|
|
3
|
-
import { l as BrowserStorageProvider } from "./setup-BuPbxpwF.esm.js";
|
|
4
|
-
import { t as BrowserTimerProvider } from "./BrowserTimerProvider-BXhgNxLt.esm.js";
|
|
5
|
-
import { s as exposeExperimentOnce } from "./feature-management-C8CuN0os.esm.js";
|
|
6
1
|
import { n as revokeObjectURL, t as getTimestamp } from "./IBrowserEnvironmentCapability-DEaRRk-R.esm.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { t as endpoints } from "./
|
|
11
|
-
import {
|
|
2
|
+
import { l as isGoogleWalletSignedRequestsEnabled, u as BrowserStorageProvider } from "./setup-B7ehQ-lf.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-BzLdXpmJ.esm.js";
|
|
7
|
+
import { t as getDisableIpify } from "./sessionInitializer-DVWMJh25.esm.js";
|
|
8
|
+
import { t as BrowserTimerProvider } from "./BrowserTimerProvider-BXhgNxLt.esm.js";
|
|
9
|
+
import { s as exposeExperimentOnce } from "./feature-management-rTfjzdDa.esm.js";
|
|
10
|
+
import { t as addDeviceStats } from "./stats-BEvexnKC.esm.js";
|
|
12
11
|
import { a as isIOS, s as isIPad, t as isAndroid, u as isMacOsSafari } from "./platform-DkcRc9JV.esm.js";
|
|
13
|
-
import "./session-
|
|
14
|
-
import { c as not, i as assign, l as raise, n as enqueueActions, o as and, r as sendTo, t as setup } from "./xstate.esm-
|
|
15
|
-
import { n as fromPromise, t as fromCallback } from "./xstate-actors.esm-
|
|
16
|
-
import { n as getUrlSearchParam, t as buildUrlWithSearchParams } from "./urlUtils-
|
|
12
|
+
import "./session-CNNTckUS.esm.js";
|
|
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
|
+
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";
|
|
17
16
|
import { r as getCameraReacquisitionConstraints } from "./camera-sIa9ceW2.esm.js";
|
|
18
|
-
import { n as invokeRequestPermissionActor, t as checkPermission } from "./permissionServices-
|
|
19
|
-
import {
|
|
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";
|
|
20
19
|
import { t as IncodeCanvas } from "./canvas-BxFzWTt-.esm.js";
|
|
21
|
-
import { n as needsMotionPrimeOnlyFromPermission, r as resolveStoredPermissionResult, t as isReadyForCaptureFromPermission } from "./permissionGuards-
|
|
22
|
-
import { o as StreamCanvasProcessingSession } from "./multipartRecordingService-
|
|
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";
|
|
23
22
|
import { t as sleep } from "./ITimerCapability-DgdDzp8G.esm.js";
|
|
24
23
|
import { t as getBrowser } from "./getBrowser-Cbe1C4Tn.esm.js";
|
|
24
|
+
import { a as isBackCameraLabel } from "./backCameraStream-CMvXj4X4.esm.js";
|
|
25
25
|
import { n as getWindowDimensions } from "./getDeviceClass-CeBiEayS.esm.js";
|
|
26
|
-
import { n as
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
26
|
+
import { n as frameSources, r as runVirtualCameraCheck } from "./deepsightService-tGP53cSS.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-D0p_RFqk.esm.js";
|
|
29
30
|
import { t as StreamCanvasCapture } from "./StreamCanvasCapture-C9jtgBdT.esm.js";
|
|
30
31
|
//#region src/modules/id/digitalUpload/digitalUploadErrors.ts
|
|
31
32
|
const TERMINAL_FAIL_REASONS = /* @__PURE__ */ new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
|
|
@@ -89,7 +90,7 @@ const uploadDigitalIdActor = fromPromise(async ({ input, signal }) => {
|
|
|
89
90
|
extractIdFace: input.extractIdFace
|
|
90
91
|
});
|
|
91
92
|
});
|
|
92
|
-
const getUploadResponseFromEvent
|
|
93
|
+
const getUploadResponseFromEvent = (event) => {
|
|
93
94
|
if (!("output" in event)) return;
|
|
94
95
|
return event.output;
|
|
95
96
|
};
|
|
@@ -153,10 +154,10 @@ const digitalUploadMachine = setup({
|
|
|
153
154
|
isSelectedFileTooLarge: ({ event }) => event.type === "FILE_PICKED" && event.file.size > 5242880,
|
|
154
155
|
isSelectedFileMimeInvalid: ({ event }) => event.type === "FILE_PICKED" && !DIGITAL_UPLOAD_ALLOWED_MIME_TYPES.includes(event.file.type),
|
|
155
156
|
hasSelectedFile: ({ context }) => context.file !== null,
|
|
156
|
-
responseHasFailReason: ({ event }) => mapDigitalIdFailReason(getUploadResponseFromEvent
|
|
157
|
+
responseHasFailReason: ({ event }) => mapDigitalIdFailReason(getUploadResponseFromEvent(event)) !== null,
|
|
157
158
|
hasAttemptsRemaining: ({ context }) => context.attemptsRemaining > 0,
|
|
158
159
|
isTerminalFailReason: ({ event }) => {
|
|
159
|
-
return isTerminalDigitalIdFailReason(getUploadResponseFromEvent
|
|
160
|
+
return isTerminalDigitalIdFailReason(getUploadResponseFromEvent(event));
|
|
160
161
|
},
|
|
161
162
|
isCurrentFailReasonTerminal: ({ context }) => {
|
|
162
163
|
const terminalReasons = /* @__PURE__ */ new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
|
|
@@ -316,14 +317,39 @@ const digitalUploadMachine = setup({
|
|
|
316
317
|
//#region src/modules/id/deviceWallet/deviceWalletServices.ts
|
|
317
318
|
/** Both wallet endpoint families are versioned via header, not path. */
|
|
318
319
|
const API_VERSION_HEADERS = { "api-version": "1.0" };
|
|
320
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
319
321
|
/**
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
+
* Turns the Google request payload into DC API request options without ever
|
|
323
|
+
* touching the payload itself — a signed request's JWS is covered by its
|
|
324
|
+
* signature, so any edit makes the wallet reject it. The backend decides the
|
|
325
|
+
* protocol; the SDK never derives it.
|
|
326
|
+
*
|
|
327
|
+
* - `{ requests: [...] }` — full DC API envelope (signed-capable backend):
|
|
328
|
+
* passed through as-is.
|
|
329
|
+
* - `{ protocol, data }` — an already-enveloped single request: not re-wrapped,
|
|
330
|
+
* only placed in the `requests` array (defensive, for rollout shape drift).
|
|
331
|
+
* - anything else — legacy bare unsigned OIDC4VP/DCQL object: wrapped with
|
|
332
|
+
* `openid4vp-v1-unsigned`.
|
|
333
|
+
*/
|
|
334
|
+
function toGoogleRequestOptions(payload) {
|
|
335
|
+
if (isRecord(payload) && Array.isArray(payload.requests)) return payload;
|
|
336
|
+
if (isRecord(payload) && typeof payload.protocol === "string") return { requests: [payload] };
|
|
337
|
+
return { requests: [{
|
|
338
|
+
protocol: "openid4vp-v1-unsigned",
|
|
339
|
+
data: payload
|
|
340
|
+
}] };
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Fetches the wallet request payload for the platform as Digital Credentials
|
|
344
|
+
* API request options.
|
|
322
345
|
*
|
|
323
346
|
* Apple: POST with an empty body → `{ deviceRequest, encryptionInfo }`,
|
|
324
347
|
* presented with protocol `org-iso-mdoc`.
|
|
325
|
-
* Google: GET → the
|
|
326
|
-
*
|
|
348
|
+
* Google: GET with `signedSupported=true` → the backend-built DC API envelope
|
|
349
|
+
* (signed or unsigned, backend's choice), passed through verbatim — see
|
|
350
|
+
* {@link toGoogleRequestOptions}. With `setup({ deviceWallet: {
|
|
351
|
+
* googleSignedRequests: false } })` the SDK sends `signedSupported=false` and
|
|
352
|
+
* the backend answers with the legacy bare unsigned payload.
|
|
327
353
|
*/
|
|
328
354
|
async function requestWalletData(platform, signal) {
|
|
329
355
|
if (platform === "ios") {
|
|
@@ -333,23 +359,21 @@ async function requestWalletData(platform, signal) {
|
|
|
333
359
|
});
|
|
334
360
|
if (!res.ok) throw new Error(`POST ${endpoints.deviceWalletAppleRequest} failed: ${res.status}`);
|
|
335
361
|
const data = res.data;
|
|
336
|
-
return {
|
|
362
|
+
return { requests: [{
|
|
337
363
|
protocol: "org-iso-mdoc",
|
|
338
364
|
data: {
|
|
339
365
|
deviceRequest: data.deviceRequest,
|
|
340
366
|
encryptionInfo: data.encryptionInfo
|
|
341
367
|
}
|
|
342
|
-
};
|
|
368
|
+
}] };
|
|
343
369
|
}
|
|
344
370
|
const res = await api.get(endpoints.deviceWalletGoogleRequest, {
|
|
345
371
|
headers: API_VERSION_HEADERS,
|
|
372
|
+
query: { signedSupported: isGoogleWalletSignedRequestsEnabled() },
|
|
346
373
|
signal
|
|
347
374
|
});
|
|
348
375
|
if (!res.ok) throw new Error(`GET ${endpoints.deviceWalletGoogleRequest} failed: ${res.status}`);
|
|
349
|
-
return
|
|
350
|
-
protocol: "openid4vp-v1-unsigned",
|
|
351
|
-
data: res.data
|
|
352
|
-
};
|
|
376
|
+
return toGoogleRequestOptions(res.data);
|
|
353
377
|
}
|
|
354
378
|
/**
|
|
355
379
|
* Forwards the opaque wallet response for backend decryption. The body key
|
|
@@ -529,408 +553,221 @@ function resolveWalletPlatform(provider) {
|
|
|
529
553
|
return isIOS() || isMacOsSafari() || isIPad() ? "ios" : "android";
|
|
530
554
|
}
|
|
531
555
|
//#endregion
|
|
532
|
-
//#region src/modules/id/
|
|
556
|
+
//#region src/modules/id/deviceWallet/instrumentation.ts
|
|
533
557
|
/**
|
|
534
|
-
*
|
|
535
|
-
*
|
|
558
|
+
* Maps a device-wallet child-machine snapshot to a tracked screen name.
|
|
559
|
+
* Family is `deviceWallet.*` — emitted cross-family under the parent
|
|
560
|
+
* `idCapture` module token, same as `mapDigitalIdScreenName`. See
|
|
561
|
+
* `docs/patterns/INSTRUMENTATION.md`.
|
|
536
562
|
*/
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
563
|
+
function mapDeviceWalletScreenName(value, failReason) {
|
|
564
|
+
if (value === "presenting") return "deviceWallet.wallet.default";
|
|
565
|
+
if (value === "failed") {
|
|
566
|
+
if (failReason === "NO_CREDENTIAL") return "deviceWallet.error.nocredential";
|
|
567
|
+
if (failReason === "UNSUPPORTED_PLATFORM") return "deviceWallet.error.unsupported";
|
|
568
|
+
return "deviceWallet.error.default";
|
|
569
|
+
}
|
|
570
|
+
return "deviceWallet.loading.default";
|
|
571
|
+
}
|
|
572
|
+
//#endregion
|
|
573
|
+
//#region ../infra/src/providers/browser/BrowserDigitalCredentialsProvider.ts
|
|
574
|
+
var BrowserDigitalCredentialsProvider = class {
|
|
575
|
+
isAvailable() {
|
|
576
|
+
return typeof navigator !== "undefined" && typeof navigator.credentials?.get === "function" && typeof globalThis.DigitalCredential !== "undefined";
|
|
577
|
+
}
|
|
578
|
+
async get(request, options) {
|
|
579
|
+
return { response: (await navigator.credentials.get({
|
|
580
|
+
mediation: "required",
|
|
581
|
+
signal: options?.signal,
|
|
582
|
+
digital: request
|
|
583
|
+
}))?.data?.response };
|
|
584
|
+
}
|
|
545
585
|
};
|
|
586
|
+
//#endregion
|
|
587
|
+
//#region src/modules/id/deviceWallet/deviceWalletActor.ts
|
|
546
588
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
* extended to also reject responses where the backend flagged a per-image
|
|
552
|
-
* quality issue (`correctSharpness`, `correctGlare`, or `readability`).
|
|
553
|
-
* `idQualityAttemptApproved` is intentionally ignored — v1 did not treat it
|
|
554
|
-
* as a manual-upload rejection signal.
|
|
555
|
-
*
|
|
556
|
-
* Quality flags are checked with `=== false` so missing/undefined values
|
|
557
|
-
* (older backends, partial payloads) keep the legacy "trust the server"
|
|
558
|
-
* behaviour and do not produce false positives.
|
|
559
|
-
*
|
|
560
|
-
* Returns `null` when the response represents a successful upload — the caller
|
|
561
|
-
* should treat `null` as "no error, advance to next slot".
|
|
589
|
+
* Starts a device-wallet actor for headless use. The ID-Capture parent invokes
|
|
590
|
+
* `deviceWalletMachine` itself (and resolves the platform through the
|
|
591
|
+
* digital-ID funnel); this factory is the standalone entry point for
|
|
592
|
+
* integrators driving the wallet handshake on their own.
|
|
562
593
|
*/
|
|
563
|
-
function
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
if (expectedTab === "id" && response.typeOfId?.toLowerCase() === "passport") return MANUAL_UPLOAD_ERROR_KEYS.wrongDocument;
|
|
570
|
-
if (response.correctSharpness === false) return MANUAL_UPLOAD_ERROR_KEYS.lowSharpness;
|
|
571
|
-
if (response.correctGlare === false) return MANUAL_UPLOAD_ERROR_KEYS.glareDetected;
|
|
572
|
-
if (response.readability === false) return MANUAL_UPLOAD_ERROR_KEYS.readabilityIssue;
|
|
573
|
-
return null;
|
|
594
|
+
function createDeviceWalletActor(options = {}) {
|
|
595
|
+
return createActor(deviceWalletMachine, { input: {
|
|
596
|
+
platform: resolveWalletPlatform(options.provider),
|
|
597
|
+
credentials: options.credentials ?? new BrowserDigitalCredentialsProvider(),
|
|
598
|
+
services: options.services
|
|
599
|
+
} }).start();
|
|
574
600
|
}
|
|
575
601
|
//#endregion
|
|
576
|
-
//#region src/modules/id/
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
return
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
};
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
602
|
+
//#region src/modules/id/deviceWallet/deviceWalletManager.ts
|
|
603
|
+
/**
|
|
604
|
+
* Absolute tracked-screen name for a device-wallet snapshot. Emitted verbatim
|
|
605
|
+
* on `event.screen` under the parent `idCapture` module token — the wallet is
|
|
606
|
+
* an ID-Capture sub-flow, so it does not own an analytics module of its own
|
|
607
|
+
* (see `docs/patterns/INSTRUMENTATION.md`).
|
|
608
|
+
*/
|
|
609
|
+
function getDeviceWalletScreenName(snapshot) {
|
|
610
|
+
return mapDeviceWalletScreenName(snapshot.value, snapshot.context?.failReason ?? null);
|
|
611
|
+
}
|
|
612
|
+
function mapState(snapshot) {
|
|
613
|
+
const typedSnapshot = snapshot;
|
|
614
|
+
const { context } = typedSnapshot;
|
|
615
|
+
const { platform } = context;
|
|
616
|
+
if (typedSnapshot.matches("presenting")) return {
|
|
617
|
+
status: "presenting",
|
|
618
|
+
platform
|
|
619
|
+
};
|
|
620
|
+
if (typedSnapshot.matches("decrypting")) return {
|
|
621
|
+
status: "decrypting",
|
|
622
|
+
platform
|
|
623
|
+
};
|
|
624
|
+
if (typedSnapshot.matches("finished") && context.response) return {
|
|
625
|
+
status: "finished",
|
|
626
|
+
platform,
|
|
627
|
+
decision: context.response.decision,
|
|
628
|
+
response: context.response
|
|
629
|
+
};
|
|
630
|
+
if (typedSnapshot.matches("failed")) return {
|
|
631
|
+
status: "failed",
|
|
632
|
+
platform,
|
|
633
|
+
reason: context.failReason ?? "WALLET_ERROR"
|
|
634
|
+
};
|
|
635
|
+
if (typedSnapshot.matches("closed")) return {
|
|
636
|
+
status: "closed",
|
|
637
|
+
platform
|
|
638
|
+
};
|
|
603
639
|
return {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
side: input.side,
|
|
607
|
-
base64Image,
|
|
608
|
-
retry: input.retry,
|
|
609
|
-
onlyFront: input.onlyFront,
|
|
610
|
-
isSecondId: input.isSecondId,
|
|
611
|
-
extractIdFace: input.extractIdFace,
|
|
612
|
-
signal
|
|
613
|
-
})
|
|
640
|
+
status: "requesting",
|
|
641
|
+
platform
|
|
614
642
|
};
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
};
|
|
623
|
-
const manualUploadMachine = setup({
|
|
624
|
-
types: {
|
|
625
|
-
context: {},
|
|
626
|
-
events: {},
|
|
627
|
-
input: {},
|
|
628
|
-
output: {}
|
|
629
|
-
},
|
|
630
|
-
actors: { uploadManualFile: uploadManualFileActor },
|
|
631
|
-
actions: {
|
|
632
|
-
setManualUploadActiveTab: assign(({ context, event }) => {
|
|
633
|
-
if (event.type !== "MANUAL_UPLOAD_TAB_CHANGED") return {};
|
|
634
|
-
return {
|
|
635
|
-
activeTab: event.tab,
|
|
636
|
-
errorMessage: null,
|
|
637
|
-
errorSide: null,
|
|
638
|
-
retriesLeft: context.captureAttempts
|
|
639
|
-
};
|
|
640
|
-
}),
|
|
641
|
-
resetManualUpload: assign(({ context }) => ({
|
|
642
|
-
frontFile: null,
|
|
643
|
-
backFile: null,
|
|
644
|
-
passportFile: null,
|
|
645
|
-
frontUploaded: false,
|
|
646
|
-
backUploaded: false,
|
|
647
|
-
passportUploaded: false,
|
|
648
|
-
skipBackFromServer: false,
|
|
649
|
-
errorMessage: null,
|
|
650
|
-
errorSide: null,
|
|
651
|
-
retriesLeft: context.captureAttempts
|
|
652
|
-
})),
|
|
653
|
-
storeSelectedFile: assign(({ event }) => {
|
|
654
|
-
if (event.type !== "MANUAL_UPLOAD_FILE_SELECTED") return {};
|
|
655
|
-
const updated = {
|
|
656
|
-
errorMessage: null,
|
|
657
|
-
errorSide: null
|
|
658
|
-
};
|
|
659
|
-
if (event.side === "front") updated.frontFile = event.file;
|
|
660
|
-
else if (event.side === "back") updated.backFile = event.file;
|
|
661
|
-
else updated.passportFile = event.file;
|
|
662
|
-
return updated;
|
|
663
|
-
}),
|
|
664
|
-
markFrontUploaded: assign(() => ({
|
|
665
|
-
frontUploaded: true,
|
|
666
|
-
errorMessage: null,
|
|
667
|
-
errorSide: null
|
|
668
|
-
})),
|
|
669
|
-
markBackUploaded: assign(() => ({
|
|
670
|
-
backUploaded: true,
|
|
671
|
-
errorMessage: null,
|
|
672
|
-
errorSide: null
|
|
673
|
-
})),
|
|
674
|
-
markPassportUploaded: assign(() => ({
|
|
675
|
-
passportUploaded: true,
|
|
676
|
-
errorMessage: null,
|
|
677
|
-
errorSide: null
|
|
678
|
-
})),
|
|
679
|
-
recordSkipBackFromResponse: assign(({ event }) => {
|
|
680
|
-
const response = getUploadResponseFromEvent(event);
|
|
681
|
-
if (!response) return {};
|
|
682
|
-
if (!response.skipBackIdCapture) return {};
|
|
683
|
-
return { skipBackFromServer: true };
|
|
684
|
-
}),
|
|
685
|
-
decrementManualUploadRetries: assign(({ context }) => ({ retriesLeft: Math.max(0, context.retriesLeft - 1) })),
|
|
686
|
-
setManualUploadErrorFromResponse: assign(({ context, event }) => {
|
|
687
|
-
const response = getUploadResponseFromEvent(event);
|
|
688
|
-
if (!response) return {};
|
|
689
|
-
return { errorMessage: mapFailReasonToErrorKey(response, context.activeTab) ?? "manualIdUpload.generic" };
|
|
690
|
-
}),
|
|
691
|
-
setManualUploadGenericError: assign(() => ({ errorMessage: "manualIdUpload.generic" })),
|
|
692
|
-
setManualUploadFileTooLargeError: assign(({ event }) => {
|
|
693
|
-
return {
|
|
694
|
-
errorMessage: "manualIdUpload.fileTooBig",
|
|
695
|
-
errorSide: event.type === "MANUAL_UPLOAD_FILE_SELECTED" ? event.side : null
|
|
696
|
-
};
|
|
697
|
-
}),
|
|
698
|
-
markErrorSideFront: assign(() => ({ errorSide: "front" })),
|
|
699
|
-
markErrorSideBack: assign(() => ({ errorSide: "back" })),
|
|
700
|
-
markErrorSidePassport: assign(() => ({ errorSide: "passport" })),
|
|
701
|
-
clearManualUploadError: assign(() => ({
|
|
702
|
-
errorMessage: null,
|
|
703
|
-
errorSide: null
|
|
704
|
-
}))
|
|
705
|
-
},
|
|
706
|
-
guards: {
|
|
707
|
-
isAllowedTabChange: ({ context, event }) => event.type === "MANUAL_UPLOAD_TAB_CHANGED" && (!context.onlyBack || event.tab === "id"),
|
|
708
|
-
isSelectedFileTooLarge: ({ context, event }) => {
|
|
709
|
-
if (event.type !== "MANUAL_UPLOAD_FILE_SELECTED") return false;
|
|
710
|
-
if (context.onlyBack && event.side !== "back") return false;
|
|
711
|
-
return event.file.size > MANUAL_UPLOAD_MAX_FILE_SIZE_BYTES;
|
|
712
|
-
},
|
|
713
|
-
isFrontFileSelection: ({ context, event }) => !context.onlyBack && event.type === "MANUAL_UPLOAD_FILE_SELECTED" && event.side === "front",
|
|
714
|
-
isBackFileSelection: ({ event }) => event.type === "MANUAL_UPLOAD_FILE_SELECTED" && event.side === "back",
|
|
715
|
-
isPassportFileSelection: ({ context, event }) => !context.onlyBack && event.type === "MANUAL_UPLOAD_FILE_SELECTED" && event.side === "passport",
|
|
716
|
-
manualUploadRetriesExhausted: ({ context }) => context.retriesLeft <= 0,
|
|
717
|
-
canContinueFromIdTab: ({ context }) => {
|
|
718
|
-
if (context.activeTab !== "id") return false;
|
|
719
|
-
if (context.onlyBack) return context.backUploaded;
|
|
720
|
-
if (!context.frontUploaded) return false;
|
|
721
|
-
if (context.onlyFront) return true;
|
|
722
|
-
if (context.skipBackFromServer) return true;
|
|
723
|
-
return context.backUploaded;
|
|
724
|
-
},
|
|
725
|
-
canContinueFromPassportTab: ({ context }) => !context.onlyBack && context.activeTab === "passport" && context.passportUploaded,
|
|
726
|
-
manualUploadResponseHasError: ({ context, event }) => {
|
|
727
|
-
const response = getUploadResponseFromEvent(event);
|
|
728
|
-
if (!response) return false;
|
|
729
|
-
return mapFailReasonToErrorKey(response, context.activeTab) !== null;
|
|
730
|
-
},
|
|
731
|
-
manualUploadPayloadTooLarge: ({ event }) => getUploadOutputFromEvent(event)?.type === "fileTooLarge"
|
|
732
|
-
}
|
|
733
|
-
}).createMachine({
|
|
734
|
-
id: "manualUpload",
|
|
735
|
-
initial: "selecting",
|
|
736
|
-
context: ({ input }) => ({
|
|
737
|
-
onlyFront: input.onlyFront,
|
|
738
|
-
onlyBack: input.onlyBack ?? false,
|
|
739
|
-
isSecondId: input.isSecondId,
|
|
740
|
-
captureAttempts: input.captureAttempts,
|
|
741
|
-
extractIdFace: input.extractIdFace,
|
|
742
|
-
frontFile: null,
|
|
743
|
-
backFile: null,
|
|
744
|
-
passportFile: null,
|
|
745
|
-
activeTab: "id",
|
|
746
|
-
retriesLeft: input.captureAttempts,
|
|
747
|
-
errorMessage: null,
|
|
748
|
-
errorSide: null,
|
|
749
|
-
skipBackFromServer: false,
|
|
750
|
-
frontUploaded: false,
|
|
751
|
-
backUploaded: false,
|
|
752
|
-
passportUploaded: false
|
|
753
|
-
}),
|
|
754
|
-
on: {
|
|
755
|
-
MANUAL_UPLOAD_TAB_CHANGED: {
|
|
756
|
-
guard: "isAllowedTabChange",
|
|
757
|
-
target: ".selecting",
|
|
758
|
-
actions: ["setManualUploadActiveTab"]
|
|
759
|
-
},
|
|
760
|
-
MANUAL_UPLOAD_RESET: {
|
|
761
|
-
target: ".selecting",
|
|
762
|
-
actions: ["resetManualUpload"]
|
|
763
|
-
}
|
|
764
|
-
},
|
|
765
|
-
states: {
|
|
766
|
-
selecting: { on: {
|
|
767
|
-
MANUAL_UPLOAD_FILE_SELECTED: [
|
|
768
|
-
{
|
|
769
|
-
guard: "isSelectedFileTooLarge",
|
|
770
|
-
actions: ["setManualUploadFileTooLargeError"]
|
|
771
|
-
},
|
|
772
|
-
{
|
|
773
|
-
guard: "isFrontFileSelection",
|
|
774
|
-
target: "uploadingFront",
|
|
775
|
-
actions: ["storeSelectedFile"]
|
|
776
|
-
},
|
|
777
|
-
{
|
|
778
|
-
guard: "isBackFileSelection",
|
|
779
|
-
target: "uploadingBack",
|
|
780
|
-
actions: ["storeSelectedFile"]
|
|
781
|
-
},
|
|
782
|
-
{
|
|
783
|
-
guard: "isPassportFileSelection",
|
|
784
|
-
target: "uploadingPassport",
|
|
785
|
-
actions: ["storeSelectedFile"]
|
|
786
|
-
}
|
|
787
|
-
],
|
|
788
|
-
MANUAL_UPLOAD_CONTINUE: [{
|
|
789
|
-
guard: "canContinueFromIdTab",
|
|
790
|
-
target: "finished"
|
|
791
|
-
}, {
|
|
792
|
-
guard: "canContinueFromPassportTab",
|
|
793
|
-
target: "finished"
|
|
794
|
-
}]
|
|
795
|
-
} },
|
|
796
|
-
uploadingFront: { invoke: {
|
|
797
|
-
id: "uploadManualFile",
|
|
798
|
-
src: "uploadManualFile",
|
|
799
|
-
input: ({ context }) => ({
|
|
800
|
-
side: "front",
|
|
801
|
-
file: context.frontFile,
|
|
802
|
-
retry: context.retriesLeft < context.captureAttempts,
|
|
803
|
-
onlyFront: context.onlyFront,
|
|
804
|
-
isSecondId: context.isSecondId,
|
|
805
|
-
extractIdFace: context.extractIdFace
|
|
806
|
-
}),
|
|
807
|
-
onDone: [
|
|
808
|
-
{
|
|
809
|
-
guard: "manualUploadPayloadTooLarge",
|
|
810
|
-
target: "selecting",
|
|
811
|
-
actions: ["setManualUploadFileTooLargeError", "markErrorSideFront"]
|
|
812
|
-
},
|
|
813
|
-
{
|
|
814
|
-
guard: "manualUploadResponseHasError",
|
|
815
|
-
target: "checkRetries",
|
|
816
|
-
actions: [
|
|
817
|
-
"decrementManualUploadRetries",
|
|
818
|
-
"setManualUploadErrorFromResponse",
|
|
819
|
-
"markErrorSideFront"
|
|
820
|
-
]
|
|
821
|
-
},
|
|
822
|
-
{
|
|
823
|
-
target: "selecting",
|
|
824
|
-
actions: [
|
|
825
|
-
"markFrontUploaded",
|
|
826
|
-
"recordSkipBackFromResponse",
|
|
827
|
-
"clearManualUploadError"
|
|
828
|
-
]
|
|
829
|
-
}
|
|
830
|
-
],
|
|
831
|
-
onError: {
|
|
832
|
-
target: "checkRetries",
|
|
833
|
-
actions: [
|
|
834
|
-
"decrementManualUploadRetries",
|
|
835
|
-
"setManualUploadGenericError",
|
|
836
|
-
"markErrorSideFront"
|
|
837
|
-
]
|
|
838
|
-
}
|
|
839
|
-
} },
|
|
840
|
-
uploadingBack: { invoke: {
|
|
841
|
-
id: "uploadManualFile",
|
|
842
|
-
src: "uploadManualFile",
|
|
843
|
-
input: ({ context }) => ({
|
|
844
|
-
side: "back",
|
|
845
|
-
file: context.backFile,
|
|
846
|
-
retry: context.retriesLeft < context.captureAttempts,
|
|
847
|
-
onlyFront: false,
|
|
848
|
-
isSecondId: context.isSecondId
|
|
849
|
-
}),
|
|
850
|
-
onDone: [
|
|
851
|
-
{
|
|
852
|
-
guard: "manualUploadPayloadTooLarge",
|
|
853
|
-
target: "selecting",
|
|
854
|
-
actions: ["setManualUploadFileTooLargeError", "markErrorSideBack"]
|
|
855
|
-
},
|
|
856
|
-
{
|
|
857
|
-
guard: "manualUploadResponseHasError",
|
|
858
|
-
target: "checkRetries",
|
|
859
|
-
actions: [
|
|
860
|
-
"decrementManualUploadRetries",
|
|
861
|
-
"setManualUploadErrorFromResponse",
|
|
862
|
-
"markErrorSideBack"
|
|
863
|
-
]
|
|
864
|
-
},
|
|
865
|
-
{
|
|
866
|
-
target: "selecting",
|
|
867
|
-
actions: ["markBackUploaded", "clearManualUploadError"]
|
|
868
|
-
}
|
|
869
|
-
],
|
|
870
|
-
onError: {
|
|
871
|
-
target: "checkRetries",
|
|
872
|
-
actions: [
|
|
873
|
-
"decrementManualUploadRetries",
|
|
874
|
-
"setManualUploadGenericError",
|
|
875
|
-
"markErrorSideBack"
|
|
876
|
-
]
|
|
877
|
-
}
|
|
878
|
-
} },
|
|
879
|
-
uploadingPassport: { invoke: {
|
|
880
|
-
id: "uploadManualFile",
|
|
881
|
-
src: "uploadManualFile",
|
|
882
|
-
input: ({ context }) => ({
|
|
883
|
-
side: "passport",
|
|
884
|
-
file: context.passportFile,
|
|
885
|
-
retry: context.retriesLeft < context.captureAttempts,
|
|
886
|
-
onlyFront: false,
|
|
887
|
-
isSecondId: context.isSecondId,
|
|
888
|
-
extractIdFace: context.extractIdFace
|
|
889
|
-
}),
|
|
890
|
-
onDone: [
|
|
891
|
-
{
|
|
892
|
-
guard: "manualUploadPayloadTooLarge",
|
|
893
|
-
target: "selecting",
|
|
894
|
-
actions: ["setManualUploadFileTooLargeError", "markErrorSidePassport"]
|
|
895
|
-
},
|
|
896
|
-
{
|
|
897
|
-
guard: "manualUploadResponseHasError",
|
|
898
|
-
target: "checkRetries",
|
|
899
|
-
actions: [
|
|
900
|
-
"decrementManualUploadRetries",
|
|
901
|
-
"setManualUploadErrorFromResponse",
|
|
902
|
-
"markErrorSidePassport"
|
|
903
|
-
]
|
|
904
|
-
},
|
|
905
|
-
{
|
|
906
|
-
target: "selecting",
|
|
907
|
-
actions: ["markPassportUploaded", "clearManualUploadError"]
|
|
908
|
-
}
|
|
909
|
-
],
|
|
910
|
-
onError: {
|
|
911
|
-
target: "checkRetries",
|
|
912
|
-
actions: [
|
|
913
|
-
"decrementManualUploadRetries",
|
|
914
|
-
"setManualUploadGenericError",
|
|
915
|
-
"markErrorSidePassport"
|
|
916
|
-
]
|
|
917
|
-
}
|
|
918
|
-
} },
|
|
919
|
-
checkRetries: { always: [{
|
|
920
|
-
guard: "manualUploadRetriesExhausted",
|
|
921
|
-
target: "retriesExhausted"
|
|
922
|
-
}, { target: "selecting" }] },
|
|
923
|
-
retriesExhausted: { after: { [MANUAL_UPLOAD_EXHAUSTION_FORWARD_MS]: { target: "exhausted" } } },
|
|
924
|
-
exhausted: {
|
|
925
|
-
type: "final",
|
|
926
|
-
output: { result: "exhausted" }
|
|
643
|
+
}
|
|
644
|
+
function createApi({ actor, trackElementClicked }) {
|
|
645
|
+
return {
|
|
646
|
+
/** Restarts the handshake after a failure. Needs a fresh user gesture. */
|
|
647
|
+
retry() {
|
|
648
|
+
trackElementClicked?.("retry");
|
|
649
|
+
actor.send({ type: "RETRY" });
|
|
927
650
|
},
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
651
|
+
/**
|
|
652
|
+
* Abandons the wallet path from a failure and moves the manager to
|
|
653
|
+
* `closed`, so the consumer can fall back to a camera ID capture.
|
|
654
|
+
*/
|
|
655
|
+
useAnotherMethod() {
|
|
656
|
+
trackElementClicked?.("useAnotherMethod");
|
|
657
|
+
actor.send({ type: "USE_ANOTHER_METHOD" });
|
|
931
658
|
}
|
|
932
|
-
}
|
|
933
|
-
}
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Creates a headless device-wallet (mDL) manager — the V2 equivalent of V1's
|
|
663
|
+
* `renderWallet`, with the intermediate states observable.
|
|
664
|
+
*
|
|
665
|
+
* Runs the Apple Wallet (web) / Google Wallet handshake with zero Incode UI,
|
|
666
|
+
* so integrators trigger it from their own button and render their own UX.
|
|
667
|
+
* Call it from a user gesture: iOS Safari requires transient user activation
|
|
668
|
+
* for `navigator.credentials.get()`.
|
|
669
|
+
*
|
|
670
|
+
* Requires an initialized session (`setup({ apiURL, token })`) — the request
|
|
671
|
+
* and decrypt calls are session-scoped.
|
|
672
|
+
*
|
|
673
|
+
* @example
|
|
674
|
+
* ```typescript
|
|
675
|
+
* import { setup } from '@incodetech/core';
|
|
676
|
+
* import { createDeviceWalletManager } from '@incodetech/core/id';
|
|
677
|
+
*
|
|
678
|
+
* setup({ apiURL, token });
|
|
679
|
+
*
|
|
680
|
+
* button.addEventListener('click', () => {
|
|
681
|
+
* const manager = createDeviceWalletManager();
|
|
682
|
+
* manager.subscribe((state) => {
|
|
683
|
+
* if (state.status === 'finished') manager.stop();
|
|
684
|
+
* if (state.status === 'failed') console.error(state.reason);
|
|
685
|
+
* });
|
|
686
|
+
* });
|
|
687
|
+
* ```
|
|
688
|
+
*/
|
|
689
|
+
function createDeviceWalletManager(options = {}) {
|
|
690
|
+
return createDeviceWalletManagerFromActor(createDeviceWalletActor(options));
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Creates a device-wallet manager from a pre-built actor. Use this when
|
|
694
|
+
* overriding the machine via `.provide()` for custom backends or tests.
|
|
695
|
+
*/
|
|
696
|
+
function createDeviceWalletManagerFromActor(actor) {
|
|
697
|
+
return createManager({
|
|
698
|
+
actor,
|
|
699
|
+
mapState,
|
|
700
|
+
createApi,
|
|
701
|
+
instrumentation: createManagerInstrumentation(eventModuleNames.idCapture, { getEventScreenName: getDeviceWalletScreenName })
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
//#endregion
|
|
705
|
+
//#region src/modules/id/deviceWallet/renderWallet.ts
|
|
706
|
+
const FAIL_MESSAGES = {
|
|
707
|
+
UNSUPPORTED_PLATFORM: "Device wallet is not supported on this platform/browser",
|
|
708
|
+
NO_CREDENTIAL: "The wallet returned no digital ID credential",
|
|
709
|
+
WALLET_ERROR: "Device wallet request failed"
|
|
710
|
+
};
|
|
711
|
+
/**
|
|
712
|
+
* Headless device-wallet (mDL) API — the V1 `renderWallet` shape, ported.
|
|
713
|
+
*
|
|
714
|
+
* Runs the Apple Wallet (web) / Google Wallet handshake with zero Incode UI,
|
|
715
|
+
* so integrators trigger it from their own button and render their own UX.
|
|
716
|
+
* Resolves once the handshake settles; the outcome arrives through
|
|
717
|
+
* `onSuccess` / `onError` exactly as in V1.
|
|
718
|
+
*
|
|
719
|
+
* MUST be called from a user gesture (e.g. a click handler) — iOS/Safari
|
|
720
|
+
* requires transient user activation for `navigator.credentials.get()` to
|
|
721
|
+
* present the wallet sheet.
|
|
722
|
+
*
|
|
723
|
+
* Requires an initialized session (`setup({ apiURL, token })`). The verified
|
|
724
|
+
* attributes are NOT returned here: they land in the session and are read back
|
|
725
|
+
* through the standard OCR / score APIs. `onSuccess` receives the submission
|
|
726
|
+
* decision/status.
|
|
727
|
+
*
|
|
728
|
+
* Prefer {@link createDeviceWalletManager} for new integrations — it exposes
|
|
729
|
+
* the intermediate `requesting` / `presenting` / `decrypting` states (and a
|
|
730
|
+
* `retry()`), which this one-shot wrapper collapses.
|
|
731
|
+
*
|
|
732
|
+
* @example
|
|
733
|
+
* ```typescript
|
|
734
|
+
* button.addEventListener('click', () => {
|
|
735
|
+
* void renderWallet({
|
|
736
|
+
* onSuccess: (result) => console.log(result.decision),
|
|
737
|
+
* onError: (error) => console.error(error.code, error.message),
|
|
738
|
+
* });
|
|
739
|
+
* });
|
|
740
|
+
* ```
|
|
741
|
+
*/
|
|
742
|
+
function renderWallet({ onSuccess, onError, ...actorOptions }) {
|
|
743
|
+
return new Promise((resolve) => {
|
|
744
|
+
const manager = createDeviceWalletManager(actorOptions);
|
|
745
|
+
const subscription = {};
|
|
746
|
+
let settled = false;
|
|
747
|
+
const settle = (state) => {
|
|
748
|
+
if (state.status === "requesting" || state.status === "presenting" || state.status === "decrypting") return false;
|
|
749
|
+
settled = true;
|
|
750
|
+
subscription.unsubscribe?.();
|
|
751
|
+
manager.stop();
|
|
752
|
+
if (state.status === "finished") onSuccess(state.response);
|
|
753
|
+
else if (state.status === "failed") onError({
|
|
754
|
+
code: state.reason,
|
|
755
|
+
message: FAIL_MESSAGES[state.reason]
|
|
756
|
+
});
|
|
757
|
+
else onError({
|
|
758
|
+
code: "WALLET_ERROR",
|
|
759
|
+
message: FAIL_MESSAGES.WALLET_ERROR
|
|
760
|
+
});
|
|
761
|
+
resolve();
|
|
762
|
+
return true;
|
|
763
|
+
};
|
|
764
|
+
if (settle(manager.getState())) return;
|
|
765
|
+
subscription.unsubscribe = manager.subscribe((state) => {
|
|
766
|
+
if (settled) return;
|
|
767
|
+
settle(state);
|
|
768
|
+
});
|
|
769
|
+
});
|
|
770
|
+
}
|
|
934
771
|
//#endregion
|
|
935
772
|
//#region src/modules/id/idCaptureGuards.ts
|
|
936
773
|
function getPermissionOutput(event) {
|
|
@@ -941,7 +778,7 @@ function getPermissionOutput(event) {
|
|
|
941
778
|
}
|
|
942
779
|
const hasShowTutorialGuard = ({ context }) => context.config.showTutorial;
|
|
943
780
|
const hasAgeAssuranceGuard = ({ context }) => context.config.ageAssurance === true;
|
|
944
|
-
const hasShowDocumentChooserGuard = ({ context }) =>
|
|
781
|
+
const hasShowDocumentChooserGuard = ({ context }) => !context.config.onlyBack && (context.config.showDocumentChooserScreen ?? false);
|
|
945
782
|
const isPermissionGrantedGuard = ({ event }) => {
|
|
946
783
|
return getPermissionOutput(event) === "granted";
|
|
947
784
|
};
|
|
@@ -959,6 +796,7 @@ const isPermissionDeniedErrorGuard = ({ event }) => {
|
|
|
959
796
|
return false;
|
|
960
797
|
};
|
|
961
798
|
const isPermissionBlockedGuard = ({ context }) => context.permissionResult === "denied" || context.permissionResult === "refresh";
|
|
799
|
+
const requiresMotionPermissionUserGestureGuard = ({ context }) => requiresMotionPermissionUserGesture(context.config.ds);
|
|
962
800
|
const hasAttemptsRemainingGuard = ({ context }) => context.attemptsRemaining > 0;
|
|
963
801
|
const hasCapturedImageGuard = ({ context }) => {
|
|
964
802
|
return context.provider?.getCapturedCanvas() !== null;
|
|
@@ -994,11 +832,9 @@ const isFrontModeGuard = ({ context }) => context.currentMode === "front" || con
|
|
|
994
832
|
* server answer exists, and
|
|
995
833
|
* 2. where you do, still self-correct once the answer arrives.
|
|
996
834
|
*
|
|
997
|
-
*
|
|
998
|
-
*
|
|
999
|
-
*
|
|
1000
|
-
* `skipBackFromServer` afterwards to satisfy (2)). This guard is on neither
|
|
1001
|
-
* path — the answer is already in hand by the time it runs.
|
|
835
|
+
* The captureOnly machine qualifies under (1) because it has no upload and no
|
|
836
|
+
* server answer. This guard is not on that path, so the answer is already in
|
|
837
|
+
* hand by the time it runs.
|
|
1002
838
|
*/
|
|
1003
839
|
const shouldContinueToBackGuard = ({ context }) => {
|
|
1004
840
|
if (context.currentMode !== "front" && context.currentMode !== "passport") return false;
|
|
@@ -1038,10 +874,8 @@ const supportsOptimizingStatusGuard = ({ context }) => context.config.supportsOp
|
|
|
1038
874
|
const isDeepsightEnabledGuard = ({ context }) => context.dependencies !== void 0;
|
|
1039
875
|
const isDeepsightReadyGuard = ({ context }) => context.deepsightService !== void 0;
|
|
1040
876
|
const needsDeepsightInitGuard = ({ context }) => context.dependencies !== void 0 && context.deepsightService === void 0 && !context.deepsightInitAttempted;
|
|
1041
|
-
const hasOnlyManualUploadAvailableGuard = ({ context }) => context.availableDocumentTypes.length === 1 && context.availableDocumentTypes[0] === "manualIdUpload";
|
|
1042
877
|
/** No capture option is enabled — the ID module is misconfigured. */
|
|
1043
878
|
const hasNoDocumentTypesAvailableGuard = ({ context }) => context.availableDocumentTypes.length === 0;
|
|
1044
|
-
const isManualIdUploadSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "manualIdUpload";
|
|
1045
879
|
const isDigitalIdUploadSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "digitalIdUpload";
|
|
1046
880
|
const isDigitalIdRedirectSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "digitalIdRedirect";
|
|
1047
881
|
/** The Digital ID (device wallet) chooser tile was picked. */
|
|
@@ -1112,237 +946,25 @@ const forceFinishAfterProcessingGuard = ({ context }) => context.forceFinishAfte
|
|
|
1112
946
|
* `MAX_EXPIRED_FIRST_SIDE_ATTEMPTS` (decoupled for V1 parity — see ENG-46592).
|
|
1113
947
|
* The two expired caps are therefore different by design.
|
|
1114
948
|
*/
|
|
1115
|
-
const isProcessingExpiredExhaustedGuard = ({ context }) => context.processingExpiredAttempts + 1 >= context.config.captureAttempts;
|
|
1116
|
-
/**
|
|
1117
|
-
* True when capturing the back side of a two-sided (front+back) ID flow.
|
|
1118
|
-
* Used to redirect an expired-back capture to front rather than retrying
|
|
1119
|
-
* the same back side (Figma Story #2.1).
|
|
1120
|
-
* Excludes onlyBack and usSmartCapture — those are single-side back flows
|
|
1121
|
-
* with no front to redirect to.
|
|
1122
|
-
*/
|
|
1123
|
-
const isBackModeInMultiSideFlowGuard = ({ context }) => context.currentMode === "back" && !context.config.onlyBack && !context.config.usSmartCapture;
|
|
1124
|
-
/**
|
|
1125
|
-
* True once the user has already been redirected from an expired second-side
|
|
1126
|
-
* (back) capture to the first side (front) for their one extra attempt
|
|
1127
|
-
* (V1's `expiredRedirected`). Used to make the expired-back→front redirect a
|
|
1128
|
-
* one-shot: any subsequent expired upload routes to `expiredExhausted` instead
|
|
1129
|
-
* of redirecting again, so total captures stay within the backend's
|
|
1130
|
-
* max-attempts/OCR cap (ENG-46592 / re-respects ENG-45666).
|
|
1131
|
-
*/
|
|
1132
|
-
const wasExpiredRedirectedGuard = ({ context }) => context.expiredRedirected === true;
|
|
1133
|
-
const hasManualCaptureTriggeredGuard = ({ context }) => context.manualCaptureTriggered;
|
|
1134
|
-
//#endregion
|
|
1135
|
-
//#region src/modules/id/digitalIdRegistry.ts
|
|
1136
|
-
/**
|
|
1137
|
-
* True when a digital-ID method uses a full-page web-redirect flow (Trinsic
|
|
1138
|
-
* iDIN/FTN). Accepts both the module `FlowType` value (`REDIRECT`) and the
|
|
1139
|
-
* backend value (`WEB_REDIRECT`). (Lives here rather than in
|
|
1140
|
-
* `idCaptureHelpers` to keep the registry free of circular imports; the
|
|
1141
|
-
* helpers re-export it.)
|
|
1142
|
-
*/
|
|
1143
|
-
function isRedirectFlowType(flowType) {
|
|
1144
|
-
return flowType === "REDIRECT" || flowType === "WEB_REDIRECT";
|
|
1145
|
-
}
|
|
1146
|
-
const DIGITAL_ID_REGISTRY = {
|
|
1147
|
-
mDL: [{
|
|
1148
|
-
kind: "incodeWallet",
|
|
1149
|
-
documentType: "digitalId",
|
|
1150
|
-
configFlag: "deviceWallet"
|
|
1151
|
-
}, {
|
|
1152
|
-
kind: "trinsicRedirect",
|
|
1153
|
-
documentType: "digitalIdRedirect",
|
|
1154
|
-
providerId: "trinsic_mdl_placeholder",
|
|
1155
|
-
method: "MDL"
|
|
1156
|
-
}],
|
|
1157
|
-
iDIN: [{
|
|
1158
|
-
kind: "trinsicRedirect",
|
|
1159
|
-
documentType: "digitalIdRedirect",
|
|
1160
|
-
providerId: "trinsic_netherlands_idin",
|
|
1161
|
-
method: "IDIN"
|
|
1162
|
-
}],
|
|
1163
|
-
FTN: [{
|
|
1164
|
-
kind: "trinsicRedirect",
|
|
1165
|
-
documentType: "digitalIdRedirect",
|
|
1166
|
-
providerId: "trinsic_finnish_trust_network",
|
|
1167
|
-
method: "FTN"
|
|
1168
|
-
}]
|
|
1169
|
-
};
|
|
1170
|
-
const DIGITAL_ID_DOCUMENT_TYPES = Object.keys(DIGITAL_ID_REGISTRY);
|
|
1171
|
-
/**
|
|
1172
|
-
* Tolerant view over `config.digitalIds`: accepts both the mapped array
|
|
1173
|
-
* (`IdCaptureDigitalIdMethod[]`) and the raw backend object
|
|
1174
|
-
* (`{ enabled, methods: [...] }`). Extracted from the old
|
|
1175
|
-
* `getDigitalIdRedirectMethod` cast so every consumer parses it the same way.
|
|
1176
|
-
*/
|
|
1177
|
-
function normalizeDigitalIdMethods(config) {
|
|
1178
|
-
const raw = config.digitalIds;
|
|
1179
|
-
return Array.isArray(raw) ? raw : raw?.methods ?? [];
|
|
1180
|
-
}
|
|
1181
|
-
/** Whether a funnel entry is activated by config + platform capabilities. */
|
|
1182
|
-
function isEntryActive(entry, config, platform) {
|
|
1183
|
-
if (entry.kind === "incodeWallet") return config[entry.configFlag] === true && platform.credentialsAvailable;
|
|
1184
|
-
return findConfiguredMethod(entry, config) !== void 0;
|
|
1185
|
-
}
|
|
1186
|
-
/**
|
|
1187
|
-
* The configured `digitalIds` method matching a Trinsic funnel entry — by
|
|
1188
|
-
* persisted method name, or (mapped shape) by provider id on a redirect
|
|
1189
|
-
* flowType. Mirrors the old first-match semantics; `methods[].enabled` is
|
|
1190
|
-
* deliberately still not consulted (pre-existing behavior).
|
|
1191
|
-
*/
|
|
1192
|
-
function findConfiguredMethod(entry, config) {
|
|
1193
|
-
return normalizeDigitalIdMethods(config).find((method) => method.method?.toUpperCase() === entry.method || method.provider === entry.providerId && !!method.flowType && isRedirectFlowType(method.flowType));
|
|
1194
|
-
}
|
|
1195
|
-
/** Normalizes a raw configured method into the mapped shape for the child input. */
|
|
1196
|
-
function toMappedMethod(entry, method) {
|
|
1197
|
-
if (method.flowType && isRedirectFlowType(method.flowType)) return method;
|
|
1198
|
-
return {
|
|
1199
|
-
method: method.method,
|
|
1200
|
-
provider: entry.providerId,
|
|
1201
|
-
flowType: "WEB_REDIRECT",
|
|
1202
|
-
country: method.country ?? method.countries?.[0],
|
|
1203
|
-
displayName: method.displayName
|
|
1204
|
-
};
|
|
1205
|
-
}
|
|
1206
|
-
/**
|
|
1207
|
-
* Resolves the implementation that should fulfil a digital-ID document type:
|
|
1208
|
-
* the first funnel entry that is active under the given config and platform.
|
|
1209
|
-
* `undefined` when nothing can run it (the chooser then shows no tile for it).
|
|
1210
|
-
*/
|
|
1211
|
-
function resolveDigitalIdImplementation(docType, config, platform) {
|
|
1212
|
-
for (const entry of DIGITAL_ID_REGISTRY[docType]) {
|
|
1213
|
-
if (!isEntryActive(entry, config, platform)) continue;
|
|
1214
|
-
if (entry.kind === "incodeWallet") return { kind: "incodeWallet" };
|
|
1215
|
-
const method = findConfiguredMethod(entry, config);
|
|
1216
|
-
return {
|
|
1217
|
-
kind: "trinsicRedirect",
|
|
1218
|
-
providerId: entry.providerId,
|
|
1219
|
-
method: method ? toMappedMethod(entry, method) : void 0
|
|
1220
|
-
};
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
//#endregion
|
|
1224
|
-
//#region src/modules/id/idCaptureHelpers.ts
|
|
1225
|
-
/**
|
|
1226
|
-
* Persisted method name → catalog provider id, derived from the digital-ID
|
|
1227
|
-
* registry's Trinsic entries (single source of truth — was a hardcoded map
|
|
1228
|
-
* here before the registry existed).
|
|
1229
|
-
*/
|
|
1230
|
-
const REDIRECT_PROVIDER_BY_METHOD = (() => {
|
|
1231
|
-
const map = {};
|
|
1232
|
-
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;
|
|
1233
|
-
return map;
|
|
1234
|
-
})();
|
|
1235
|
-
/**
|
|
1236
|
-
* The first enabled web-redirect digital-ID method (iDIN-only for now), or
|
|
1237
|
-
* `undefined` when none is configured. Drives both the `digitalIdRedirect`
|
|
1238
|
-
* chooser option and the provider passed to the `digitalIdRedirectMachine`.
|
|
1239
|
-
*
|
|
1240
|
-
* Accepts both the mapped array (`IdCaptureDigitalIdMethod[]`) and the raw
|
|
1241
|
-
* backend `configuration.digitalIds` object (`{ enabled, methods: [...] }`);
|
|
1242
|
-
* for the raw shape it derives `provider`/`flowType` from the persisted method
|
|
1243
|
-
* name via the digital-ID registry (`IDIN` → `trinsic_netherlands_idin`,
|
|
1244
|
-
* `WEB_REDIRECT`).
|
|
1245
|
-
*/
|
|
1246
|
-
function getDigitalIdRedirectMethod(config) {
|
|
1247
|
-
for (const method of normalizeDigitalIdMethods(config)) {
|
|
1248
|
-
if (method.flowType && isRedirectFlowType(method.flowType)) return method;
|
|
1249
|
-
const provider = method.method ? REDIRECT_PROVIDER_BY_METHOD[method.method.toUpperCase()] : void 0;
|
|
1250
|
-
if (provider) return {
|
|
1251
|
-
method: method.method,
|
|
1252
|
-
provider,
|
|
1253
|
-
flowType: "WEB_REDIRECT",
|
|
1254
|
-
country: method.country ?? method.countries?.[0],
|
|
1255
|
-
displayName: method.displayName
|
|
1256
|
-
};
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
/**
|
|
1260
|
-
* Map of config properties received from the backend to adjusted, internal document types.
|
|
1261
|
-
*/
|
|
1262
|
-
const DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP = [
|
|
1263
|
-
["enableId", "id"],
|
|
1264
|
-
["enablePassport", "passport"],
|
|
1265
|
-
["manualUploadIdCapture", "manualIdUpload"],
|
|
1266
|
-
["digitalIdsUpload", "digitalIdUpload"]
|
|
1267
|
-
];
|
|
1268
|
-
/**
|
|
1269
|
-
* Returns the list of document types enabled by config for the chooser screen, in display order.
|
|
1270
|
-
* Used to populate chooser state so UI and headless consumers can render the correct options.
|
|
1271
|
-
*
|
|
1272
|
-
* Digital-ID document types (device wallet, Trinsic web-redirect) come from
|
|
1273
|
-
* the digital-ID registry funnel: each registry document type contributes the
|
|
1274
|
-
* tile of its first active implementation. A `deviceWallet: true` config on a
|
|
1275
|
-
* platform without the Credentials API therefore shows the Trinsic fallback
|
|
1276
|
-
* tile when one is configured — or no tile at all, instead of a dead-end one.
|
|
1277
|
-
*
|
|
1278
|
-
* @param config - ID capture configuration (from flow or init)
|
|
1279
|
-
* @param platform - Platform capabilities consulted by the digital-ID funnel.
|
|
1280
|
-
* Defaults to no Credentials API for pure-node callers; the machine passes
|
|
1281
|
-
* the real capability check.
|
|
1282
|
-
* @returns Array of IdDocumentType values that should be shown in the document type chooser
|
|
1283
|
-
*/
|
|
1284
|
-
function getAvailableDocumentTypes(config, platform = { credentialsAvailable: false }) {
|
|
1285
|
-
if (config.onlyBack && config.manualUploadIdCapture) return config.enableId ? ["id", "manualIdUpload"] : ["manualIdUpload"];
|
|
1286
|
-
const adjustedDocumentTypes = [];
|
|
1287
|
-
for (const [configProperty, adjustedType] of DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP) if (config[configProperty]) adjustedDocumentTypes.push(adjustedType);
|
|
1288
|
-
for (const docType of DIGITAL_ID_DOCUMENT_TYPES) {
|
|
1289
|
-
const route = resolveDigitalIdImplementation(docType, config, platform);
|
|
1290
|
-
if (!route) continue;
|
|
1291
|
-
const documentType = route.kind === "incodeWallet" ? "digitalId" : "digitalIdRedirect";
|
|
1292
|
-
if (!adjustedDocumentTypes.includes(documentType)) adjustedDocumentTypes.push(documentType);
|
|
1293
|
-
}
|
|
1294
|
-
return adjustedDocumentTypes;
|
|
1295
|
-
}
|
|
949
|
+
const isProcessingExpiredExhaustedGuard = ({ context }) => context.processingExpiredAttempts + 1 >= context.config.captureAttempts;
|
|
1296
950
|
/**
|
|
1297
|
-
*
|
|
1298
|
-
*
|
|
951
|
+
* True when capturing the back side of a two-sided (front+back) ID flow.
|
|
952
|
+
* Used to redirect an expired-back capture to front rather than retrying
|
|
953
|
+
* the same back side (Figma Story #2.1).
|
|
954
|
+
* Excludes onlyBack and usSmartCapture — those are single-side back flows
|
|
955
|
+
* with no front to redirect to.
|
|
1299
956
|
*/
|
|
1300
|
-
|
|
1301
|
-
if (config.onlyBack) return {
|
|
1302
|
-
showIdTab: true,
|
|
1303
|
-
showPassportTab: false
|
|
1304
|
-
};
|
|
1305
|
-
const showIdTab = !!config.enableId;
|
|
1306
|
-
const showPassportTab = !!config.enablePassport;
|
|
1307
|
-
if (!showIdTab && !showPassportTab) return {
|
|
1308
|
-
showIdTab: true,
|
|
1309
|
-
showPassportTab: true
|
|
1310
|
-
};
|
|
1311
|
-
return {
|
|
1312
|
-
showIdTab,
|
|
1313
|
-
showPassportTab
|
|
1314
|
-
};
|
|
1315
|
-
}
|
|
957
|
+
const isBackModeInMultiSideFlowGuard = ({ context }) => context.currentMode === "back" && !context.config.onlyBack && !context.config.usSmartCapture;
|
|
1316
958
|
/**
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
1324
|
-
* Requiring a captured back is deliberate and load-bearing: the manual-upload
|
|
1325
|
-
* and digital-ID-upload paths submit a full ID (front face present) but do NOT
|
|
1326
|
-
* populate `capturedImages` (only the camera path does). Gating on a captured
|
|
1327
|
-
* back excludes those upload paths so a real ID-vs-selfie match is never
|
|
1328
|
-
* silently skipped. `capturedImages.front`/`forceFrontIdCapture` alone are not
|
|
1329
|
-
* enough (a later front upload clears the request; uploads set neither field).
|
|
1330
|
-
*
|
|
1331
|
-
* Always `false` outside US Smart Capture. The selfie/face capture itself is
|
|
1332
|
-
* unaffected — only the ID-vs-selfie match is skipped.
|
|
1333
|
-
*
|
|
1334
|
-
* Also `true` on the Digital ID web-redirect (Trinsic iDIN/FTN) COMPLETED path
|
|
1335
|
-
* when the scheme returned no portrait (`isDigitalIdRedirect && !portraitPresent`,
|
|
1336
|
-
* FM-1/FM-2): there is no ID face to match the selfie against.
|
|
959
|
+
* True once the user has already been redirected from an expired second-side
|
|
960
|
+
* (back) capture to the first side (front) for their one extra attempt
|
|
961
|
+
* (V1's `expiredRedirected`). Used to make the expired-back→front redirect a
|
|
962
|
+
* one-shot: any subsequent expired upload routes to `expiredExhausted` instead
|
|
963
|
+
* of redirecting again, so total captures stay within the backend's
|
|
964
|
+
* max-attempts/OCR cap (ENG-46592 / re-respects ENG-45666).
|
|
1337
965
|
*/
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
const backIdCaptured = Boolean(context.capturedImages.back);
|
|
1341
|
-
return {
|
|
1342
|
-
frontIdCaptured,
|
|
1343
|
-
skipFaceMatch: context.isDigitalIdRedirect === true && context.portraitPresent !== true || context.config.usSmartCapture === true && backIdCaptured && !frontIdCaptured
|
|
1344
|
-
};
|
|
1345
|
-
}
|
|
966
|
+
const wasExpiredRedirectedGuard = ({ context }) => context.expiredRedirected === true;
|
|
967
|
+
const hasManualCaptureTriggeredGuard = ({ context }) => context.manualCaptureTriggered;
|
|
1346
968
|
//#endregion
|
|
1347
969
|
//#region src/modules/id/idDetectionNotificationController.ts
|
|
1348
970
|
const NOTIFICATION_DURATION_MS = 500;
|
|
@@ -1418,9 +1040,26 @@ async function requestIdCapturePermission(input) {
|
|
|
1418
1040
|
cameraFallbackLevel: fallbackLevel
|
|
1419
1041
|
};
|
|
1420
1042
|
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Resolves and primes Deepsight motion without touching camera permission.
|
|
1045
|
+
* IDC-03 invokes this directly from the tutorial CTA's event macrostep so
|
|
1046
|
+
* iOS keeps the transient user activation required by DeviceMotion.
|
|
1047
|
+
*/
|
|
1048
|
+
async function requestIdCaptureMotionPermission() {
|
|
1049
|
+
const result = await requestMotionPermission();
|
|
1050
|
+
return result === "not-required" ? "granted" : result;
|
|
1051
|
+
}
|
|
1421
1052
|
const requestPermissionActor = fromPromise(async ({ input }) => {
|
|
1422
1053
|
return requestIdCapturePermission(input);
|
|
1423
1054
|
});
|
|
1055
|
+
/**
|
|
1056
|
+
* Takes no `AbortSignal` on purpose: the work it awaits is the OS-owned
|
|
1057
|
+
* `DeviceMotionEvent.requestPermission()` prompt, which exposes no
|
|
1058
|
+
* cancellation. XState still discards the settled result if the state is
|
|
1059
|
+
* left, and `primeWasmMotionSensor` is idempotent, so an abandoned request
|
|
1060
|
+
* cannot mis-drive the machine.
|
|
1061
|
+
*/
|
|
1062
|
+
const requestMotionPermissionActor = fromPromise(() => requestIdCaptureMotionPermission());
|
|
1424
1063
|
fromPromise(async ({ input }) => {
|
|
1425
1064
|
return initializeIdCapture(input);
|
|
1426
1065
|
});
|
|
@@ -1781,7 +1420,7 @@ fromPromise(async ({ input }) => {
|
|
|
1781
1420
|
});
|
|
1782
1421
|
fromPromise(async ({ input }) => {
|
|
1783
1422
|
if (!input.dependencies) return;
|
|
1784
|
-
const { loadDeepsightSession } = await import("./deepsightLoader-
|
|
1423
|
+
const { loadDeepsightSession } = await import("./deepsightLoader-DZMdYSl-.esm.js");
|
|
1785
1424
|
return loadDeepsightSession({
|
|
1786
1425
|
ds: input.ds,
|
|
1787
1426
|
storage: input.dependencies.storage,
|
|
@@ -2224,7 +1863,7 @@ function cleanup(service) {
|
|
|
2224
1863
|
service.cleanup();
|
|
2225
1864
|
} catch {}
|
|
2226
1865
|
}
|
|
2227
|
-
function createIdMetadataPreparationCoordinator(load = async (input) => (await import("./deepsightLoader-
|
|
1866
|
+
function createIdMetadataPreparationCoordinator(load = async (input) => (await import("./deepsightLoader-DZMdYSl-.esm.js")).loadDeepsightSession(input)) {
|
|
2228
1867
|
let disposed = false;
|
|
2229
1868
|
let preparation;
|
|
2230
1869
|
let service;
|
|
@@ -2257,6 +1896,46 @@ function createIdMetadataPreparationCoordinator(load = async (input) => (await i
|
|
|
2257
1896
|
};
|
|
2258
1897
|
}
|
|
2259
1898
|
//#endregion
|
|
1899
|
+
//#region src/modules/id/idCaptureOnlyConfig.ts
|
|
1900
|
+
/**
|
|
1901
|
+
* The `IdCaptureConfig` keys the captureOnly flow supports.
|
|
1902
|
+
*/
|
|
1903
|
+
const ID_CAPTURE_ONLY_CONFIG_KEYS = [
|
|
1904
|
+
"showTutorial",
|
|
1905
|
+
"captureAttempts",
|
|
1906
|
+
"autoCaptureTimeout",
|
|
1907
|
+
"deviceIdleTimeout",
|
|
1908
|
+
"enableId",
|
|
1909
|
+
"enablePassport",
|
|
1910
|
+
"onlyFront",
|
|
1911
|
+
"onlyBack",
|
|
1912
|
+
"showDocumentChooserScreen"
|
|
1913
|
+
];
|
|
1914
|
+
/**
|
|
1915
|
+
* `onCapture` marks a config as captureOnly. It is not part of
|
|
1916
|
+
* `IdCaptureConfig`, but JavaScript callers (and `<incode-id>`'s `config`
|
|
1917
|
+
* property) can still pass it.
|
|
1918
|
+
*/
|
|
1919
|
+
function hasOnCaptureCallback(config) {
|
|
1920
|
+
return typeof config.onCapture === "function";
|
|
1921
|
+
}
|
|
1922
|
+
/** Keeps the supported keys and `onCapture`, dropping backend-only options. */
|
|
1923
|
+
function pickIdCaptureOnlyConfig(config) {
|
|
1924
|
+
return {
|
|
1925
|
+
...Object.fromEntries(ID_CAPTURE_ONLY_CONFIG_KEYS.filter((key) => config[key] !== void 0).map((key) => [key, config[key]])),
|
|
1926
|
+
onCapture: config.onCapture
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* Whether the captureOnly flow needs the back side after this capture. There
|
|
1931
|
+
* is no backend answer (`skipBackIdCapture`), so `onlyFront` decides. Drives
|
|
1932
|
+
* both the `shouldContinueToBack` guard and the manager's `needsBackCapture`.
|
|
1933
|
+
*/
|
|
1934
|
+
function captureOnlyNeedsBack({ currentMode, config }) {
|
|
1935
|
+
if (currentMode !== "front" && currentMode !== "passport") return false;
|
|
1936
|
+
return !config.onlyFront && !config.onlyBack && !config.usSmartCapture;
|
|
1937
|
+
}
|
|
1938
|
+
//#endregion
|
|
2260
1939
|
//#region src/modules/id/idProtectedCapture.ts
|
|
2261
1940
|
const ID_PROTECTED_CAPTURE_CONTROLLER = Symbol("idProtectedCaptureController");
|
|
2262
1941
|
function attachIdProtectedCaptureController(owner, controller) {
|
|
@@ -2294,12 +1973,12 @@ function streamUsesBackCamera(stream) {
|
|
|
2294
1973
|
const track = stream.getVideoTracks()[0];
|
|
2295
1974
|
if (!track) return;
|
|
2296
1975
|
const settings = typeof track.getSettings === "function" ? track.getSettings() : {};
|
|
2297
|
-
const constrainedFacingMode = typeof track.getConstraints === "function" ? track.getConstraints().facingMode : void 0;
|
|
1976
|
+
const constrainedFacingMode = getDeviceClass() !== "desktop" && typeof track.getConstraints === "function" ? track.getConstraints().facingMode : void 0;
|
|
2298
1977
|
const facingMode = settings.facingMode ?? (typeof constrainedFacingMode === "string" ? constrainedFacingMode : void 0);
|
|
2299
1978
|
if (facingMode === "environment") return true;
|
|
2300
1979
|
if (facingMode === "user") return false;
|
|
2301
1980
|
const label = typeof track.label === "string" ? track.label.toLowerCase() : "";
|
|
2302
|
-
if (
|
|
1981
|
+
if (isBackCameraLabel(label)) return true;
|
|
2303
1982
|
if (label.includes("front") || label.includes("user")) return false;
|
|
2304
1983
|
}
|
|
2305
1984
|
function createIdProtectedCaptureController(dependencies = {}) {
|
|
@@ -2400,6 +2079,7 @@ function createIdProtectedCaptureController(dependencies = {}) {
|
|
|
2400
2079
|
};
|
|
2401
2080
|
const clearAttempt = () => {
|
|
2402
2081
|
if (diagnosticAttempt) logDiagnostic("attempt-release", { committed });
|
|
2082
|
+
noteTrueSightCaptureActivity(false);
|
|
2403
2083
|
attemptGeneration += 1;
|
|
2404
2084
|
frameCapturer?.dispose();
|
|
2405
2085
|
frameCapturer = void 0;
|
|
@@ -2480,6 +2160,7 @@ function createIdProtectedCaptureController(dependencies = {}) {
|
|
|
2480
2160
|
provider = (dependencies.createProvider ?? createProtectedIdProvider)(context.config, context.currentMode);
|
|
2481
2161
|
cycleOwnership = createCameraCycleOwnership(cameraCycleProvider);
|
|
2482
2162
|
logDiagnostic("attempt-start", { aggregationMs: context.config?.thresholds?.framesAggregationInterval ?? DEFAULT_ID_CAPTURE_THRESHOLDS.framesAggregationInterval });
|
|
2163
|
+
noteTrueSightCaptureActivity(true);
|
|
2483
2164
|
},
|
|
2484
2165
|
startMetadataPreparation(context) {
|
|
2485
2166
|
const storage = context.dependencies?.storage;
|
|
@@ -2654,6 +2335,7 @@ function createIdProtectedCaptureController(dependencies = {}) {
|
|
|
2654
2335
|
autoCommitted: storeCommit,
|
|
2655
2336
|
manualCommitted: storeCommit,
|
|
2656
2337
|
finalized(_recording, stream) {
|
|
2338
|
+
noteTrueSightCaptureActivity(false);
|
|
2657
2339
|
if (!stream || disposed) {
|
|
2658
2340
|
logDiagnostic("attempt-finalized");
|
|
2659
2341
|
return;
|
|
@@ -2896,6 +2578,8 @@ function createProtectedIdCallbackSession(input) {
|
|
|
2896
2578
|
let countdownTimers = [];
|
|
2897
2579
|
let qualityElements;
|
|
2898
2580
|
let isCapturing = false;
|
|
2581
|
+
let active = true;
|
|
2582
|
+
let paused = false;
|
|
2899
2583
|
let lastReportedSide = null;
|
|
2900
2584
|
let blurSignals = 0;
|
|
2901
2585
|
let bestFrameSignals = 0;
|
|
@@ -2922,7 +2606,7 @@ function createProtectedIdCallbackSession(input) {
|
|
|
2922
2606
|
};
|
|
2923
2607
|
const startCountdown = () => {
|
|
2924
2608
|
clearCountdown();
|
|
2925
|
-
const stepMs = (input.context.config
|
|
2609
|
+
const stepMs = resolveCountdownStepMs(input.context.config);
|
|
2926
2610
|
input.send({
|
|
2927
2611
|
type: "COUNTER_VALUE_CHANGE",
|
|
2928
2612
|
value: 3
|
|
@@ -2937,6 +2621,7 @@ function createProtectedIdCallbackSession(input) {
|
|
|
2937
2621
|
}), stepMs * (index + 1)));
|
|
2938
2622
|
};
|
|
2939
2623
|
const setDetectionStatus = (status) => {
|
|
2624
|
+
trueSightHintTransition("module.id-capture", "idScan", status);
|
|
2940
2625
|
input.send({
|
|
2941
2626
|
type: "DETECTION_UPDATE",
|
|
2942
2627
|
status
|
|
@@ -2946,114 +2631,139 @@ function createProtectedIdCallbackSession(input) {
|
|
|
2946
2631
|
send: setDetectionStatus,
|
|
2947
2632
|
isSuppressed: () => isReportedIdSideWrong(input.context.currentMode, lastReportedSide)
|
|
2948
2633
|
});
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
}
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
input.send({ type: "PROTECTED_OPTIMIZING" });
|
|
2997
|
-
}
|
|
2998
|
-
}, input.context.captureWindowMs);
|
|
2999
|
-
}
|
|
3000
|
-
},
|
|
3001
|
-
onBestFrame: (blur, glare, orientation) => {
|
|
3002
|
-
bestFrameSignals += 1;
|
|
3003
|
-
bestBlur = bestBlur === void 0 ? blur : Math.min(bestBlur, blur);
|
|
3004
|
-
qualityElements = {
|
|
3005
|
-
glare,
|
|
3006
|
-
sharpness: blur
|
|
3007
|
-
};
|
|
3008
|
-
if (orientation === "horizontal" || orientation === "vertical") input.send({
|
|
3009
|
-
type: "ORIENTATION_CHANGE",
|
|
3010
|
-
orientation
|
|
3011
|
-
});
|
|
3012
|
-
},
|
|
3013
|
-
onCapture: (canvas) => {
|
|
3014
|
-
isCapturing = false;
|
|
2634
|
+
const callbacks = {
|
|
2635
|
+
onFarAway: () => {
|
|
2636
|
+
if (!active || paused) return;
|
|
2637
|
+
if (!isCapturing) notifications.show("farAway");
|
|
2638
|
+
},
|
|
2639
|
+
onDetectionStarted: () => {},
|
|
2640
|
+
onMaskChange: (_show, _mask, _top, orientation) => {
|
|
2641
|
+
if (!active || paused) return;
|
|
2642
|
+
input.send({
|
|
2643
|
+
type: "ORIENTATION_CHANGE",
|
|
2644
|
+
orientation
|
|
2645
|
+
});
|
|
2646
|
+
},
|
|
2647
|
+
onBlur: () => {
|
|
2648
|
+
if (!active || paused) return;
|
|
2649
|
+
blurSignals += 1;
|
|
2650
|
+
if (!isCapturing) notifications.show("blur");
|
|
2651
|
+
},
|
|
2652
|
+
onGlare: () => {
|
|
2653
|
+
if (!active || paused) return;
|
|
2654
|
+
if (!isCapturing) notifications.show("glare");
|
|
2655
|
+
},
|
|
2656
|
+
onIdNotDetected: () => {
|
|
2657
|
+
if (!active || paused) return;
|
|
2658
|
+
if (!isCapturing) setDetectionStatus("idNotDetected");
|
|
2659
|
+
},
|
|
2660
|
+
onSwitchToManualCapture: () => {
|
|
2661
|
+
if (!active || paused) return;
|
|
2662
|
+
isCapturing = false;
|
|
2663
|
+
notifications.clear();
|
|
2664
|
+
clearOptimizingBoundary();
|
|
2665
|
+
clearCountdown();
|
|
2666
|
+
input.send({ type: input.controller.hasCommit() ? "PROTECTED_RELEASE_STASHED_COMMIT" : "SWITCH_TO_MANUAL_CAPTURE" });
|
|
2667
|
+
},
|
|
2668
|
+
onCapturing: () => {
|
|
2669
|
+
if (!active || paused) return;
|
|
2670
|
+
const wasCapturing = isCapturing;
|
|
2671
|
+
notifications.clear();
|
|
2672
|
+
lastReportedSide = null;
|
|
2673
|
+
isCapturing = true;
|
|
2674
|
+
setDetectionStatus("capturing");
|
|
2675
|
+
if (!wasCapturing) logDiagnostic("capture-window", {
|
|
2676
|
+
aggregationMs: input.context.config.thresholds?.framesAggregationInterval ?? DEFAULT_ID_CAPTURE_THRESHOLDS.framesAggregationInterval,
|
|
2677
|
+
blurSignals
|
|
2678
|
+
});
|
|
2679
|
+
if (!wasCapturing && input.context.captureFeedbackMode === "countdown") startCountdown();
|
|
2680
|
+
if (input.context.captureFeedbackMode === "optimizing" && input.context.config.supportsOptimizingStatus === true && input.context.captureWindowMs != null) {
|
|
3015
2681
|
clearOptimizingBoundary();
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
});
|
|
3024
|
-
input.controller.storeAutoCaptureFrame(canvas);
|
|
3025
|
-
input.send({
|
|
3026
|
-
type: "PROTECTED_AUTO_CAPTURE",
|
|
3027
|
-
qualityElements
|
|
3028
|
-
});
|
|
3029
|
-
},
|
|
3030
|
-
onIdTypeChange: (idType) => {
|
|
3031
|
-
input.send({
|
|
3032
|
-
type: "ID_TYPE_CHANGE",
|
|
3033
|
-
idType
|
|
3034
|
-
});
|
|
3035
|
-
},
|
|
3036
|
-
onIdSideChange: (side) => {
|
|
3037
|
-
if (isCapturing) return;
|
|
3038
|
-
lastReportedSide = side;
|
|
3039
|
-
if (isReportedIdSideWrong(input.context.currentMode, lastReportedSide)) notifications.clear();
|
|
3040
|
-
input.send({
|
|
3041
|
-
type: "ID_SIDE_CHANGE",
|
|
3042
|
-
side
|
|
3043
|
-
});
|
|
3044
|
-
},
|
|
3045
|
-
onCapturingCounterValueChange: () => {},
|
|
3046
|
-
onBarcodeDecoded: (decoded) => {
|
|
3047
|
-
input.send({
|
|
3048
|
-
type: "BARCODE_DECODED",
|
|
3049
|
-
decoded
|
|
3050
|
-
});
|
|
2682
|
+
optimizingBoundary = timer.setTimeout(() => {
|
|
2683
|
+
optimizingBoundary = null;
|
|
2684
|
+
const presentation = input.controller.getPresentationCanvas();
|
|
2685
|
+
if (presentation) {
|
|
2686
|
+
presentation.release();
|
|
2687
|
+
input.send({ type: "PROTECTED_OPTIMIZING" });
|
|
2688
|
+
}
|
|
2689
|
+
}, input.context.captureWindowMs);
|
|
3051
2690
|
}
|
|
3052
2691
|
},
|
|
3053
|
-
|
|
3054
|
-
|
|
2692
|
+
onBestFrame: (blur, glare, orientation) => {
|
|
2693
|
+
if (!active || paused) return;
|
|
2694
|
+
bestFrameSignals += 1;
|
|
2695
|
+
bestBlur = bestBlur === void 0 ? blur : Math.min(bestBlur, blur);
|
|
2696
|
+
qualityElements = {
|
|
2697
|
+
glare,
|
|
2698
|
+
sharpness: blur
|
|
2699
|
+
};
|
|
2700
|
+
if (orientation === "horizontal" || orientation === "vertical") input.send({
|
|
2701
|
+
type: "ORIENTATION_CHANGE",
|
|
2702
|
+
orientation
|
|
2703
|
+
});
|
|
2704
|
+
},
|
|
2705
|
+
onCapture: (canvas) => {
|
|
2706
|
+
if (!active || paused) return;
|
|
2707
|
+
isCapturing = false;
|
|
3055
2708
|
clearOptimizingBoundary();
|
|
3056
2709
|
clearCountdown();
|
|
2710
|
+
logDiagnostic("capture-selected", {
|
|
2711
|
+
blurSignals,
|
|
2712
|
+
bestFrameSignals,
|
|
2713
|
+
bestBlur,
|
|
2714
|
+
selectedBlur: qualityElements?.sharpness,
|
|
2715
|
+
selectedGlare: qualityElements?.glare
|
|
2716
|
+
});
|
|
2717
|
+
input.controller.storeAutoCaptureFrame(canvas);
|
|
2718
|
+
input.send({
|
|
2719
|
+
type: "PROTECTED_AUTO_CAPTURE",
|
|
2720
|
+
qualityElements
|
|
2721
|
+
});
|
|
2722
|
+
},
|
|
2723
|
+
onIdTypeChange: (idType) => {
|
|
2724
|
+
if (!active || paused) return;
|
|
2725
|
+
input.send({
|
|
2726
|
+
type: "ID_TYPE_CHANGE",
|
|
2727
|
+
idType
|
|
2728
|
+
});
|
|
2729
|
+
},
|
|
2730
|
+
onIdSideChange: (side) => {
|
|
2731
|
+
if (!active || paused) return;
|
|
2732
|
+
if (isCapturing) return;
|
|
2733
|
+
lastReportedSide = side;
|
|
2734
|
+
if (isReportedIdSideWrong(input.context.currentMode, lastReportedSide)) notifications.clear();
|
|
2735
|
+
input.send({
|
|
2736
|
+
type: "ID_SIDE_CHANGE",
|
|
2737
|
+
side
|
|
2738
|
+
});
|
|
2739
|
+
},
|
|
2740
|
+
onCapturingCounterValueChange: () => {},
|
|
2741
|
+
onBarcodeDecoded: (decoded) => {
|
|
2742
|
+
if (!active || paused) return;
|
|
2743
|
+
input.send({
|
|
2744
|
+
type: "BARCODE_DECODED",
|
|
2745
|
+
decoded
|
|
2746
|
+
});
|
|
2747
|
+
}
|
|
2748
|
+
};
|
|
2749
|
+
const pause = () => {
|
|
2750
|
+
paused = true;
|
|
2751
|
+
notifications.clear();
|
|
2752
|
+
clearOptimizingBoundary();
|
|
2753
|
+
clearCountdown();
|
|
2754
|
+
isCapturing = false;
|
|
2755
|
+
qualityElements = void 0;
|
|
2756
|
+
lastReportedSide = null;
|
|
2757
|
+
};
|
|
2758
|
+
return {
|
|
2759
|
+
callbacks,
|
|
2760
|
+
pause,
|
|
2761
|
+
resume: () => {
|
|
2762
|
+
paused = false;
|
|
2763
|
+
},
|
|
2764
|
+
dispose: () => {
|
|
2765
|
+
active = false;
|
|
2766
|
+
pause();
|
|
3057
2767
|
}
|
|
3058
2768
|
};
|
|
3059
2769
|
}
|
|
@@ -3068,7 +2778,7 @@ function createProtectedIdAttemptInput(input) {
|
|
|
3068
2778
|
const preAcquired = controller.takePreAcquiredStream();
|
|
3069
2779
|
let selectedVideoTrack = preAcquired?.stream.getVideoTracks()[0];
|
|
3070
2780
|
const constraints = getCameraReacquisitionConstraints(selectedVideoTrack, preAcquired?.constraints);
|
|
3071
|
-
const captureOnly =
|
|
2781
|
+
const captureOnly = hasOnCaptureCallback(context.config);
|
|
3072
2782
|
const diagnosticAttempt = controller.getDiagnosticAttempt();
|
|
3073
2783
|
const isAttemptActive = () => !controller.disposed && controller.getProvider() === provider && controller.getDiagnosticAttempt() === diagnosticAttempt;
|
|
3074
2784
|
const logSelectedCamera = (stream, fallbackLevel, reacquisitionConstraints, preAcquiredStream) => {
|
|
@@ -3137,6 +2847,11 @@ function createProtectedIdAttemptInput(input) {
|
|
|
3137
2847
|
...timing
|
|
3138
2848
|
});
|
|
3139
2849
|
},
|
|
2850
|
+
pauseDetection: callbackSession.pause,
|
|
2851
|
+
resumeDetection(reset) {
|
|
2852
|
+
if (reset) provider.resetDetectionState();
|
|
2853
|
+
callbackSession.resume();
|
|
2854
|
+
},
|
|
3140
2855
|
async configureWorkflow() {
|
|
3141
2856
|
await provider.initialize({});
|
|
3142
2857
|
configureIdCaptureProvider({
|
|
@@ -3199,52 +2914,383 @@ function createProtectedIdAttemptInput(input) {
|
|
|
3199
2914
|
}
|
|
3200
2915
|
};
|
|
3201
2916
|
}
|
|
3202
|
-
function protectedIdResultToCaptureResponse(result) {
|
|
3203
|
-
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;
|
|
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
|
|
3136
|
+
};
|
|
3137
|
+
}
|
|
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;
|
|
3204
3176
|
return {
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
readability: result.readability === true,
|
|
3212
|
-
typeOfId: result.typeOfId ?? "",
|
|
3213
|
-
issueYear: 0,
|
|
3214
|
-
issueName: "",
|
|
3215
|
-
sessionStatus: result.sessionStatus ?? "",
|
|
3216
|
-
countryCode: result.countryCode ?? "",
|
|
3217
|
-
skipBackIdCapture: result.skipBackIdCapture,
|
|
3218
|
-
skipGlareFront: result.skipGlareFront,
|
|
3219
|
-
skipGlareBack: result.skipGlareBack,
|
|
3220
|
-
acceptedDocuments: result.acceptedDocuments ? [...result.acceptedDocuments] : void 0,
|
|
3221
|
-
forceFrontIdCapture: result.forceFrontIdCapture,
|
|
3222
|
-
idValidationCompleted: result.idValidationCompleted,
|
|
3223
|
-
showMandatoryConsent: result.showMandatoryConsent,
|
|
3224
|
-
regulationType,
|
|
3225
|
-
failReason: result.failReason,
|
|
3226
|
-
side: result.side,
|
|
3227
|
-
idQualityAttemptApproved: result.idQualityAttemptApproved,
|
|
3228
|
-
isDocumentExpired: result.isDocumentExpired,
|
|
3229
|
-
success: result.success
|
|
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
|
|
3230
3183
|
};
|
|
3231
3184
|
}
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
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);
|
|
3290
|
+
return {
|
|
3291
|
+
frontIdCaptured,
|
|
3292
|
+
skipFaceMatch: context.isDigitalIdRedirect === true && context.portraitPresent !== true || context.config.usSmartCapture === true && backIdCaptured && !frontIdCaptured
|
|
3243
3293
|
};
|
|
3244
|
-
return Object.keys(config).length > 0 ? {
|
|
3245
|
-
target,
|
|
3246
|
-
config
|
|
3247
|
-
} : { target };
|
|
3248
3294
|
}
|
|
3249
3295
|
//#endregion
|
|
3250
3296
|
//#region src/modules/digital-id-redirect/pollCadence.ts
|
|
@@ -3765,9 +3811,6 @@ function getIdErrorCodeFromUnknown(error) {
|
|
|
3765
3811
|
function asPublicIdEvent(event) {
|
|
3766
3812
|
return event;
|
|
3767
3813
|
}
|
|
3768
|
-
function isCaptureOnlyConfig(config) {
|
|
3769
|
-
return "onCapture" in config && typeof config.onCapture === "function";
|
|
3770
|
-
}
|
|
3771
3814
|
function protectedFailure(event) {
|
|
3772
3815
|
return event.type === "PROTECTED_ATTEMPT_FAILED" ? event : null;
|
|
3773
3816
|
}
|
|
@@ -3781,13 +3824,13 @@ const idCaptureMachine = setup({
|
|
|
3781
3824
|
actors: {
|
|
3782
3825
|
checkPermission: checkPermissionActor,
|
|
3783
3826
|
requestPermission: requestPermissionActor,
|
|
3827
|
+
requestMotionPermission: requestMotionPermissionActor,
|
|
3784
3828
|
protectedAttempt: createProtectedIdAttemptActor(),
|
|
3785
3829
|
protectedControllerLifetime: createProtectedIdControllerLifetimeActor(),
|
|
3786
3830
|
captureOnlyDelivery: createIdCaptureOnlyDeliveryActor(),
|
|
3787
3831
|
uploadProgressTicker: uploadProgressTickerActor,
|
|
3788
3832
|
processId: processIdActor,
|
|
3789
3833
|
submitBarcode: submitBarcodeActor,
|
|
3790
|
-
manualUploadMachine,
|
|
3791
3834
|
digitalUploadMachine,
|
|
3792
3835
|
digitalIdRedirectMachine,
|
|
3793
3836
|
deviceWalletMachine,
|
|
@@ -3804,7 +3847,7 @@ const idCaptureMachine = setup({
|
|
|
3804
3847
|
return {};
|
|
3805
3848
|
}),
|
|
3806
3849
|
startProtectedMetadataPreparation: ({ context, self }) => {
|
|
3807
|
-
if (!
|
|
3850
|
+
if (!hasOnCaptureCallback(context.config)) getIdProtectedCaptureController(self).startMetadataPreparation(context);
|
|
3808
3851
|
},
|
|
3809
3852
|
bindProtectedControllerLifetime: sendTo("protectedControllerLifetime", ({ self }) => ({
|
|
3810
3853
|
type: "BIND_PROTECTED_ID_CONTROLLER",
|
|
@@ -3845,7 +3888,7 @@ const idCaptureMachine = setup({
|
|
|
3845
3888
|
requestProtectedManualCommit: sendTo("protectedAttempt", { type: "MANUAL_CAPTURE" }),
|
|
3846
3889
|
finalizeProtectedAttempt: sendTo("protectedAttempt", { type: "FINALIZE" }),
|
|
3847
3890
|
requestProtectedUpload: enqueueActions(({ context, enqueue }) => {
|
|
3848
|
-
if (
|
|
3891
|
+
if (hasOnCaptureCallback(context.config)) return;
|
|
3849
3892
|
enqueue(sendTo("protectedAttempt", {
|
|
3850
3893
|
type: "UPLOAD_PROTECTED",
|
|
3851
3894
|
request: getProtectedIdUploadRequest(context)
|
|
@@ -3863,6 +3906,25 @@ const idCaptureMachine = setup({
|
|
|
3863
3906
|
type: "RELEASE",
|
|
3864
3907
|
reason: "retry"
|
|
3865
3908
|
}),
|
|
3909
|
+
pauseProtectedDetection: sendTo("protectedAttempt", { type: "PAUSE_DETECTION" }),
|
|
3910
|
+
resumeProtectedDetection: sendTo("protectedAttempt", ({ context }) => ({
|
|
3911
|
+
type: "RESUME_DETECTION",
|
|
3912
|
+
reset: !context.manualCaptureTriggered
|
|
3913
|
+
})),
|
|
3914
|
+
resetAutomaticCapture: assign({
|
|
3915
|
+
manualCaptureTriggered: false,
|
|
3916
|
+
detectionStatus: "idle",
|
|
3917
|
+
counterValue: 0,
|
|
3918
|
+
decodedBarcode: null,
|
|
3919
|
+
barcodeFastPathAttempted: false,
|
|
3920
|
+
qualityElements: void 0
|
|
3921
|
+
}),
|
|
3922
|
+
trackSwitchToAutoCapture: ({ context }) => {
|
|
3923
|
+
addEvent({
|
|
3924
|
+
code: context.currentMode === "back" ? "switchToAutoCaptureBackId" : "switchToAutoCaptureFrontId",
|
|
3925
|
+
module: eventModuleNames.idCapture
|
|
3926
|
+
});
|
|
3927
|
+
},
|
|
3866
3928
|
forwardProtectedBackground: sendTo("protectedAttempt", { type: "BACKGROUND" }),
|
|
3867
3929
|
forwardProtectedForeground: sendTo("protectedAttempt", { type: "FOREGROUND" }),
|
|
3868
3930
|
storeProtectedAutoQuality: assign(({ event }) => event.type === "PROTECTED_AUTO_CAPTURE" ? { qualityElements: event.qualityElements } : {}),
|
|
@@ -4047,9 +4109,12 @@ const idCaptureMachine = setup({
|
|
|
4047
4109
|
performStopMediaRecording(context);
|
|
4048
4110
|
},
|
|
4049
4111
|
clearRecordingSession: assign({ recordingSession: () => void 0 }),
|
|
4050
|
-
setSelectedDocument: assign({
|
|
4051
|
-
|
|
4052
|
-
|
|
4112
|
+
setSelectedDocument: assign({
|
|
4113
|
+
selectedDocumentType: ({ event }) => {
|
|
4114
|
+
if ("documentType" in event) return event.documentType;
|
|
4115
|
+
},
|
|
4116
|
+
selectedDigitalIdProviderId: ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "digitalIdRedirect" ? event.providerId : void 0
|
|
4117
|
+
}),
|
|
4053
4118
|
setCurrentMode: assign({ currentMode: ({ event, context }) => getCurrentModeFromEvent(context, asPublicIdEvent(event)) }),
|
|
4054
4119
|
storeCapturedImage: assign(({ context, event }) => getStoreCapturedImageValues(context, asPublicIdEvent(event))),
|
|
4055
4120
|
setCandidateFrame: assign(({ context, event }) => getCandidateFrameValues(context, asPublicIdEvent(event))),
|
|
@@ -4190,6 +4255,22 @@ const idCaptureMachine = setup({
|
|
|
4190
4255
|
digitalIdResumeProviderId: pending?.providerId
|
|
4191
4256
|
};
|
|
4192
4257
|
}),
|
|
4258
|
+
/**
|
|
4259
|
+
* Drops the inputs that belong to one digital-ID attempt: the return-leg
|
|
4260
|
+
* params and the recovered verificationId/providerId, plus the funnel
|
|
4261
|
+
* route. The `digitalIdRedirect` child copies what it needs on entry, so
|
|
4262
|
+
* once it exits nothing reads them — but left in place they are replayed
|
|
4263
|
+
* on the next redirect selection. The return leg would re-submit the
|
|
4264
|
+
* previous provider's result (the user picks iDIN and gets FTN's
|
|
4265
|
+
* cancelled screen back), and a stale route would override the card the
|
|
4266
|
+
* user just picked.
|
|
4267
|
+
*/
|
|
4268
|
+
clearDigitalIdAttempt: assign({
|
|
4269
|
+
digitalIdReturnParams: () => void 0,
|
|
4270
|
+
digitalIdResumeVerificationId: () => void 0,
|
|
4271
|
+
digitalIdResumeProviderId: () => void 0,
|
|
4272
|
+
digitalIdRoute: () => void 0
|
|
4273
|
+
}),
|
|
4193
4274
|
incrementProcessingExpiredAttempts: assign(({ context }) => ({ processingExpiredAttempts: context.processingExpiredAttempts + 1 })),
|
|
4194
4275
|
setSkipProcessId: assign({ skipProcessId: () => true }),
|
|
4195
4276
|
setExpiredFromUpload: assign({ expiredFromUpload: () => true }),
|
|
@@ -4199,7 +4280,7 @@ const idCaptureMachine = setup({
|
|
|
4199
4280
|
clearExpiredFromUpload: assign({ expiredFromUpload: () => false })
|
|
4200
4281
|
},
|
|
4201
4282
|
guards: {
|
|
4202
|
-
isCaptureOnlyDelivery: ({ context }) =>
|
|
4283
|
+
isCaptureOnlyDelivery: ({ context }) => hasOnCaptureCallback(context.config),
|
|
4203
4284
|
isProtectedUploadFailure: ({ event }) => protectedFailure(event)?.failure.stage === "upload",
|
|
4204
4285
|
isProtectedManualRefusal: ({ event }) => protectedFailure(event)?.failure.stage === "manualCommit",
|
|
4205
4286
|
hasShowTutorial: hasShowTutorialGuard,
|
|
@@ -4216,6 +4297,7 @@ const idCaptureMachine = setup({
|
|
|
4216
4297
|
}),
|
|
4217
4298
|
isPermissionDeniedError: ({ event }) => isPermissionDeniedErrorGuard({ event: asPublicIdEvent(event) }),
|
|
4218
4299
|
isPermissionBlocked: isPermissionBlockedGuard,
|
|
4300
|
+
requiresMotionPermissionUserGesture: requiresMotionPermissionUserGestureGuard,
|
|
4219
4301
|
hasAttemptsRemaining: hasAttemptsRemainingGuard,
|
|
4220
4302
|
hasCapturedImage: hasCapturedImageGuard,
|
|
4221
4303
|
hasCandidateFrame: ({ event }) => hasCandidateFrameGuard({ event: asPublicIdEvent(event) }),
|
|
@@ -4229,9 +4311,7 @@ const idCaptureMachine = setup({
|
|
|
4229
4311
|
isDeepsightEnabled: isDeepsightEnabledGuard,
|
|
4230
4312
|
isDeepsightReady: isDeepsightReadyGuard,
|
|
4231
4313
|
needsDeepsightInit: needsDeepsightInitGuard,
|
|
4232
|
-
hasOnlyManualUploadAvailable: hasOnlyManualUploadAvailableGuard,
|
|
4233
4314
|
hasNoDocumentTypesAvailable: hasNoDocumentTypesAvailableGuard,
|
|
4234
|
-
isManualIdUploadSelected: ({ event }) => isManualIdUploadSelectedGuard({ event: asPublicIdEvent(event) }),
|
|
4235
4315
|
isDigitalIdUploadSelected: ({ event }) => isDigitalIdUploadSelectedGuard({ event: asPublicIdEvent(event) }),
|
|
4236
4316
|
isDigitalIdRedirectSelected: ({ event }) => isDigitalIdRedirectSelectedGuard({ event: asPublicIdEvent(event) }),
|
|
4237
4317
|
isDigitalIdSelected: ({ event }) => isDigitalIdSelectedGuard({ event: asPublicIdEvent(event) }),
|
|
@@ -4254,7 +4334,6 @@ const idCaptureMachine = setup({
|
|
|
4254
4334
|
forceFinishAfterProcessing: forceFinishAfterProcessingGuard,
|
|
4255
4335
|
isBackModeInMultiSideFlow: isBackModeInMultiSideFlowGuard,
|
|
4256
4336
|
wasExpiredRedirected: wasExpiredRedirectedGuard,
|
|
4257
|
-
isManualUploadExhausted: ({ event }) => event.output?.result === "exhausted",
|
|
4258
4337
|
isDigitalUploadExhausted: ({ event }) => event.output?.result === "exhausted",
|
|
4259
4338
|
isDigitalUploadSuccessful: ({ event }) => event.output?.result === "success",
|
|
4260
4339
|
isDigitalIdRedirectCompleted: ({ event }) => event.output?.status === "COMPLETED",
|
|
@@ -4303,9 +4382,13 @@ const idCaptureMachine = setup({
|
|
|
4303
4382
|
},
|
|
4304
4383
|
context: ({ input, self }) => {
|
|
4305
4384
|
attachIdProtectedCaptureController(self, createIdProtectedCaptureController());
|
|
4385
|
+
const config = {
|
|
4386
|
+
...input.config,
|
|
4387
|
+
captureAttempts: input.config.captureAttempts ?? 1
|
|
4388
|
+
};
|
|
4306
4389
|
const currentMode = input.config.onlyBack ? "back" : !input.config.enableId && input.config.enablePassport ? "passport" : input.config.usSmartCapture ? "back" : "front";
|
|
4307
4390
|
return {
|
|
4308
|
-
config
|
|
4391
|
+
config,
|
|
4309
4392
|
captureFeedbackMode: input.captureFeedbackMode ?? "countdown",
|
|
4310
4393
|
captureWindowMs: input.captureWindowMs,
|
|
4311
4394
|
optimizingDwellMs: input.optimizingDwellMs,
|
|
@@ -4325,7 +4408,7 @@ const idCaptureMachine = setup({
|
|
|
4325
4408
|
barcodeFastPathAttempted: false,
|
|
4326
4409
|
barcodeFastPathCaptured: false,
|
|
4327
4410
|
recordingSession: void 0,
|
|
4328
|
-
attemptsRemaining:
|
|
4411
|
+
attemptsRemaining: config.captureAttempts,
|
|
4329
4412
|
expiredAttempts: 0,
|
|
4330
4413
|
expiredRedirected: false,
|
|
4331
4414
|
processingExpiredAttempts: 0,
|
|
@@ -4359,6 +4442,8 @@ const idCaptureMachine = setup({
|
|
|
4359
4442
|
disableIpify: getDisableIpify(),
|
|
4360
4443
|
deepsightInitAttempted: false,
|
|
4361
4444
|
availableDocumentTypes: getAvailableDocumentTypes(input.config, { credentialsAvailable: input.dependencies?.credentials?.isAvailable() ?? false }),
|
|
4445
|
+
digitalIdRedirectOptions: getAvailableDigitalIdRedirectOptions(input.config),
|
|
4446
|
+
selectedDigitalIdProviderId: void 0,
|
|
4362
4447
|
captureResolution: void 0,
|
|
4363
4448
|
cameraFallbackLevel: void 0,
|
|
4364
4449
|
usingBackCamera: void 0
|
|
@@ -4379,10 +4464,6 @@ const idCaptureMachine = setup({
|
|
|
4379
4464
|
guard: "hasNoDocumentTypesAvailable",
|
|
4380
4465
|
actions: [() => console.error(ID_CAPTURE_NO_DOCUMENT_TYPES_ERROR), assign({ error: () => ID_CAPTURE_NO_DOCUMENT_TYPES_ERROR })]
|
|
4381
4466
|
},
|
|
4382
|
-
{
|
|
4383
|
-
target: "manualIdUpload",
|
|
4384
|
-
guard: "hasOnlyManualUploadAvailable"
|
|
4385
|
-
},
|
|
4386
4467
|
{
|
|
4387
4468
|
target: "chooser",
|
|
4388
4469
|
guard: "hasShowDocumentChooser"
|
|
@@ -4413,11 +4494,6 @@ const idCaptureMachine = setup({
|
|
|
4413
4494
|
guard: "isDigitalIdUploadSelected",
|
|
4414
4495
|
actions: ["setSelectedDocument"]
|
|
4415
4496
|
},
|
|
4416
|
-
{
|
|
4417
|
-
target: "manualIdUpload",
|
|
4418
|
-
guard: "isManualIdUploadSelected",
|
|
4419
|
-
actions: ["setSelectedDocument"]
|
|
4420
|
-
},
|
|
4421
4497
|
{
|
|
4422
4498
|
target: "ageVerification",
|
|
4423
4499
|
guard: "hasAgeAssurance",
|
|
@@ -4494,6 +4570,14 @@ const idCaptureMachine = setup({
|
|
|
4494
4570
|
}]
|
|
4495
4571
|
},
|
|
4496
4572
|
on: {
|
|
4573
|
+
CONTINUE_TO_PERMISSION: [{
|
|
4574
|
+
target: "requestingMotionPermission",
|
|
4575
|
+
guard: "requiresMotionPermissionUserGesture",
|
|
4576
|
+
actions: "trackContinue"
|
|
4577
|
+
}, {
|
|
4578
|
+
target: "#idCapture.permissions",
|
|
4579
|
+
actions: "trackContinue"
|
|
4580
|
+
}],
|
|
4497
4581
|
NEXT_STEP: {
|
|
4498
4582
|
target: "#idCapture.capture",
|
|
4499
4583
|
actions: "trackContinue"
|
|
@@ -4506,6 +4590,14 @@ const idCaptureMachine = setup({
|
|
|
4506
4590
|
},
|
|
4507
4591
|
initializingCamera: {
|
|
4508
4592
|
type: "parallel",
|
|
4593
|
+
on: { CONTINUE_TO_PERMISSION: [{
|
|
4594
|
+
target: "requestingMotionPermission",
|
|
4595
|
+
guard: "requiresMotionPermissionUserGesture",
|
|
4596
|
+
actions: "trackContinue"
|
|
4597
|
+
}, {
|
|
4598
|
+
target: "#idCapture.permissions",
|
|
4599
|
+
actions: "trackContinue"
|
|
4600
|
+
}] },
|
|
4509
4601
|
states: {
|
|
4510
4602
|
cameraInit: {
|
|
4511
4603
|
initial: "initializingStream",
|
|
@@ -4547,6 +4639,14 @@ const idCaptureMachine = setup({
|
|
|
4547
4639
|
onDone: { target: "#idCapture.capture" }
|
|
4548
4640
|
},
|
|
4549
4641
|
ready: { on: {
|
|
4642
|
+
CONTINUE_TO_PERMISSION: [{
|
|
4643
|
+
target: "requestingMotionPermission",
|
|
4644
|
+
guard: "requiresMotionPermissionUserGesture",
|
|
4645
|
+
actions: "trackContinue"
|
|
4646
|
+
}, {
|
|
4647
|
+
target: "#idCapture.permissions",
|
|
4648
|
+
actions: "trackContinue"
|
|
4649
|
+
}],
|
|
4550
4650
|
NEXT_STEP: {
|
|
4551
4651
|
target: "waitingForPermission",
|
|
4552
4652
|
actions: "trackContinue"
|
|
@@ -4587,6 +4687,15 @@ const idCaptureMachine = setup({
|
|
|
4587
4687
|
actions: assign({ permissionResult: ({ event }) => event.output })
|
|
4588
4688
|
}
|
|
4589
4689
|
]
|
|
4690
|
+
} },
|
|
4691
|
+
requestingMotionPermission: { invoke: {
|
|
4692
|
+
id: "requestTutorialMotionPermission",
|
|
4693
|
+
src: "requestMotionPermission",
|
|
4694
|
+
onDone: [{
|
|
4695
|
+
target: "#idCapture.permissions.denied",
|
|
4696
|
+
guard: ({ event }) => event.output === "denied"
|
|
4697
|
+
}, { target: "#idCapture.permissions" }],
|
|
4698
|
+
onError: { target: "#idCapture.permissions.denied" }
|
|
4590
4699
|
} }
|
|
4591
4700
|
}
|
|
4592
4701
|
},
|
|
@@ -4642,6 +4751,7 @@ const idCaptureMachine = setup({
|
|
|
4642
4751
|
} },
|
|
4643
4752
|
motionOnly: { on: {
|
|
4644
4753
|
REQUEST_PERMISSION: "requesting",
|
|
4754
|
+
GO_TO_LEARN_MORE: "learnMore",
|
|
4645
4755
|
BACK: {
|
|
4646
4756
|
target: "#idCapture.tutorial.ready",
|
|
4647
4757
|
guard: "hasShowTutorial"
|
|
@@ -4755,6 +4865,7 @@ const idCaptureMachine = setup({
|
|
|
4755
4865
|
}],
|
|
4756
4866
|
entry: [assign({ detectionStatus: () => "detecting" })],
|
|
4757
4867
|
on: {
|
|
4868
|
+
OPEN_HELP: { target: "help" },
|
|
4758
4869
|
DETECTION_UPDATE: { actions: "setDetectionStatus" },
|
|
4759
4870
|
PROTECTED_AUTO_CAPTURE: { actions: ["storeProtectedAutoQuality", "requestProtectedAutoCommit"] },
|
|
4760
4871
|
PROTECTED_AUTO_COMMITTED_SIGNAL: {
|
|
@@ -4819,6 +4930,7 @@ const idCaptureMachine = setup({
|
|
|
4819
4930
|
initial: "searching",
|
|
4820
4931
|
states: {
|
|
4821
4932
|
searching: { on: {
|
|
4933
|
+
OPEN_HELP: { target: "#idCapture.capture.help" },
|
|
4822
4934
|
DETECTION_UPDATE: { actions: "setDetectionStatus" },
|
|
4823
4935
|
ID_SIDE_CHANGE: { actions: assign({ detectionStatus: ({ context, event }) => getDetectionStatusFromSideChange(context, event.side) }) },
|
|
4824
4936
|
BARCODE_DECODED: [{
|
|
@@ -4856,7 +4968,34 @@ const idCaptureMachine = setup({
|
|
|
4856
4968
|
}
|
|
4857
4969
|
}
|
|
4858
4970
|
},
|
|
4971
|
+
help: {
|
|
4972
|
+
entry: "pauseProtectedDetection",
|
|
4973
|
+
on: {
|
|
4974
|
+
CLOSE_HELP: [{
|
|
4975
|
+
guard: "hasManualCaptureTriggered",
|
|
4976
|
+
target: "manualCaptureWaiting",
|
|
4977
|
+
actions: "resumeProtectedDetection"
|
|
4978
|
+
}, {
|
|
4979
|
+
target: "choosingDetectionStrategy",
|
|
4980
|
+
actions: ["resetAutomaticCapture", "resumeProtectedDetection"]
|
|
4981
|
+
}],
|
|
4982
|
+
SWITCH_TO_MANUAL_CAPTURE: { actions: assign({
|
|
4983
|
+
manualCaptureTriggered: true,
|
|
4984
|
+
detectionStatus: "manualCapture"
|
|
4985
|
+
}) },
|
|
4986
|
+
SWITCH_TO_AUTO_CAPTURE: {
|
|
4987
|
+
guard: "hasManualCaptureTriggered",
|
|
4988
|
+
target: "releasingForRetry",
|
|
4989
|
+
actions: ["trackSwitchToAutoCapture", "resetAutomaticCapture"]
|
|
4990
|
+
}
|
|
4991
|
+
}
|
|
4992
|
+
},
|
|
4859
4993
|
manualCaptureWaiting: { on: {
|
|
4994
|
+
OPEN_HELP: { target: "help" },
|
|
4995
|
+
SWITCH_TO_AUTO_CAPTURE: {
|
|
4996
|
+
target: "releasingForRetry",
|
|
4997
|
+
actions: ["trackSwitchToAutoCapture", "resetAutomaticCapture"]
|
|
4998
|
+
},
|
|
4860
4999
|
MANUAL_CAPTURE: { actions: "requestProtectedManualCommit" },
|
|
4861
5000
|
PROTECTED_MANUAL_COMMITTED_SIGNAL: {
|
|
4862
5001
|
target: "capturingManual",
|
|
@@ -4962,7 +5101,7 @@ const idCaptureMachine = setup({
|
|
|
4962
5101
|
id: "captureOnlyDelivery",
|
|
4963
5102
|
src: "captureOnlyDelivery",
|
|
4964
5103
|
input: ({ context }) => {
|
|
4965
|
-
if (!
|
|
5104
|
+
if (!hasOnCaptureCallback(context.config)) return { mode: "protected" };
|
|
4966
5105
|
return { mode: "captureOnly" };
|
|
4967
5106
|
}
|
|
4968
5107
|
}],
|
|
@@ -5264,35 +5403,6 @@ const idCaptureMachine = setup({
|
|
|
5264
5403
|
actions: "resetContext"
|
|
5265
5404
|
} }
|
|
5266
5405
|
},
|
|
5267
|
-
manualIdUpload: {
|
|
5268
|
-
invoke: {
|
|
5269
|
-
id: "manualIdUpload",
|
|
5270
|
-
src: "manualUploadMachine",
|
|
5271
|
-
input: ({ context }) => ({
|
|
5272
|
-
isSecondId: context.config.isSecondId ?? false,
|
|
5273
|
-
onlyFront: context.config.onlyFront ?? false,
|
|
5274
|
-
onlyBack: context.config.onlyBack ?? false,
|
|
5275
|
-
captureAttempts: context.config.captureAttempts,
|
|
5276
|
-
extractIdFace: context.config.extractIdFace
|
|
5277
|
-
}),
|
|
5278
|
-
onSnapshot: { actions: () => {} },
|
|
5279
|
-
onDone: [{
|
|
5280
|
-
guard: "isManualUploadExhausted",
|
|
5281
|
-
target: "#idCapture.finished"
|
|
5282
|
-
}, { target: "#idCapture.processing" }],
|
|
5283
|
-
onError: {
|
|
5284
|
-
target: "#idCapture.error",
|
|
5285
|
-
actions: assign({ error: ({ event }) => String(event.error) })
|
|
5286
|
-
}
|
|
5287
|
-
},
|
|
5288
|
-
on: {
|
|
5289
|
-
QUIT: { target: "closed" },
|
|
5290
|
-
MANUAL_UPLOAD_TAB_CHANGED: { actions: sendTo("manualIdUpload", ({ event }) => event) },
|
|
5291
|
-
MANUAL_UPLOAD_FILE_SELECTED: { actions: sendTo("manualIdUpload", ({ event }) => event) },
|
|
5292
|
-
MANUAL_UPLOAD_CONTINUE: { actions: sendTo("manualIdUpload", ({ event }) => event) },
|
|
5293
|
-
MANUAL_UPLOAD_RESET: { actions: sendTo("manualIdUpload", ({ event }) => event) }
|
|
5294
|
-
}
|
|
5295
|
-
},
|
|
5296
5406
|
digitalIdUpload: {
|
|
5297
5407
|
invoke: {
|
|
5298
5408
|
id: "digitalIdUpload",
|
|
@@ -5351,28 +5461,38 @@ const idCaptureMachine = setup({
|
|
|
5351
5461
|
},
|
|
5352
5462
|
{
|
|
5353
5463
|
target: "chooser",
|
|
5354
|
-
guard: "hasShowDocumentChooser"
|
|
5464
|
+
guard: "hasShowDocumentChooser",
|
|
5465
|
+
actions: ["clearDigitalIdAttempt"]
|
|
5355
5466
|
},
|
|
5356
|
-
{
|
|
5467
|
+
{
|
|
5468
|
+
target: "loading",
|
|
5469
|
+
actions: ["clearDigitalIdAttempt"]
|
|
5470
|
+
}
|
|
5357
5471
|
],
|
|
5358
5472
|
onError: [{
|
|
5359
5473
|
target: "chooser",
|
|
5360
|
-
guard: "hasShowDocumentChooser"
|
|
5361
|
-
|
|
5474
|
+
guard: "hasShowDocumentChooser",
|
|
5475
|
+
actions: ["clearDigitalIdAttempt"]
|
|
5476
|
+
}, {
|
|
5477
|
+
target: "loading",
|
|
5478
|
+
actions: ["clearDigitalIdAttempt"]
|
|
5479
|
+
}]
|
|
5362
5480
|
},
|
|
5363
5481
|
on: { QUIT: { target: "closed" } }
|
|
5364
5482
|
},
|
|
5365
5483
|
digitalIdRedirect: {
|
|
5484
|
+
exit: "clearDigitalIdAttempt",
|
|
5366
5485
|
invoke: {
|
|
5367
5486
|
id: "digitalIdRedirect",
|
|
5368
5487
|
src: "digitalIdRedirectMachine",
|
|
5369
5488
|
input: ({ context }) => {
|
|
5370
|
-
const method = getDigitalIdRedirectMethod(context.config);
|
|
5371
5489
|
const resuming = context.digitalIdReturnParams !== void 0 && context.digitalIdResumeVerificationId !== void 0;
|
|
5372
5490
|
const routedProvider = context.digitalIdRoute?.kind === "trinsicRedirect" ? context.digitalIdRoute.providerId : void 0;
|
|
5491
|
+
const presetProvider = (resuming ? context.digitalIdResumeProviderId : void 0) ?? routedProvider ?? context.selectedDigitalIdProviderId;
|
|
5492
|
+
const method = presetProvider !== void 0 ? getDigitalIdRedirectMethod(context.config, presetProvider) : getDigitalIdRedirectMethod(context.config);
|
|
5373
5493
|
return {
|
|
5374
5494
|
config: {
|
|
5375
|
-
provider:
|
|
5495
|
+
provider: presetProvider ?? method?.provider,
|
|
5376
5496
|
returnUrl: context.config.digitalIdReturnUrl,
|
|
5377
5497
|
country: method?.country
|
|
5378
5498
|
},
|
|
@@ -5479,4 +5599,4 @@ function provideIdProtectedCaptureController(machine, controller) {
|
|
|
5479
5599
|
});
|
|
5480
5600
|
}
|
|
5481
5601
|
//#endregion
|
|
5482
|
-
export {
|
|
5602
|
+
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 };
|