@incodetech/core 2.3.2 → 2.4.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.txt +1243 -3
- package/dist/Actor-DpTj5PFb.d.ts +1 -0
- package/dist/{BaseWasmProvider-Dyi6dKp1.d.ts → BaseWasmProvider-BL9wIRnN.d.ts} +2 -2
- package/dist/{FaceDetectionProvider-DtmtCKa9.esm.js → FaceDetectionProvider-BjTer9h3.esm.js} +126 -10
- package/dist/HttpRequestError-Bh0pNGSC.esm.js +35 -0
- package/dist/{IIdCaptureCapability-RNiFhvXR.d.ts → IIdCaptureCapability-DBsv9-7M.d.ts} +2 -2
- package/dist/{IWasmUtilCapability-CNWRl7jr.d.ts → IWasmUtilCapability-CPX0RGdQ.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-DVmzJux5.d.ts} +2 -2
- package/dist/{safeStorage-BdU9_m2E.esm.js → WasmUtilProvider-CIdnE7Fx.esm.js} +95 -46
- package/dist/{addressSearch-DyHGgeX8.esm.js → addressSearch-BiYZjvp3.esm.js} +143 -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-BY36bS12.d.ts → antifraudManager-DbGCvlJs.d.ts} +2 -2
- package/dist/{antifraudManager-DNkw66oW.esm.js → antifraudManager-HL08jeDX.esm.js} +3 -3
- package/dist/{antifraudStateMachine-DBeq47D2.esm.js → antifraudStateMachine-DoJVzblM.esm.js} +3 -3
- package/dist/{apiError-CmGEmaGU.esm.js → apiError-DcSWedC6.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-CANv5-W5.d.ts} +2 -8
- package/dist/{authenticationManager-BFjSjtQ_.esm.js → authenticationManager-SaiAxqvS.esm.js} +6 -6
- package/dist/{authenticationStateMachine-Dfo34ZiI.esm.js → authenticationStateMachine-CHSxmV7z.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-CMg4SgL4.esm.js} +3 -3
- package/dist/{certificateIssuanceManager-DCgEidHz.d.ts → certificateIssuanceManager-Dr8A4Lgr.d.ts} +2 -3
- package/dist/{certificateIssuanceStateMachine-CxqS_nD-.esm.js → certificateIssuanceStateMachine-Cs64QmYH.esm.js} +4 -4
- package/dist/consent.d.ts +1 -1
- package/dist/consent.esm.js +2 -2
- package/dist/{consentManager-B6E1XJDw.esm.js → consentManager-CjrxY737.esm.js} +3 -3
- package/dist/{consentManager-2h_w6wFc.d.ts → consentManager-DgzWQpAR.d.ts} +6 -7
- package/dist/{consentStateMachine-DTSfdGiW.esm.js → consentStateMachine-BCj5Jb3g.esm.js} +3 -3
- package/dist/{createCameraCycleOwnership-DnwTl1ad.esm.js → createCameraCycleOwnership-kdlhkmmY.esm.js} +71 -65
- package/dist/{createFaceAvatar-BlcTYgJv.d.ts → createFaceAvatar-DXgmQmQy.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-BHnGRsto.esm.js} +4 -4
- 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-DNuZn9fn.d.ts → curpValidationManager-B-1EZbP_.d.ts} +3 -3
- package/dist/{curpValidationManager-DbIMYFcJ.esm.js → curpValidationManager-DBNIn8BF.esm.js} +15 -22
- package/dist/{curpValidationStateMachine-g5kMfuLj.esm.js → curpValidationStateMachine-DAxImy8p.esm.js} +4 -4
- 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-CzWZTkW-.esm.js → customFieldsManager-BV6UyLFV.esm.js} +4 -4
- package/dist/{customFieldsManager-8-W2KY4n.d.ts → customFieldsManager-CF-cO8ap.d.ts} +2 -2
- package/dist/{customWatchlistManager-DWTED5Ur.esm.js → customWatchlistManager-DML0UPzf.esm.js} +3 -3
- package/dist/{customWatchlistManager-PBWHr_oM.d.ts → customWatchlistManager-DolUswyR.d.ts} +2 -2
- package/dist/{customWatchlistStateMachine-DOQou6TW.esm.js → customWatchlistStateMachine-D9gI5uu7.esm.js} +3 -3
- package/dist/deepsightLoader-DvfAYnzg.esm.js +55 -0
- package/dist/{deepsightLoader-v-dLejS-.esm.js → deepsightService-DLGO9yv1.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-C9XUnYU6.esm.js} +17 -18
- package/dist/{documentCaptureManager-lEtCM320.d.ts → documentCaptureManager-DkyDtm3Y.d.ts} +11 -34
- package/dist/{documentCaptureStateMachine-D312sSIu.esm.js → documentCaptureStateMachine-BHDsCfhL.esm.js} +55 -58
- package/dist/dynamic-forms.d.ts +2 -2
- package/dist/dynamic-forms.esm.js +2 -2
- package/dist/{dynamicFormsManager-C-9Jhnd3.esm.js → dynamicFormsManager-5uIXobxi.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-DQmok084.esm.js} +4 -4
- package/dist/ekyb.d.ts +5 -5
- package/dist/ekyb.esm.js +3 -3
- package/dist/{ekybManager-BwRuGAwt.d.ts → ekybManager-BaZ_7CEu.d.ts} +4 -4
- package/dist/{ekybManager-DeoMcZEz.esm.js → ekybManager-CazShiQz.esm.js} +23 -27
- package/dist/{ekybStateMachine-D1IJ1Z72.esm.js → ekybStateMachine-hstiCNmW.esm.js} +338 -13
- package/dist/ekyc.d.ts +2 -2
- package/dist/ekyc.esm.js +3 -3
- package/dist/{ekycManager-BX2d46FY.esm.js → ekycManager-BdJRUsz0.esm.js} +29 -36
- package/dist/{ekycManager-DLzDuBzI.d.ts → ekycManager-DW-ynodd.d.ts} +3 -3
- package/dist/ekycStateMachine-x6Klot8g.esm.js +1444 -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-Bc8spG8p.esm.js} +10 -10
- 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-CtlKRRaR.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-5Neq3rE5.esm.js} +4 -4
- package/dist/{endpoints-B-3Q-LUw.esm.js → endpoints-DHzlkQNe.esm.js} +2 -0
- package/dist/{events-ijlbX_Wx.esm.js → events-CAgFE-k3.esm.js} +19 -7
- 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-jKQ2QtY-.d.ts} +11 -51
- package/dist/{faceCaptureManagerFactory-B6i9QcAk.esm.js → faceCaptureManagerFactory-uFm1AcaY.esm.js} +19 -54
- package/dist/{faceCaptureSetup-DU1mjRr6.esm.js → faceCaptureSetup-Cu2wabzo.esm.js} +99 -395
- package/dist/{faceMatchManager-Bmv0HzuY.esm.js → faceMatchManager-9Nj9aPci.esm.js} +3 -3
- package/dist/{faceMatchManager-BnvrZM2F.d.ts → faceMatchManager-DIgG-UFS.d.ts} +1 -2
- package/dist/{faceMatchStateMachine-mRIHQ3dA.esm.js → faceMatchStateMachine-B9ZUnlyU.esm.js} +6 -4
- package/dist/{feature-management-C8CuN0os.esm.js → feature-management-BTbYruNe.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-Dk38hXZP.esm.js} +35 -17
- 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-DmBkQfs0.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-xnn_SlJU.esm.js} +2 -2
- package/dist/{flowServices-CdsWsppG.esm.js → flowServices-DA64AEZC.esm.js} +11 -7
- package/dist/geolocation.d.ts +1 -1
- package/dist/geolocation.esm.js +2 -2
- package/dist/{geolocationManager-CGHBxtMb.esm.js → geolocationManager-CqNLY45e.esm.js} +6 -7
- package/dist/{geolocationManager-Cz744E5S.d.ts → geolocationManager-Dn24g1fl.d.ts} +2 -3
- package/dist/{geolocationStateMachine-CdEb1Gn0.esm.js → geolocationStateMachine-D-cQi7ar.esm.js} +4 -4
- 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-CP0SiOOe.esm.js} +3 -3
- package/dist/{governmentValidationStateMachine-CoaZOSTP.esm.js → governmentValidationStateMachine-C3YQ8yCZ.esm.js} +3 -3
- package/dist/home.d.ts +3 -26
- package/dist/home.esm.js +2 -2
- 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-CBg73RnV.esm.js} +8 -5
- package/dist/{idCaptureManager-BHwL2Z0V.d.ts → idCaptureManager-BY97SRCV.d.ts} +242 -98
- package/dist/{idCaptureManager-BNmVJQkd.esm.js → idCaptureManager-D4V8vXtY.esm.js} +276 -210
- package/dist/{idCaptureServices-dtDG2HXS.esm.js → idCaptureServices-DJ33k3-p.esm.js} +21 -39
- package/dist/{idCaptureStateMachine-BbiZD3uf.esm.js → idCaptureStateMachine-PJt0yzom.esm.js} +989 -872
- package/dist/{idOcrManager-CFlDwUvN.d.ts → idOcrManager-BTdHlJ9D.d.ts} +2 -3
- package/dist/{idOcrManager-ByWuQ4ej.esm.js → idOcrManager-DxoCesYP.esm.js} +3 -3
- package/dist/{idOcrStateMachine-Bt_abXQQ.esm.js → idOcrStateMachine-kPn7DB2I.esm.js} +3 -3
- package/dist/{idVerificationManager-BB4Pj_N6.d.ts → idVerificationManager-BJapZfpy.d.ts} +2 -3
- package/dist/{idVerificationManager-DT42c77H.esm.js → idVerificationManager-CDhRUU5n.esm.js} +3 -3
- package/dist/{idVerificationStateMachine-DbDVIh9t.esm.js → idVerificationStateMachine-0HTVVxse.esm.js} +3 -3
- package/dist/identity-reuse.d.ts +2 -2
- package/dist/identity-reuse.esm.js +2 -2
- package/dist/{identityReuseManager-yG3acUrQ.esm.js → identityReuseManager-BleUi6TK.esm.js} +26 -13
- package/dist/{identityReuseManager-BXEBBI3N.d.ts → identityReuseManager-ooAbp6Kc.d.ts} +164 -46
- package/dist/{identityReuseStateMachine-BhAkuIra.esm.js → identityReuseStateMachine-BrBUpfn5.esm.js} +89 -23
- package/dist/{index-CeaC32qI.d.ts → index-DfEuu-Ew.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-BW7V3vub.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-CX_Dyht7.esm.js} +3 -3
- package/dist/{mandatoryConsentManager-DFVm_i2B.d.ts → mandatoryConsentManager-TkX57U6f.d.ts} +3 -4
- package/dist/{mandatoryConsentStateMachine-DC5Mo6M1.esm.js → mandatoryConsentStateMachine-CoaSB7P7.esm.js} +3 -3
- package/dist/{multipartRecordingService-mwKFTlhR.esm.js → multipartRecordingService-DbeQpXdU.esm.js} +2 -2
- package/dist/{permissionGuards-D6TfVop2.esm.js → permissionGuards-Bf4LbHjC.esm.js} +1 -1
- package/dist/{permissionServices-EY3_Vx6c.esm.js → permissionServices-d2UW0r_L.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-IjhSv5XS.esm.js → phoneManager-BGBcpqsk.esm.js} +31 -22
- package/dist/{phoneManager-BBU8Lq0O.d.ts → phoneManager-BO-LTih5.d.ts} +16 -3
- package/dist/{phoneStateMachine-CXdXufKg.esm.js → phoneStateMachine-CEm2y7yG.esm.js} +39 -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-FLEWJtv8.esm.js → redirectToMobileManager-B1yQHFLu.esm.js} +4 -4
- package/dist/{redirectToMobileManager-BD2PvT5B.d.ts → redirectToMobileManager-CVsvpVbQ.d.ts} +2 -2
- package/dist/{redirectToMobileStateMachine-CSWWgUTO.esm.js → redirectToMobileStateMachine--Sr9NEVT.esm.js} +5 -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-vdxQMCmO.esm.js} +13 -12
- package/dist/safeStorage-UxDrnjwa.esm.js +35 -0
- package/dist/{sdkVersion-N1UiyFiY.esm.js → sdkVersion-F5YZbjip.esm.js} +1 -1
- package/dist/selfie.d.ts +4 -4
- package/dist/selfie.esm.js +12 -12
- package/dist/selfieErrorUtils-D-tsgEuX.esm.js +21 -0
- package/dist/{selfieManager-BSZG891S.d.ts → selfieManager-1J0IEyFq.d.ts} +2 -8
- package/dist/{selfieManager-AS6wfUvZ.esm.js → selfieManager-26pENXxw.esm.js} +6 -6
- package/dist/selfieStateMachine-BhfKsl3I.esm.js +41 -0
- package/dist/{session-BESZc05k.esm.js → session-Bu7djCsj.esm.js} +5 -5
- package/dist/session.d.ts +15 -3
- package/dist/session.esm.js +30 -5
- package/dist/sessionInitializer-jxbfCnE-.esm.js +974 -0
- package/dist/{setup-BuPbxpwF.esm.js → setup-C38QkrSP.esm.js} +232 -112
- package/dist/{setup-Cyko6cAn.d.ts → setup-lgkQ8dJW.d.ts} +20 -11
- 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-qqXyH93e.esm.js} +7 -11
- package/dist/{signatureStateMachine-ce_XMA3l.esm.js → signatureStateMachine-BkRSrkKp.esm.js} +3 -3
- 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-DmG_tkGk.esm.js} +1 -1
- 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-BWgRVGIT.esm.js} +893 -900
- 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-BGXxRwQM.d.ts} +6 -7
- package/dist/{types-BfgmV7s7.d.ts → types-BQA7lRDV.d.ts} +1 -1
- package/dist/{types-CxGdmzxa.d.ts → types-BvFmYX5c.d.ts} +1 -1
- package/dist/{types-Cx-1zo-i.d.ts → types-BvLo3U4u.d.ts} +1 -1
- package/dist/types-C71Zo6vl.d.ts +6 -0
- package/dist/{types-DEGVXwsk2.d.ts → types-CyPUIpzf.d.ts} +110 -62
- package/dist/{types-Bx-BWveD.d.ts → types-DTYr9pCB.d.ts} +1 -1
- package/dist/{types-BjSly8cp.d.ts → types-DUnFZ08M.d.ts} +1 -1
- package/dist/{types-ESdtnHtg.d.ts → types-zpO4fU6a.d.ts} +3 -4
- 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 +1386 -1344
- package/dist/{videoSelfieCameraWarmer-q9ZjvXu9.esm.js → videoSelfieCameraWarmer-C366RKqu.esm.js} +11 -11
- package/dist/{videoSelfieFlowModuleMachine-BUe2uACW.esm.js → videoSelfieFlowModuleMachine-BCFVHBQ1.esm.js} +1 -1
- package/dist/{videoSelfieStepDetector-ChYgFM15.d.ts → videoSelfieStepDetector-C5QHOvWb.d.ts} +4 -4
- package/dist/videoTrimByCopy-BFfAiNpv.esm.js +15901 -0
- package/dist/{warmup-Cis2p6O0.d.ts → warmup-BUPPRAA1.d.ts} +7 -0
- package/dist/{warmup-ChDwHSel.esm.js → warmup-DMtbyb2l.esm.js} +27 -9
- package/dist/wasm.d.ts +2 -2
- package/dist/wasm.esm.js +4 -4
- package/dist/{wasmDsFlagSync-DYrLUEII.esm.js → wasmDsFlagSync-BXCGqP48.esm.js} +1 -1
- package/dist/{wasmWebClient-B7baE-Wf.esm.js → wasmWebClient-kbYZ2sxw.esm.js} +259 -20
- 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-BvF4jK3S.esm.js} +7 -5
- package/dist/{watchlistForBusinessStateMachine-CJ-MvUre.esm.js → watchlistForBusinessStateMachine-121XK-Et.esm.js} +3 -3
- package/dist/{watchlistManager-CixcLNDT.esm.js → watchlistManager-CNWEOYSq.esm.js} +3 -3
- package/dist/{watchlistManager-DLXef90v.d.ts → watchlistManager-DJQOd8Pw.d.ts} +2 -2
- package/dist/{watchlistStateMachine-CBqk2w-h.esm.js → watchlistStateMachine-Dgfm42w2.esm.js} +3 -3
- package/dist/workflow.d.ts +34 -5
- package/dist/workflow.esm.js +64 -46
- 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/StateMachine-EDpYWy0i.d.ts +0 -6
- 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-PJt0yzom.esm.js}
RENAMED
|
@@ -1,31 +1,33 @@
|
|
|
1
|
-
import { c as trueSightHintTransition, l as trueSightLog,
|
|
2
|
-
import {
|
|
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";
|
|
1
|
+
import { c as trueSightHintTransition, l as trueSightLog, r as noteTrueSightCaptureActivity, v as isTrueSightTesting } from "./trueSightService-BWgRVGIT.esm.js";
|
|
2
|
+
import { t as WasmUtilProvider } from "./WasmUtilProvider-CIdnE7Fx.esm.js";
|
|
6
3
|
import { n as revokeObjectURL, t as getTimestamp } from "./IBrowserEnvironmentCapability-DEaRRk-R.esm.js";
|
|
4
|
+
import { n as eventModuleNames, o as createManagerInstrumentation, s as recordExperimentAssignmentOnce, v as addEvent } from "./events-CAgFE-k3.esm.js";
|
|
7
5
|
import { r as getToken, t as api } from "./api-Bx3gKW_y.esm.js";
|
|
8
|
-
import {
|
|
9
|
-
import { t as
|
|
10
|
-
import { t as
|
|
11
|
-
import { t as
|
|
6
|
+
import { l as isGoogleWalletSignedRequestsEnabled, u as BrowserStorageProvider } from "./setup-C38QkrSP.esm.js";
|
|
7
|
+
import { t as endpoints } from "./endpoints-DHzlkQNe.esm.js";
|
|
8
|
+
import { t as getDisableIpify } from "./sessionInitializer-jxbfCnE-.esm.js";
|
|
9
|
+
import { t as BrowserTimerProvider } from "./BrowserTimerProvider-BXhgNxLt.esm.js";
|
|
10
|
+
import { s as exposeExperimentOnce } from "./feature-management-BTbYruNe.esm.js";
|
|
11
|
+
import { t as addDeviceStats } from "./stats-DmG_tkGk.esm.js";
|
|
12
12
|
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-
|
|
13
|
+
import "./session-Bu7djCsj.esm.js";
|
|
14
|
+
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";
|
|
15
|
+
import { n as fromPromise, t as fromCallback } from "./xstate-actors.esm-8Gzepa_A.esm.js";
|
|
16
|
+
import { n as getUrlSearchParam, t as buildUrlWithSearchParams } from "./urlUtils-6jsE6rKp.esm.js";
|
|
17
17
|
import { r as getCameraReacquisitionConstraints } from "./camera-sIa9ceW2.esm.js";
|
|
18
|
-
import { n as invokeRequestPermissionActor, t as checkPermission } from "./permissionServices-
|
|
19
|
-
import {
|
|
18
|
+
import { i as requestMotionPermission, n as invokeRequestPermissionActor, o as requiresMotionPermissionUserGesture, t as checkPermission } from "./permissionServices-d2UW0r_L.esm.js";
|
|
19
|
+
import { a as flagIdManualReview, n as runProtectedAttempt, o as PROTECTED_CAPTURE_TARGET, r as cameraCycleProvider, t as createCameraCycleOwnership } from "./createCameraCycleOwnership-kdlhkmmY.esm.js";
|
|
20
20
|
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-
|
|
21
|
+
import { n as needsMotionPrimeOnlyFromPermission, r as resolveStoredPermissionResult, t as isReadyForCaptureFromPermission } from "./permissionGuards-Bf4LbHjC.esm.js";
|
|
22
|
+
import { o as StreamCanvasProcessingSession } from "./multipartRecordingService-DbeQpXdU.esm.js";
|
|
23
23
|
import { t as sleep } from "./ITimerCapability-DgdDzp8G.esm.js";
|
|
24
24
|
import { t as getBrowser } from "./getBrowser-Cbe1C4Tn.esm.js";
|
|
25
|
+
import { a as isBackCameraLabel } from "./backCameraStream-CMvXj4X4.esm.js";
|
|
25
26
|
import { n as getWindowDimensions } from "./getDeviceClass-CeBiEayS.esm.js";
|
|
26
|
-
import { n as
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
27
|
+
import { n as frameSources, r as runVirtualCameraCheck } from "./deepsightService-DLGO9yv1.esm.js";
|
|
28
|
+
import { t as getDeviceClass } from "./getDeviceClass-bsWdEDxP.esm.js";
|
|
29
|
+
import { n as DEFAULT_ID_CAPTURE_THRESHOLDS, r as IdCaptureProvider } from "./idCaptureDefaults-CBg73RnV.esm.js";
|
|
30
|
+
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-DJ33k3-p.esm.js";
|
|
29
31
|
import { t as StreamCanvasCapture } from "./StreamCanvasCapture-C9jtgBdT.esm.js";
|
|
30
32
|
//#region src/modules/id/digitalUpload/digitalUploadErrors.ts
|
|
31
33
|
const TERMINAL_FAIL_REASONS = /* @__PURE__ */ new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
|
|
@@ -89,7 +91,7 @@ const uploadDigitalIdActor = fromPromise(async ({ input, signal }) => {
|
|
|
89
91
|
extractIdFace: input.extractIdFace
|
|
90
92
|
});
|
|
91
93
|
});
|
|
92
|
-
const getUploadResponseFromEvent
|
|
94
|
+
const getUploadResponseFromEvent = (event) => {
|
|
93
95
|
if (!("output" in event)) return;
|
|
94
96
|
return event.output;
|
|
95
97
|
};
|
|
@@ -153,10 +155,10 @@ const digitalUploadMachine = setup({
|
|
|
153
155
|
isSelectedFileTooLarge: ({ event }) => event.type === "FILE_PICKED" && event.file.size > 5242880,
|
|
154
156
|
isSelectedFileMimeInvalid: ({ event }) => event.type === "FILE_PICKED" && !DIGITAL_UPLOAD_ALLOWED_MIME_TYPES.includes(event.file.type),
|
|
155
157
|
hasSelectedFile: ({ context }) => context.file !== null,
|
|
156
|
-
responseHasFailReason: ({ event }) => mapDigitalIdFailReason(getUploadResponseFromEvent
|
|
158
|
+
responseHasFailReason: ({ event }) => mapDigitalIdFailReason(getUploadResponseFromEvent(event)) !== null,
|
|
157
159
|
hasAttemptsRemaining: ({ context }) => context.attemptsRemaining > 0,
|
|
158
160
|
isTerminalFailReason: ({ event }) => {
|
|
159
|
-
return isTerminalDigitalIdFailReason(getUploadResponseFromEvent
|
|
161
|
+
return isTerminalDigitalIdFailReason(getUploadResponseFromEvent(event));
|
|
160
162
|
},
|
|
161
163
|
isCurrentFailReasonTerminal: ({ context }) => {
|
|
162
164
|
const terminalReasons = /* @__PURE__ */ new Set(["DIGITAL_ID_REQUESTED_BUT_OTHER_PROVIDED", "ID_TYPE_UNACCEPTABLE"]);
|
|
@@ -316,14 +318,39 @@ const digitalUploadMachine = setup({
|
|
|
316
318
|
//#region src/modules/id/deviceWallet/deviceWalletServices.ts
|
|
317
319
|
/** Both wallet endpoint families are versioned via header, not path. */
|
|
318
320
|
const API_VERSION_HEADERS = { "api-version": "1.0" };
|
|
321
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
319
322
|
/**
|
|
320
|
-
*
|
|
321
|
-
*
|
|
323
|
+
* Turns the Google request payload into DC API request options without ever
|
|
324
|
+
* touching the payload itself — a signed request's JWS is covered by its
|
|
325
|
+
* signature, so any edit makes the wallet reject it. The backend decides the
|
|
326
|
+
* protocol; the SDK never derives it.
|
|
327
|
+
*
|
|
328
|
+
* - `{ requests: [...] }` — full DC API envelope (signed-capable backend):
|
|
329
|
+
* passed through as-is.
|
|
330
|
+
* - `{ protocol, data }` — an already-enveloped single request: not re-wrapped,
|
|
331
|
+
* only placed in the `requests` array (defensive, for rollout shape drift).
|
|
332
|
+
* - anything else — legacy bare unsigned OIDC4VP/DCQL object: wrapped with
|
|
333
|
+
* `openid4vp-v1-unsigned`.
|
|
334
|
+
*/
|
|
335
|
+
function toGoogleRequestOptions(payload) {
|
|
336
|
+
if (isRecord(payload) && Array.isArray(payload.requests)) return payload;
|
|
337
|
+
if (isRecord(payload) && typeof payload.protocol === "string") return { requests: [payload] };
|
|
338
|
+
return { requests: [{
|
|
339
|
+
protocol: "openid4vp-v1-unsigned",
|
|
340
|
+
data: payload
|
|
341
|
+
}] };
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Fetches the wallet request payload for the platform as Digital Credentials
|
|
345
|
+
* API request options.
|
|
322
346
|
*
|
|
323
347
|
* Apple: POST with an empty body → `{ deviceRequest, encryptionInfo }`,
|
|
324
348
|
* presented with protocol `org-iso-mdoc`.
|
|
325
|
-
* Google: GET → the
|
|
326
|
-
*
|
|
349
|
+
* Google: GET with `signedSupported=true` → the backend-built DC API envelope
|
|
350
|
+
* (signed or unsigned, backend's choice), passed through verbatim — see
|
|
351
|
+
* {@link toGoogleRequestOptions}. With `setup({ deviceWallet: {
|
|
352
|
+
* googleSignedRequests: false } })` the SDK sends `signedSupported=false` and
|
|
353
|
+
* the backend answers with the legacy bare unsigned payload.
|
|
327
354
|
*/
|
|
328
355
|
async function requestWalletData(platform, signal) {
|
|
329
356
|
if (platform === "ios") {
|
|
@@ -333,23 +360,21 @@ async function requestWalletData(platform, signal) {
|
|
|
333
360
|
});
|
|
334
361
|
if (!res.ok) throw new Error(`POST ${endpoints.deviceWalletAppleRequest} failed: ${res.status}`);
|
|
335
362
|
const data = res.data;
|
|
336
|
-
return {
|
|
363
|
+
return { requests: [{
|
|
337
364
|
protocol: "org-iso-mdoc",
|
|
338
365
|
data: {
|
|
339
366
|
deviceRequest: data.deviceRequest,
|
|
340
367
|
encryptionInfo: data.encryptionInfo
|
|
341
368
|
}
|
|
342
|
-
};
|
|
369
|
+
}] };
|
|
343
370
|
}
|
|
344
371
|
const res = await api.get(endpoints.deviceWalletGoogleRequest, {
|
|
345
372
|
headers: API_VERSION_HEADERS,
|
|
373
|
+
query: { signedSupported: isGoogleWalletSignedRequestsEnabled() },
|
|
346
374
|
signal
|
|
347
375
|
});
|
|
348
376
|
if (!res.ok) throw new Error(`GET ${endpoints.deviceWalletGoogleRequest} failed: ${res.status}`);
|
|
349
|
-
return
|
|
350
|
-
protocol: "openid4vp-v1-unsigned",
|
|
351
|
-
data: res.data
|
|
352
|
-
};
|
|
377
|
+
return toGoogleRequestOptions(res.data);
|
|
353
378
|
}
|
|
354
379
|
/**
|
|
355
380
|
* Forwards the opaque wallet response for backend decryption. The body key
|
|
@@ -529,408 +554,221 @@ function resolveWalletPlatform(provider) {
|
|
|
529
554
|
return isIOS() || isMacOsSafari() || isIPad() ? "ios" : "android";
|
|
530
555
|
}
|
|
531
556
|
//#endregion
|
|
532
|
-
//#region src/modules/id/
|
|
557
|
+
//#region src/modules/id/deviceWallet/instrumentation.ts
|
|
533
558
|
/**
|
|
534
|
-
*
|
|
535
|
-
*
|
|
559
|
+
* Maps a device-wallet child-machine snapshot to a tracked screen name.
|
|
560
|
+
* Family is `deviceWallet.*` — emitted cross-family under the parent
|
|
561
|
+
* `idCapture` module token, same as `mapDigitalIdScreenName`. See
|
|
562
|
+
* `docs/patterns/INSTRUMENTATION.md`.
|
|
536
563
|
*/
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
564
|
+
function mapDeviceWalletScreenName(value, failReason) {
|
|
565
|
+
if (value === "presenting") return "deviceWallet.wallet.default";
|
|
566
|
+
if (value === "failed") {
|
|
567
|
+
if (failReason === "NO_CREDENTIAL") return "deviceWallet.error.nocredential";
|
|
568
|
+
if (failReason === "UNSUPPORTED_PLATFORM") return "deviceWallet.error.unsupported";
|
|
569
|
+
return "deviceWallet.error.default";
|
|
570
|
+
}
|
|
571
|
+
return "deviceWallet.loading.default";
|
|
572
|
+
}
|
|
573
|
+
//#endregion
|
|
574
|
+
//#region ../infra/src/providers/browser/BrowserDigitalCredentialsProvider.ts
|
|
575
|
+
var BrowserDigitalCredentialsProvider = class {
|
|
576
|
+
isAvailable() {
|
|
577
|
+
return typeof navigator !== "undefined" && typeof navigator.credentials?.get === "function" && typeof globalThis.DigitalCredential !== "undefined";
|
|
578
|
+
}
|
|
579
|
+
async get(request, options) {
|
|
580
|
+
return { response: (await navigator.credentials.get({
|
|
581
|
+
mediation: "required",
|
|
582
|
+
signal: options?.signal,
|
|
583
|
+
digital: request
|
|
584
|
+
}))?.data?.response };
|
|
585
|
+
}
|
|
545
586
|
};
|
|
587
|
+
//#endregion
|
|
588
|
+
//#region src/modules/id/deviceWallet/deviceWalletActor.ts
|
|
546
589
|
/**
|
|
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".
|
|
590
|
+
* Starts a device-wallet actor for headless use. The ID-Capture parent invokes
|
|
591
|
+
* `deviceWalletMachine` itself (and resolves the platform through the
|
|
592
|
+
* digital-ID funnel); this factory is the standalone entry point for
|
|
593
|
+
* integrators driving the wallet handshake on their own.
|
|
562
594
|
*/
|
|
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;
|
|
595
|
+
function createDeviceWalletActor(options = {}) {
|
|
596
|
+
return createActor(deviceWalletMachine, { input: {
|
|
597
|
+
platform: resolveWalletPlatform(options.provider),
|
|
598
|
+
credentials: options.credentials ?? new BrowserDigitalCredentialsProvider(),
|
|
599
|
+
services: options.services
|
|
600
|
+
} }).start();
|
|
574
601
|
}
|
|
575
602
|
//#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
|
-
|
|
603
|
+
//#region src/modules/id/deviceWallet/deviceWalletManager.ts
|
|
604
|
+
/**
|
|
605
|
+
* Absolute tracked-screen name for a device-wallet snapshot. Emitted verbatim
|
|
606
|
+
* on `event.screen` under the parent `idCapture` module token — the wallet is
|
|
607
|
+
* an ID-Capture sub-flow, so it does not own an analytics module of its own
|
|
608
|
+
* (see `docs/patterns/INSTRUMENTATION.md`).
|
|
609
|
+
*/
|
|
610
|
+
function getDeviceWalletScreenName(snapshot) {
|
|
611
|
+
return mapDeviceWalletScreenName(snapshot.value, snapshot.context?.failReason ?? null);
|
|
612
|
+
}
|
|
613
|
+
function mapState(snapshot) {
|
|
614
|
+
const typedSnapshot = snapshot;
|
|
615
|
+
const { context } = typedSnapshot;
|
|
616
|
+
const { platform } = context;
|
|
617
|
+
if (typedSnapshot.matches("presenting")) return {
|
|
618
|
+
status: "presenting",
|
|
619
|
+
platform
|
|
620
|
+
};
|
|
621
|
+
if (typedSnapshot.matches("decrypting")) return {
|
|
622
|
+
status: "decrypting",
|
|
623
|
+
platform
|
|
624
|
+
};
|
|
625
|
+
if (typedSnapshot.matches("finished") && context.response) return {
|
|
626
|
+
status: "finished",
|
|
627
|
+
platform,
|
|
628
|
+
decision: context.response.decision,
|
|
629
|
+
response: context.response
|
|
630
|
+
};
|
|
631
|
+
if (typedSnapshot.matches("failed")) return {
|
|
632
|
+
status: "failed",
|
|
633
|
+
platform,
|
|
634
|
+
reason: context.failReason ?? "WALLET_ERROR"
|
|
635
|
+
};
|
|
636
|
+
if (typedSnapshot.matches("closed")) return {
|
|
637
|
+
status: "closed",
|
|
638
|
+
platform
|
|
639
|
+
};
|
|
603
640
|
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
|
-
})
|
|
641
|
+
status: "requesting",
|
|
642
|
+
platform
|
|
614
643
|
};
|
|
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" }
|
|
644
|
+
}
|
|
645
|
+
function createApi({ actor, trackElementClicked }) {
|
|
646
|
+
return {
|
|
647
|
+
/** Restarts the handshake after a failure. Needs a fresh user gesture. */
|
|
648
|
+
retry() {
|
|
649
|
+
trackElementClicked?.("retry");
|
|
650
|
+
actor.send({ type: "RETRY" });
|
|
927
651
|
},
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
652
|
+
/**
|
|
653
|
+
* Abandons the wallet path from a failure and moves the manager to
|
|
654
|
+
* `closed`, so the consumer can fall back to a camera ID capture.
|
|
655
|
+
*/
|
|
656
|
+
useAnotherMethod() {
|
|
657
|
+
trackElementClicked?.("useAnotherMethod");
|
|
658
|
+
actor.send({ type: "USE_ANOTHER_METHOD" });
|
|
931
659
|
}
|
|
932
|
-
}
|
|
933
|
-
}
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Creates a headless device-wallet (mDL) manager — the V2 equivalent of V1's
|
|
664
|
+
* `renderWallet`, with the intermediate states observable.
|
|
665
|
+
*
|
|
666
|
+
* Runs the Apple Wallet (web) / Google Wallet handshake with zero Incode UI,
|
|
667
|
+
* so integrators trigger it from their own button and render their own UX.
|
|
668
|
+
* Call it from a user gesture: iOS Safari requires transient user activation
|
|
669
|
+
* for `navigator.credentials.get()`.
|
|
670
|
+
*
|
|
671
|
+
* Requires an initialized session (`setup({ apiURL, token })`) — the request
|
|
672
|
+
* and decrypt calls are session-scoped.
|
|
673
|
+
*
|
|
674
|
+
* @example
|
|
675
|
+
* ```typescript
|
|
676
|
+
* import { setup } from '@incodetech/core';
|
|
677
|
+
* import { createDeviceWalletManager } from '@incodetech/core/id';
|
|
678
|
+
*
|
|
679
|
+
* setup({ apiURL, token });
|
|
680
|
+
*
|
|
681
|
+
* button.addEventListener('click', () => {
|
|
682
|
+
* const manager = createDeviceWalletManager();
|
|
683
|
+
* manager.subscribe((state) => {
|
|
684
|
+
* if (state.status === 'finished') manager.stop();
|
|
685
|
+
* if (state.status === 'failed') console.error(state.reason);
|
|
686
|
+
* });
|
|
687
|
+
* });
|
|
688
|
+
* ```
|
|
689
|
+
*/
|
|
690
|
+
function createDeviceWalletManager(options = {}) {
|
|
691
|
+
return createDeviceWalletManagerFromActor(createDeviceWalletActor(options));
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Creates a device-wallet manager from a pre-built actor. Use this when
|
|
695
|
+
* overriding the machine via `.provide()` for custom backends or tests.
|
|
696
|
+
*/
|
|
697
|
+
function createDeviceWalletManagerFromActor(actor) {
|
|
698
|
+
return createManager({
|
|
699
|
+
actor,
|
|
700
|
+
mapState,
|
|
701
|
+
createApi,
|
|
702
|
+
instrumentation: createManagerInstrumentation(eventModuleNames.idCapture, { getEventScreenName: getDeviceWalletScreenName })
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
//#endregion
|
|
706
|
+
//#region src/modules/id/deviceWallet/renderWallet.ts
|
|
707
|
+
const FAIL_MESSAGES = {
|
|
708
|
+
UNSUPPORTED_PLATFORM: "Device wallet is not supported on this platform/browser",
|
|
709
|
+
NO_CREDENTIAL: "The wallet returned no digital ID credential",
|
|
710
|
+
WALLET_ERROR: "Device wallet request failed"
|
|
711
|
+
};
|
|
712
|
+
/**
|
|
713
|
+
* Headless device-wallet (mDL) API — the V1 `renderWallet` shape, ported.
|
|
714
|
+
*
|
|
715
|
+
* Runs the Apple Wallet (web) / Google Wallet handshake with zero Incode UI,
|
|
716
|
+
* so integrators trigger it from their own button and render their own UX.
|
|
717
|
+
* Resolves once the handshake settles; the outcome arrives through
|
|
718
|
+
* `onSuccess` / `onError` exactly as in V1.
|
|
719
|
+
*
|
|
720
|
+
* MUST be called from a user gesture (e.g. a click handler) — iOS/Safari
|
|
721
|
+
* requires transient user activation for `navigator.credentials.get()` to
|
|
722
|
+
* present the wallet sheet.
|
|
723
|
+
*
|
|
724
|
+
* Requires an initialized session (`setup({ apiURL, token })`). The verified
|
|
725
|
+
* attributes are NOT returned here: they land in the session and are read back
|
|
726
|
+
* through the standard OCR / score APIs. `onSuccess` receives the submission
|
|
727
|
+
* decision/status.
|
|
728
|
+
*
|
|
729
|
+
* Prefer {@link createDeviceWalletManager} for new integrations — it exposes
|
|
730
|
+
* the intermediate `requesting` / `presenting` / `decrypting` states (and a
|
|
731
|
+
* `retry()`), which this one-shot wrapper collapses.
|
|
732
|
+
*
|
|
733
|
+
* @example
|
|
734
|
+
* ```typescript
|
|
735
|
+
* button.addEventListener('click', () => {
|
|
736
|
+
* void renderWallet({
|
|
737
|
+
* onSuccess: (result) => console.log(result.decision),
|
|
738
|
+
* onError: (error) => console.error(error.code, error.message),
|
|
739
|
+
* });
|
|
740
|
+
* });
|
|
741
|
+
* ```
|
|
742
|
+
*/
|
|
743
|
+
function renderWallet({ onSuccess, onError, ...actorOptions }) {
|
|
744
|
+
return new Promise((resolve) => {
|
|
745
|
+
const manager = createDeviceWalletManager(actorOptions);
|
|
746
|
+
const subscription = {};
|
|
747
|
+
let settled = false;
|
|
748
|
+
const settle = (state) => {
|
|
749
|
+
if (state.status === "requesting" || state.status === "presenting" || state.status === "decrypting") return false;
|
|
750
|
+
settled = true;
|
|
751
|
+
subscription.unsubscribe?.();
|
|
752
|
+
manager.stop();
|
|
753
|
+
if (state.status === "finished") onSuccess(state.response);
|
|
754
|
+
else if (state.status === "failed") onError({
|
|
755
|
+
code: state.reason,
|
|
756
|
+
message: FAIL_MESSAGES[state.reason]
|
|
757
|
+
});
|
|
758
|
+
else onError({
|
|
759
|
+
code: "WALLET_ERROR",
|
|
760
|
+
message: FAIL_MESSAGES.WALLET_ERROR
|
|
761
|
+
});
|
|
762
|
+
resolve();
|
|
763
|
+
return true;
|
|
764
|
+
};
|
|
765
|
+
if (settle(manager.getState())) return;
|
|
766
|
+
subscription.unsubscribe = manager.subscribe((state) => {
|
|
767
|
+
if (settled) return;
|
|
768
|
+
settle(state);
|
|
769
|
+
});
|
|
770
|
+
});
|
|
771
|
+
}
|
|
934
772
|
//#endregion
|
|
935
773
|
//#region src/modules/id/idCaptureGuards.ts
|
|
936
774
|
function getPermissionOutput(event) {
|
|
@@ -941,7 +779,7 @@ function getPermissionOutput(event) {
|
|
|
941
779
|
}
|
|
942
780
|
const hasShowTutorialGuard = ({ context }) => context.config.showTutorial;
|
|
943
781
|
const hasAgeAssuranceGuard = ({ context }) => context.config.ageAssurance === true;
|
|
944
|
-
const hasShowDocumentChooserGuard = ({ context }) =>
|
|
782
|
+
const hasShowDocumentChooserGuard = ({ context }) => !context.config.onlyBack && (context.config.showDocumentChooserScreen ?? false);
|
|
945
783
|
const isPermissionGrantedGuard = ({ event }) => {
|
|
946
784
|
return getPermissionOutput(event) === "granted";
|
|
947
785
|
};
|
|
@@ -959,6 +797,7 @@ const isPermissionDeniedErrorGuard = ({ event }) => {
|
|
|
959
797
|
return false;
|
|
960
798
|
};
|
|
961
799
|
const isPermissionBlockedGuard = ({ context }) => context.permissionResult === "denied" || context.permissionResult === "refresh";
|
|
800
|
+
const requiresMotionPermissionUserGestureGuard = ({ context }) => requiresMotionPermissionUserGesture(context.config.ds);
|
|
962
801
|
const hasAttemptsRemainingGuard = ({ context }) => context.attemptsRemaining > 0;
|
|
963
802
|
const hasCapturedImageGuard = ({ context }) => {
|
|
964
803
|
return context.provider?.getCapturedCanvas() !== null;
|
|
@@ -994,11 +833,9 @@ const isFrontModeGuard = ({ context }) => context.currentMode === "front" || con
|
|
|
994
833
|
* server answer exists, and
|
|
995
834
|
* 2. where you do, still self-correct once the answer arrives.
|
|
996
835
|
*
|
|
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.
|
|
836
|
+
* The captureOnly machine qualifies under (1) because it has no upload and no
|
|
837
|
+
* server answer. This guard is not on that path, so the answer is already in
|
|
838
|
+
* hand by the time it runs.
|
|
1002
839
|
*/
|
|
1003
840
|
const shouldContinueToBackGuard = ({ context }) => {
|
|
1004
841
|
if (context.currentMode !== "front" && context.currentMode !== "passport") return false;
|
|
@@ -1038,10 +875,8 @@ const supportsOptimizingStatusGuard = ({ context }) => context.config.supportsOp
|
|
|
1038
875
|
const isDeepsightEnabledGuard = ({ context }) => context.dependencies !== void 0;
|
|
1039
876
|
const isDeepsightReadyGuard = ({ context }) => context.deepsightService !== void 0;
|
|
1040
877
|
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
878
|
/** No capture option is enabled — the ID module is misconfigured. */
|
|
1043
879
|
const hasNoDocumentTypesAvailableGuard = ({ context }) => context.availableDocumentTypes.length === 0;
|
|
1044
|
-
const isManualIdUploadSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "manualIdUpload";
|
|
1045
880
|
const isDigitalIdUploadSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "digitalIdUpload";
|
|
1046
881
|
const isDigitalIdRedirectSelectedGuard = ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "digitalIdRedirect";
|
|
1047
882
|
/** The Digital ID (device wallet) chooser tile was picked. */
|
|
@@ -1110,239 +945,27 @@ const forceFinishAfterProcessingGuard = ({ context }) => context.forceFinishAfte
|
|
|
1110
945
|
* the dashboard-configurable `config.captureAttempts`, unlike the per-upload
|
|
1111
946
|
* (camera) same-side expired path, which uses the fixed
|
|
1112
947
|
* `MAX_EXPIRED_FIRST_SIDE_ATTEMPTS` (decoupled for V1 parity — see ENG-46592).
|
|
1113
|
-
* The two expired caps are therefore different by design.
|
|
1114
|
-
*/
|
|
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
|
|
948
|
+
* The two expired caps are therefore different by design.
|
|
1283
949
|
*/
|
|
1284
|
-
|
|
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
|
-
}
|
|
950
|
+
const isProcessingExpiredExhaustedGuard = ({ context }) => context.processingExpiredAttempts + 1 >= context.config.captureAttempts;
|
|
1296
951
|
/**
|
|
1297
|
-
*
|
|
1298
|
-
*
|
|
952
|
+
* True when capturing the back side of a two-sided (front+back) ID flow.
|
|
953
|
+
* Used to redirect an expired-back capture to front rather than retrying
|
|
954
|
+
* the same back side (Figma Story #2.1).
|
|
955
|
+
* Excludes onlyBack and usSmartCapture — those are single-side back flows
|
|
956
|
+
* with no front to redirect to.
|
|
1299
957
|
*/
|
|
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
|
-
}
|
|
958
|
+
const isBackModeInMultiSideFlowGuard = ({ context }) => context.currentMode === "back" && !context.config.onlyBack && !context.config.usSmartCapture;
|
|
1316
959
|
/**
|
|
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.
|
|
960
|
+
* True once the user has already been redirected from an expired second-side
|
|
961
|
+
* (back) capture to the first side (front) for their one extra attempt
|
|
962
|
+
* (V1's `expiredRedirected`). Used to make the expired-back→front redirect a
|
|
963
|
+
* one-shot: any subsequent expired upload routes to `expiredExhausted` instead
|
|
964
|
+
* of redirecting again, so total captures stay within the backend's
|
|
965
|
+
* max-attempts/OCR cap (ENG-46592 / re-respects ENG-45666).
|
|
1337
966
|
*/
|
|
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
|
-
}
|
|
967
|
+
const wasExpiredRedirectedGuard = ({ context }) => context.expiredRedirected === true;
|
|
968
|
+
const hasManualCaptureTriggeredGuard = ({ context }) => context.manualCaptureTriggered;
|
|
1346
969
|
//#endregion
|
|
1347
970
|
//#region src/modules/id/idDetectionNotificationController.ts
|
|
1348
971
|
const NOTIFICATION_DURATION_MS = 500;
|
|
@@ -1418,9 +1041,26 @@ async function requestIdCapturePermission(input) {
|
|
|
1418
1041
|
cameraFallbackLevel: fallbackLevel
|
|
1419
1042
|
};
|
|
1420
1043
|
}
|
|
1044
|
+
/**
|
|
1045
|
+
* Resolves and primes Deepsight motion without touching camera permission.
|
|
1046
|
+
* IDC-03 invokes this directly from the tutorial CTA's event macrostep so
|
|
1047
|
+
* iOS keeps the transient user activation required by DeviceMotion.
|
|
1048
|
+
*/
|
|
1049
|
+
async function requestIdCaptureMotionPermission() {
|
|
1050
|
+
const result = await requestMotionPermission();
|
|
1051
|
+
return result === "not-required" ? "granted" : result;
|
|
1052
|
+
}
|
|
1421
1053
|
const requestPermissionActor = fromPromise(async ({ input }) => {
|
|
1422
1054
|
return requestIdCapturePermission(input);
|
|
1423
1055
|
});
|
|
1056
|
+
/**
|
|
1057
|
+
* Takes no `AbortSignal` on purpose: the work it awaits is the OS-owned
|
|
1058
|
+
* `DeviceMotionEvent.requestPermission()` prompt, which exposes no
|
|
1059
|
+
* cancellation. XState still discards the settled result if the state is
|
|
1060
|
+
* left, and `primeWasmMotionSensor` is idempotent, so an abandoned request
|
|
1061
|
+
* cannot mis-drive the machine.
|
|
1062
|
+
*/
|
|
1063
|
+
const requestMotionPermissionActor = fromPromise(() => requestIdCaptureMotionPermission());
|
|
1424
1064
|
fromPromise(async ({ input }) => {
|
|
1425
1065
|
return initializeIdCapture(input);
|
|
1426
1066
|
});
|
|
@@ -1781,7 +1421,7 @@ fromPromise(async ({ input }) => {
|
|
|
1781
1421
|
});
|
|
1782
1422
|
fromPromise(async ({ input }) => {
|
|
1783
1423
|
if (!input.dependencies) return;
|
|
1784
|
-
const { loadDeepsightSession } = await import("./deepsightLoader-
|
|
1424
|
+
const { loadDeepsightSession } = await import("./deepsightLoader-DvfAYnzg.esm.js");
|
|
1785
1425
|
return loadDeepsightSession({
|
|
1786
1426
|
ds: input.ds,
|
|
1787
1427
|
storage: input.dependencies.storage,
|
|
@@ -2224,7 +1864,7 @@ function cleanup(service) {
|
|
|
2224
1864
|
service.cleanup();
|
|
2225
1865
|
} catch {}
|
|
2226
1866
|
}
|
|
2227
|
-
function createIdMetadataPreparationCoordinator(load = async (input) => (await import("./deepsightLoader-
|
|
1867
|
+
function createIdMetadataPreparationCoordinator(load = async (input) => (await import("./deepsightLoader-DvfAYnzg.esm.js")).loadDeepsightSession(input)) {
|
|
2228
1868
|
let disposed = false;
|
|
2229
1869
|
let preparation;
|
|
2230
1870
|
let service;
|
|
@@ -2257,6 +1897,46 @@ function createIdMetadataPreparationCoordinator(load = async (input) => (await i
|
|
|
2257
1897
|
};
|
|
2258
1898
|
}
|
|
2259
1899
|
//#endregion
|
|
1900
|
+
//#region src/modules/id/idCaptureOnlyConfig.ts
|
|
1901
|
+
/**
|
|
1902
|
+
* The `IdCaptureConfig` keys the captureOnly flow supports.
|
|
1903
|
+
*/
|
|
1904
|
+
const ID_CAPTURE_ONLY_CONFIG_KEYS = [
|
|
1905
|
+
"showTutorial",
|
|
1906
|
+
"captureAttempts",
|
|
1907
|
+
"autoCaptureTimeout",
|
|
1908
|
+
"deviceIdleTimeout",
|
|
1909
|
+
"enableId",
|
|
1910
|
+
"enablePassport",
|
|
1911
|
+
"onlyFront",
|
|
1912
|
+
"onlyBack",
|
|
1913
|
+
"showDocumentChooserScreen"
|
|
1914
|
+
];
|
|
1915
|
+
/**
|
|
1916
|
+
* `onCapture` marks a config as captureOnly. It is not part of
|
|
1917
|
+
* `IdCaptureConfig`, but JavaScript callers (and `<incode-id>`'s `config`
|
|
1918
|
+
* property) can still pass it.
|
|
1919
|
+
*/
|
|
1920
|
+
function hasOnCaptureCallback(config) {
|
|
1921
|
+
return typeof config.onCapture === "function";
|
|
1922
|
+
}
|
|
1923
|
+
/** Keeps the supported keys and `onCapture`, dropping backend-only options. */
|
|
1924
|
+
function pickIdCaptureOnlyConfig(config) {
|
|
1925
|
+
return {
|
|
1926
|
+
...Object.fromEntries(ID_CAPTURE_ONLY_CONFIG_KEYS.filter((key) => config[key] !== void 0).map((key) => [key, config[key]])),
|
|
1927
|
+
onCapture: config.onCapture
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
/**
|
|
1931
|
+
* Whether the captureOnly flow needs the back side after this capture. There
|
|
1932
|
+
* is no backend answer (`skipBackIdCapture`), so `onlyFront` decides. Drives
|
|
1933
|
+
* both the `shouldContinueToBack` guard and the manager's `needsBackCapture`.
|
|
1934
|
+
*/
|
|
1935
|
+
function captureOnlyNeedsBack({ currentMode, config }) {
|
|
1936
|
+
if (currentMode !== "front" && currentMode !== "passport") return false;
|
|
1937
|
+
return !config.onlyFront && !config.onlyBack && !config.usSmartCapture;
|
|
1938
|
+
}
|
|
1939
|
+
//#endregion
|
|
2260
1940
|
//#region src/modules/id/idProtectedCapture.ts
|
|
2261
1941
|
const ID_PROTECTED_CAPTURE_CONTROLLER = Symbol("idProtectedCaptureController");
|
|
2262
1942
|
function attachIdProtectedCaptureController(owner, controller) {
|
|
@@ -2294,12 +1974,12 @@ function streamUsesBackCamera(stream) {
|
|
|
2294
1974
|
const track = stream.getVideoTracks()[0];
|
|
2295
1975
|
if (!track) return;
|
|
2296
1976
|
const settings = typeof track.getSettings === "function" ? track.getSettings() : {};
|
|
2297
|
-
const constrainedFacingMode = typeof track.getConstraints === "function" ? track.getConstraints().facingMode : void 0;
|
|
1977
|
+
const constrainedFacingMode = getDeviceClass() !== "desktop" && typeof track.getConstraints === "function" ? track.getConstraints().facingMode : void 0;
|
|
2298
1978
|
const facingMode = settings.facingMode ?? (typeof constrainedFacingMode === "string" ? constrainedFacingMode : void 0);
|
|
2299
1979
|
if (facingMode === "environment") return true;
|
|
2300
1980
|
if (facingMode === "user") return false;
|
|
2301
1981
|
const label = typeof track.label === "string" ? track.label.toLowerCase() : "";
|
|
2302
|
-
if (
|
|
1982
|
+
if (isBackCameraLabel(label)) return true;
|
|
2303
1983
|
if (label.includes("front") || label.includes("user")) return false;
|
|
2304
1984
|
}
|
|
2305
1985
|
function createIdProtectedCaptureController(dependencies = {}) {
|
|
@@ -2896,6 +2576,8 @@ function createProtectedIdCallbackSession(input) {
|
|
|
2896
2576
|
let countdownTimers = [];
|
|
2897
2577
|
let qualityElements;
|
|
2898
2578
|
let isCapturing = false;
|
|
2579
|
+
let active = true;
|
|
2580
|
+
let paused = false;
|
|
2899
2581
|
let lastReportedSide = null;
|
|
2900
2582
|
let blurSignals = 0;
|
|
2901
2583
|
let bestFrameSignals = 0;
|
|
@@ -2922,7 +2604,7 @@ function createProtectedIdCallbackSession(input) {
|
|
|
2922
2604
|
};
|
|
2923
2605
|
const startCountdown = () => {
|
|
2924
2606
|
clearCountdown();
|
|
2925
|
-
const stepMs = (input.context.config
|
|
2607
|
+
const stepMs = resolveCountdownStepMs(input.context.config);
|
|
2926
2608
|
input.send({
|
|
2927
2609
|
type: "COUNTER_VALUE_CHANGE",
|
|
2928
2610
|
value: 3
|
|
@@ -2946,114 +2628,139 @@ function createProtectedIdCallbackSession(input) {
|
|
|
2946
2628
|
send: setDetectionStatus,
|
|
2947
2629
|
isSuppressed: () => isReportedIdSideWrong(input.context.currentMode, lastReportedSide)
|
|
2948
2630
|
});
|
|
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;
|
|
2631
|
+
const callbacks = {
|
|
2632
|
+
onFarAway: () => {
|
|
2633
|
+
if (!active || paused) return;
|
|
2634
|
+
if (!isCapturing) notifications.show("farAway");
|
|
2635
|
+
},
|
|
2636
|
+
onDetectionStarted: () => {},
|
|
2637
|
+
onMaskChange: (_show, _mask, _top, orientation) => {
|
|
2638
|
+
if (!active || paused) return;
|
|
2639
|
+
input.send({
|
|
2640
|
+
type: "ORIENTATION_CHANGE",
|
|
2641
|
+
orientation
|
|
2642
|
+
});
|
|
2643
|
+
},
|
|
2644
|
+
onBlur: () => {
|
|
2645
|
+
if (!active || paused) return;
|
|
2646
|
+
blurSignals += 1;
|
|
2647
|
+
if (!isCapturing) notifications.show("blur");
|
|
2648
|
+
},
|
|
2649
|
+
onGlare: () => {
|
|
2650
|
+
if (!active || paused) return;
|
|
2651
|
+
if (!isCapturing) notifications.show("glare");
|
|
2652
|
+
},
|
|
2653
|
+
onIdNotDetected: () => {
|
|
2654
|
+
if (!active || paused) return;
|
|
2655
|
+
if (!isCapturing) setDetectionStatus("idNotDetected");
|
|
2656
|
+
},
|
|
2657
|
+
onSwitchToManualCapture: () => {
|
|
2658
|
+
if (!active || paused) return;
|
|
2659
|
+
isCapturing = false;
|
|
2660
|
+
notifications.clear();
|
|
2661
|
+
clearOptimizingBoundary();
|
|
2662
|
+
clearCountdown();
|
|
2663
|
+
input.send({ type: input.controller.hasCommit() ? "PROTECTED_RELEASE_STASHED_COMMIT" : "SWITCH_TO_MANUAL_CAPTURE" });
|
|
2664
|
+
},
|
|
2665
|
+
onCapturing: () => {
|
|
2666
|
+
if (!active || paused) return;
|
|
2667
|
+
const wasCapturing = isCapturing;
|
|
2668
|
+
notifications.clear();
|
|
2669
|
+
lastReportedSide = null;
|
|
2670
|
+
isCapturing = true;
|
|
2671
|
+
setDetectionStatus("capturing");
|
|
2672
|
+
if (!wasCapturing) logDiagnostic("capture-window", {
|
|
2673
|
+
aggregationMs: input.context.config.thresholds?.framesAggregationInterval ?? DEFAULT_ID_CAPTURE_THRESHOLDS.framesAggregationInterval,
|
|
2674
|
+
blurSignals
|
|
2675
|
+
});
|
|
2676
|
+
if (!wasCapturing && input.context.captureFeedbackMode === "countdown") startCountdown();
|
|
2677
|
+
if (input.context.captureFeedbackMode === "optimizing" && input.context.config.supportsOptimizingStatus === true && input.context.captureWindowMs != null) {
|
|
3015
2678
|
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
|
-
});
|
|
2679
|
+
optimizingBoundary = timer.setTimeout(() => {
|
|
2680
|
+
optimizingBoundary = null;
|
|
2681
|
+
const presentation = input.controller.getPresentationCanvas();
|
|
2682
|
+
if (presentation) {
|
|
2683
|
+
presentation.release();
|
|
2684
|
+
input.send({ type: "PROTECTED_OPTIMIZING" });
|
|
2685
|
+
}
|
|
2686
|
+
}, input.context.captureWindowMs);
|
|
3051
2687
|
}
|
|
3052
2688
|
},
|
|
3053
|
-
|
|
3054
|
-
|
|
2689
|
+
onBestFrame: (blur, glare, orientation) => {
|
|
2690
|
+
if (!active || paused) return;
|
|
2691
|
+
bestFrameSignals += 1;
|
|
2692
|
+
bestBlur = bestBlur === void 0 ? blur : Math.min(bestBlur, blur);
|
|
2693
|
+
qualityElements = {
|
|
2694
|
+
glare,
|
|
2695
|
+
sharpness: blur
|
|
2696
|
+
};
|
|
2697
|
+
if (orientation === "horizontal" || orientation === "vertical") input.send({
|
|
2698
|
+
type: "ORIENTATION_CHANGE",
|
|
2699
|
+
orientation
|
|
2700
|
+
});
|
|
2701
|
+
},
|
|
2702
|
+
onCapture: (canvas) => {
|
|
2703
|
+
if (!active || paused) return;
|
|
2704
|
+
isCapturing = false;
|
|
3055
2705
|
clearOptimizingBoundary();
|
|
3056
2706
|
clearCountdown();
|
|
2707
|
+
logDiagnostic("capture-selected", {
|
|
2708
|
+
blurSignals,
|
|
2709
|
+
bestFrameSignals,
|
|
2710
|
+
bestBlur,
|
|
2711
|
+
selectedBlur: qualityElements?.sharpness,
|
|
2712
|
+
selectedGlare: qualityElements?.glare
|
|
2713
|
+
});
|
|
2714
|
+
input.controller.storeAutoCaptureFrame(canvas);
|
|
2715
|
+
input.send({
|
|
2716
|
+
type: "PROTECTED_AUTO_CAPTURE",
|
|
2717
|
+
qualityElements
|
|
2718
|
+
});
|
|
2719
|
+
},
|
|
2720
|
+
onIdTypeChange: (idType) => {
|
|
2721
|
+
if (!active || paused) return;
|
|
2722
|
+
input.send({
|
|
2723
|
+
type: "ID_TYPE_CHANGE",
|
|
2724
|
+
idType
|
|
2725
|
+
});
|
|
2726
|
+
},
|
|
2727
|
+
onIdSideChange: (side) => {
|
|
2728
|
+
if (!active || paused) return;
|
|
2729
|
+
if (isCapturing) return;
|
|
2730
|
+
lastReportedSide = side;
|
|
2731
|
+
if (isReportedIdSideWrong(input.context.currentMode, lastReportedSide)) notifications.clear();
|
|
2732
|
+
input.send({
|
|
2733
|
+
type: "ID_SIDE_CHANGE",
|
|
2734
|
+
side
|
|
2735
|
+
});
|
|
2736
|
+
},
|
|
2737
|
+
onCapturingCounterValueChange: () => {},
|
|
2738
|
+
onBarcodeDecoded: (decoded) => {
|
|
2739
|
+
if (!active || paused) return;
|
|
2740
|
+
input.send({
|
|
2741
|
+
type: "BARCODE_DECODED",
|
|
2742
|
+
decoded
|
|
2743
|
+
});
|
|
2744
|
+
}
|
|
2745
|
+
};
|
|
2746
|
+
const pause = () => {
|
|
2747
|
+
paused = true;
|
|
2748
|
+
notifications.clear();
|
|
2749
|
+
clearOptimizingBoundary();
|
|
2750
|
+
clearCountdown();
|
|
2751
|
+
isCapturing = false;
|
|
2752
|
+
qualityElements = void 0;
|
|
2753
|
+
lastReportedSide = null;
|
|
2754
|
+
};
|
|
2755
|
+
return {
|
|
2756
|
+
callbacks,
|
|
2757
|
+
pause,
|
|
2758
|
+
resume: () => {
|
|
2759
|
+
paused = false;
|
|
2760
|
+
},
|
|
2761
|
+
dispose: () => {
|
|
2762
|
+
active = false;
|
|
2763
|
+
pause();
|
|
3057
2764
|
}
|
|
3058
2765
|
};
|
|
3059
2766
|
}
|
|
@@ -3068,7 +2775,7 @@ function createProtectedIdAttemptInput(input) {
|
|
|
3068
2775
|
const preAcquired = controller.takePreAcquiredStream();
|
|
3069
2776
|
let selectedVideoTrack = preAcquired?.stream.getVideoTracks()[0];
|
|
3070
2777
|
const constraints = getCameraReacquisitionConstraints(selectedVideoTrack, preAcquired?.constraints);
|
|
3071
|
-
const captureOnly =
|
|
2778
|
+
const captureOnly = hasOnCaptureCallback(context.config);
|
|
3072
2779
|
const diagnosticAttempt = controller.getDiagnosticAttempt();
|
|
3073
2780
|
const isAttemptActive = () => !controller.disposed && controller.getProvider() === provider && controller.getDiagnosticAttempt() === diagnosticAttempt;
|
|
3074
2781
|
const logSelectedCamera = (stream, fallbackLevel, reacquisitionConstraints, preAcquiredStream) => {
|
|
@@ -3137,6 +2844,11 @@ function createProtectedIdAttemptInput(input) {
|
|
|
3137
2844
|
...timing
|
|
3138
2845
|
});
|
|
3139
2846
|
},
|
|
2847
|
+
pauseDetection: callbackSession.pause,
|
|
2848
|
+
resumeDetection(reset) {
|
|
2849
|
+
if (reset) provider.resetDetectionState();
|
|
2850
|
+
callbackSession.resume();
|
|
2851
|
+
},
|
|
3140
2852
|
async configureWorkflow() {
|
|
3141
2853
|
await provider.initialize({});
|
|
3142
2854
|
configureIdCaptureProvider({
|
|
@@ -3199,52 +2911,383 @@ function createProtectedIdAttemptInput(input) {
|
|
|
3199
2911
|
}
|
|
3200
2912
|
};
|
|
3201
2913
|
}
|
|
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;
|
|
2914
|
+
function protectedIdResultToCaptureResponse(result) {
|
|
2915
|
+
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;
|
|
2916
|
+
return {
|
|
2917
|
+
sharpness: result.sharpness ?? 0,
|
|
2918
|
+
correctSharpness: result.sharpness != null && result.sharpness >= 10,
|
|
2919
|
+
glare: result.glare ?? 0,
|
|
2920
|
+
correctGlare: result.glare != null && result.glare >= 10,
|
|
2921
|
+
horizontalResolution: 0,
|
|
2922
|
+
classification: result.classification === true,
|
|
2923
|
+
readability: result.readability === true,
|
|
2924
|
+
typeOfId: result.typeOfId ?? "",
|
|
2925
|
+
issueYear: 0,
|
|
2926
|
+
issueName: "",
|
|
2927
|
+
sessionStatus: result.sessionStatus ?? "",
|
|
2928
|
+
countryCode: result.countryCode ?? "",
|
|
2929
|
+
skipBackIdCapture: result.skipBackIdCapture,
|
|
2930
|
+
skipGlareFront: result.skipGlareFront,
|
|
2931
|
+
skipGlareBack: result.skipGlareBack,
|
|
2932
|
+
acceptedDocuments: result.acceptedDocuments ? [...result.acceptedDocuments] : void 0,
|
|
2933
|
+
forceFrontIdCapture: result.forceFrontIdCapture,
|
|
2934
|
+
idValidationCompleted: result.idValidationCompleted,
|
|
2935
|
+
showMandatoryConsent: result.showMandatoryConsent,
|
|
2936
|
+
regulationType,
|
|
2937
|
+
failReason: result.failReason,
|
|
2938
|
+
side: result.side,
|
|
2939
|
+
idQualityAttemptApproved: result.idQualityAttemptApproved,
|
|
2940
|
+
isDocumentExpired: result.isDocumentExpired,
|
|
2941
|
+
success: result.success
|
|
2942
|
+
};
|
|
2943
|
+
}
|
|
2944
|
+
function getProtectedIdUploadRequest(context, sessionToken = getToken()) {
|
|
2945
|
+
const target = resolveProtectedIdTarget(context.config, context.currentMode);
|
|
2946
|
+
const front = context.currentMode !== "back";
|
|
2947
|
+
const params = { captureType: context.manualCaptureTriggered ? "MANUAL" : "AUTO" };
|
|
2948
|
+
if (front && context.config.onlyFront === true) params.onlyFront = true;
|
|
2949
|
+
if (front && context.config.extractIdFace === false) params.extractIdFace = false;
|
|
2950
|
+
const sharpness = context.qualityElements?.sharpness;
|
|
2951
|
+
if (sharpness !== void 0 && sharpness !== 0 && Number.isFinite(sharpness)) params.sharpness = getRealQualityValue(sharpness);
|
|
2952
|
+
return {
|
|
2953
|
+
target,
|
|
2954
|
+
config: {
|
|
2955
|
+
...sessionToken ? { headers: { "X-Incode-Hardware-Id": sessionToken } } : {},
|
|
2956
|
+
params
|
|
2957
|
+
}
|
|
2958
|
+
};
|
|
2959
|
+
}
|
|
2960
|
+
//#endregion
|
|
2961
|
+
//#region src/modules/id/digitalIdRegistry.ts
|
|
2962
|
+
/**
|
|
2963
|
+
* True when a digital-ID method uses a full-page web-redirect flow (Trinsic
|
|
2964
|
+
* iDIN/FTN). Accepts both the module `FlowType` value (`REDIRECT`) and the
|
|
2965
|
+
* backend value (`WEB_REDIRECT`). (Lives here rather than in
|
|
2966
|
+
* `idCaptureHelpers` to keep the registry free of circular imports; the
|
|
2967
|
+
* helpers re-export it.)
|
|
2968
|
+
*/
|
|
2969
|
+
function isRedirectFlowType(flowType) {
|
|
2970
|
+
return flowType === "REDIRECT" || flowType === "WEB_REDIRECT";
|
|
2971
|
+
}
|
|
2972
|
+
const DIGITAL_ID_REGISTRY = {
|
|
2973
|
+
mDL: [{
|
|
2974
|
+
kind: "incodeWallet",
|
|
2975
|
+
documentType: "digitalId"
|
|
2976
|
+
}, {
|
|
2977
|
+
kind: "trinsicRedirect",
|
|
2978
|
+
documentType: "digitalIdRedirect",
|
|
2979
|
+
providerId: "trinsic_mdl_placeholder",
|
|
2980
|
+
method: "MDL"
|
|
2981
|
+
}],
|
|
2982
|
+
iDIN: [{
|
|
2983
|
+
kind: "trinsicRedirect",
|
|
2984
|
+
documentType: "digitalIdRedirect",
|
|
2985
|
+
providerId: "trinsic_netherlands_idin",
|
|
2986
|
+
method: "IDIN"
|
|
2987
|
+
}],
|
|
2988
|
+
FTN: [{
|
|
2989
|
+
kind: "trinsicRedirect",
|
|
2990
|
+
documentType: "digitalIdRedirect",
|
|
2991
|
+
providerId: "trinsic_finnish_trust_network",
|
|
2992
|
+
method: "FTN"
|
|
2993
|
+
}]
|
|
2994
|
+
};
|
|
2995
|
+
const DIGITAL_ID_DOCUMENT_TYPES = Object.keys(DIGITAL_ID_REGISTRY);
|
|
2996
|
+
/**
|
|
2997
|
+
* Single place that widens `config.digitalIds` to the shapes the backend
|
|
2998
|
+
* actually sends — the mapped array or the raw `{ enabled, methods }` object.
|
|
2999
|
+
* Shared so the cast is written once.
|
|
3000
|
+
*/
|
|
3001
|
+
function asDigitalIdsConfig(config) {
|
|
3002
|
+
return config.digitalIds;
|
|
3003
|
+
}
|
|
3004
|
+
/**
|
|
3005
|
+
* Persisted method name → catalog provider id, derived from the registry's
|
|
3006
|
+
* Trinsic entries (single source of truth). Lets the SDK launch iDIN / FTN
|
|
3007
|
+
* from a backend that does not yet send `providerId` on each method.
|
|
3008
|
+
* TODO(roadmap: fully-catalog-driven): remove once every backend enriches
|
|
3009
|
+
* `digitalIds.methods[]` with `providerId` + `flowType`.
|
|
3010
|
+
*/
|
|
3011
|
+
const REDIRECT_PROVIDER_BY_METHOD = (() => {
|
|
3012
|
+
const map = {};
|
|
3013
|
+
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;
|
|
3014
|
+
return map;
|
|
3015
|
+
})();
|
|
3016
|
+
/**
|
|
3017
|
+
* Redirect providers that are the fallback leg of a wallet-first funnel
|
|
3018
|
+
* (mDL): they are reached through the `digitalId` tile's funnel resolution,
|
|
3019
|
+
* not offered as a standalone chooser card.
|
|
3020
|
+
*/
|
|
3021
|
+
const WALLET_FUNNEL_REDIRECT_PROVIDER_IDS = new Set(DIGITAL_ID_DOCUMENT_TYPES.flatMap((docType) => {
|
|
3022
|
+
const entries = DIGITAL_ID_REGISTRY[docType];
|
|
3023
|
+
if (!entries.some((entry) => entry.kind === "incodeWallet")) return [];
|
|
3024
|
+
return entries.flatMap((entry) => entry.kind === "trinsicRedirect" ? [entry.providerId] : []);
|
|
3025
|
+
}));
|
|
3026
|
+
/**
|
|
3027
|
+
* True for a redirect provider that gets its own chooser card (iDIN, FTN, any
|
|
3028
|
+
* catalog-enriched redirect method) — as opposed to the mDL wallet fallback,
|
|
3029
|
+
* which only surfaces through the Digital ID tile.
|
|
3030
|
+
*/
|
|
3031
|
+
function isStandaloneRedirectProvider(providerId) {
|
|
3032
|
+
return !WALLET_FUNNEL_REDIRECT_PROVIDER_IDS.has(providerId);
|
|
3033
|
+
}
|
|
3034
|
+
/**
|
|
3035
|
+
* The provider id a configured method launches with, when it is a
|
|
3036
|
+
* web-redirect method; `undefined` for wallets / other flow shapes.
|
|
3037
|
+
*
|
|
3038
|
+
* Resolution order:
|
|
3039
|
+
* 1. an explicit redirect `flowType` with a `provider` (mapped shape) or
|
|
3040
|
+
* `providerId` (catalog-enriched raw shape) — backend-authoritative;
|
|
3041
|
+
* 2. otherwise the persisted method name via the registry (legacy raw shape).
|
|
3042
|
+
*/
|
|
3043
|
+
function resolveRedirectProviderId(method) {
|
|
3044
|
+
if (method.flowType) {
|
|
3045
|
+
if (!isRedirectFlowType(method.flowType)) return;
|
|
3046
|
+
const explicit = method.provider ?? method.providerId;
|
|
3047
|
+
if (explicit) return explicit;
|
|
3048
|
+
}
|
|
3049
|
+
return method.method ? REDIRECT_PROVIDER_BY_METHOD[method.method.toUpperCase()] : void 0;
|
|
3050
|
+
}
|
|
3051
|
+
/**
|
|
3052
|
+
* Tolerant view over `config.digitalIds`: accepts both the mapped array
|
|
3053
|
+
* (`IdCaptureDigitalIdMethod[]`) and the raw backend object
|
|
3054
|
+
* (`{ enabled, methods: [...] }`). Extracted from the old
|
|
3055
|
+
* `getDigitalIdRedirectMethod` cast so every consumer parses it the same way.
|
|
3056
|
+
*
|
|
3057
|
+
* Honors both dashboard toggles: a raw object with `enabled: false` yields no
|
|
3058
|
+
* methods, and individual methods with `enabled: false` are dropped (absent
|
|
3059
|
+
* `enabled` counts as on). This is what "enabled for the flow / workflow"
|
|
3060
|
+
* means — for the redirect chooser cards as much as for the wallet tile.
|
|
3061
|
+
*/
|
|
3062
|
+
function normalizeDigitalIdMethods(config) {
|
|
3063
|
+
const raw = asDigitalIdsConfig(config);
|
|
3064
|
+
if (!Array.isArray(raw) && raw?.enabled === false) return [];
|
|
3065
|
+
return (Array.isArray(raw) ? raw : raw?.methods ?? []).filter((method) => method.enabled !== false);
|
|
3066
|
+
}
|
|
3067
|
+
/**
|
|
3068
|
+
* Persisted method names of the Incode-native device wallets — the backend
|
|
3069
|
+
* `DigitalIdMethodCatalog` entries of type `MDL`. A catalog-enriched method
|
|
3070
|
+
* carries `type: 'MDL'` instead of relying on the name; both are honoured.
|
|
3071
|
+
*/
|
|
3072
|
+
const DEVICE_WALLET_METHODS = /* @__PURE__ */ new Set([
|
|
3073
|
+
"APPLE_WALLET",
|
|
3074
|
+
"GOOGLE_WALLET",
|
|
3075
|
+
"CA_DMV_WALLET"
|
|
3076
|
+
]);
|
|
3077
|
+
/**
|
|
3078
|
+
* True for a configured method the native device-wallet handshake can fulfil.
|
|
3079
|
+
* Redirect methods (iDIN, FTN) never count, whatever their name or type — they
|
|
3080
|
+
* must not surface a wallet tile with no wallet behind it.
|
|
3081
|
+
*
|
|
3082
|
+
* Classifies by *kind* only. Whether a method is switched on is already
|
|
3083
|
+
* settled by `normalizeDigitalIdMethods`, which drops disabled methods before
|
|
3084
|
+
* any caller walks the list.
|
|
3085
|
+
*/
|
|
3086
|
+
function isDeviceWalletMethod(method) {
|
|
3087
|
+
if (method.flowType && isRedirectFlowType(method.flowType)) return false;
|
|
3088
|
+
if (method.type?.toUpperCase() === "MDL") return true;
|
|
3089
|
+
return method.method !== void 0 && DEVICE_WALLET_METHODS.has(method.method.toUpperCase());
|
|
3090
|
+
}
|
|
3091
|
+
/**
|
|
3092
|
+
* Whether a device wallet is enabled for this ID-capture config: the coarse
|
|
3093
|
+
* `deviceWallet` flag, or an enabled wallet method in `config.digitalIds`.
|
|
3094
|
+
*
|
|
3095
|
+
* The dashboard persists a wallet only in `digitalIds.methods` and leaves the
|
|
3096
|
+
* legacy `deviceWallet` / `appleWallet` booleans at their stored `false`. The
|
|
3097
|
+
* backend derives the booleans from `digitalIds` for the flow response, but
|
|
3098
|
+
* the workflow-node response historically shipped them raw — so a workflow
|
|
3099
|
+
* with Apple Wallet enabled arrived here as `deviceWallet: false`, and the
|
|
3100
|
+
* tile was dropped while SDK 1 (which reads `digitalIds` itself) showed it.
|
|
3101
|
+
* Mirrors the backend's own `deriveDeviceWalletFlag`, minus its "unknown
|
|
3102
|
+
* method counts as a wallet" fallback: an unrecognised method must not
|
|
3103
|
+
* launch a handshake that cannot know what to request.
|
|
3104
|
+
*/
|
|
3105
|
+
function isDeviceWalletEnabled(config) {
|
|
3106
|
+
if (config.deviceWallet === true) return true;
|
|
3107
|
+
return hasEnabledDeviceWalletMethod(config);
|
|
3108
|
+
}
|
|
3109
|
+
/** Whether a funnel entry is activated by config + platform capabilities. */
|
|
3110
|
+
function isEntryActive(entry, config, platform) {
|
|
3111
|
+
if (entry.kind === "incodeWallet") return isDeviceWalletEnabled(config) && platform.credentialsAvailable;
|
|
3112
|
+
return findConfiguredMethod(entry, config) !== void 0;
|
|
3113
|
+
}
|
|
3114
|
+
/**
|
|
3115
|
+
* The configured `digitalIds` method matching a Trinsic funnel entry — by
|
|
3116
|
+
* persisted method name, or (mapped shape) by provider id on a redirect
|
|
3117
|
+
* flowType. First match wins; disabled methods are already dropped by
|
|
3118
|
+
* `normalizeDigitalIdMethods`.
|
|
3119
|
+
*/
|
|
3120
|
+
function findConfiguredMethod(entry, config) {
|
|
3121
|
+
return normalizeDigitalIdMethods(config).find((method) => method.method?.toUpperCase() === entry.method || method.provider === entry.providerId && !!method.flowType && isRedirectFlowType(method.flowType));
|
|
3122
|
+
}
|
|
3123
|
+
/** Normalizes a raw configured method into the mapped shape for the child input. */
|
|
3124
|
+
function toMappedMethod(entry, method) {
|
|
3125
|
+
if (method.flowType && isRedirectFlowType(method.flowType)) return method;
|
|
3126
|
+
return {
|
|
3127
|
+
method: method.method,
|
|
3128
|
+
provider: entry.providerId,
|
|
3129
|
+
flowType: "WEB_REDIRECT",
|
|
3130
|
+
country: method.country ?? method.countries?.[0],
|
|
3131
|
+
displayName: method.displayName,
|
|
3132
|
+
logoUrl: method.logoUrl
|
|
3133
|
+
};
|
|
3134
|
+
}
|
|
3135
|
+
/**
|
|
3136
|
+
* True when `config.digitalIds` carries a device-wallet method that is switched
|
|
3137
|
+
* on, honouring both dashboard toggles: the `digitalIds.enabled` master switch
|
|
3138
|
+
* and each method's own `enabled` flag. An absent `enabled` counts as on, the
|
|
3139
|
+
* tolerant reading the rest of this module uses.
|
|
3140
|
+
*
|
|
3141
|
+
* Both toggles are applied by `normalizeDigitalIdMethods`, so this only has to
|
|
3142
|
+
* ask whether any surviving method is a wallet.
|
|
3143
|
+
*/
|
|
3144
|
+
function hasEnabledDeviceWalletMethod(config) {
|
|
3145
|
+
return normalizeDigitalIdMethods(config).some(isDeviceWalletMethod);
|
|
3146
|
+
}
|
|
3147
|
+
/**
|
|
3148
|
+
* Resolves the implementation that should fulfil a digital-ID document type:
|
|
3149
|
+
* the first funnel entry that is active under the given config and platform.
|
|
3150
|
+
* `undefined` when nothing can run it (the chooser then shows no tile for it).
|
|
3151
|
+
*/
|
|
3152
|
+
function resolveDigitalIdImplementation(docType, config, platform) {
|
|
3153
|
+
for (const entry of DIGITAL_ID_REGISTRY[docType]) {
|
|
3154
|
+
if (!isEntryActive(entry, config, platform)) continue;
|
|
3155
|
+
if (entry.kind === "incodeWallet") return { kind: "incodeWallet" };
|
|
3156
|
+
const method = findConfiguredMethod(entry, config);
|
|
3157
|
+
return {
|
|
3158
|
+
kind: "trinsicRedirect",
|
|
3159
|
+
providerId: entry.providerId,
|
|
3160
|
+
method: method ? toMappedMethod(entry, method) : void 0
|
|
3161
|
+
};
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
//#endregion
|
|
3165
|
+
//#region src/modules/id/idCaptureHelpers.ts
|
|
3166
|
+
/**
|
|
3167
|
+
* Normalizes a configured method into the mapped redirect shape for a
|
|
3168
|
+
* resolved provider. The already-mapped shape is returned as-is; the raw
|
|
3169
|
+
* backend shape gets `provider` + `WEB_REDIRECT` filled in.
|
|
3170
|
+
*/
|
|
3171
|
+
function toRedirectMethod(method, provider) {
|
|
3172
|
+
if (method.provider && method.flowType) return method;
|
|
3204
3173
|
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
|
|
3174
|
+
method: method.method,
|
|
3175
|
+
provider,
|
|
3176
|
+
flowType: "WEB_REDIRECT",
|
|
3177
|
+
country: method.country ?? method.countries?.[0],
|
|
3178
|
+
displayName: method.displayName,
|
|
3179
|
+
logoUrl: method.logoUrl
|
|
3230
3180
|
};
|
|
3231
3181
|
}
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3182
|
+
/**
|
|
3183
|
+
* The enabled web-redirect digital-ID method to launch — the one matching
|
|
3184
|
+
* `providerId` when given (a chooser card was picked), else the first
|
|
3185
|
+
* configured redirect method — or `undefined` when none is configured.
|
|
3186
|
+
* Drives the provider and country passed to the `digitalIdRedirectMachine`.
|
|
3187
|
+
*
|
|
3188
|
+
* Accepts both the mapped array (`IdCaptureDigitalIdMethod[]`) and the raw
|
|
3189
|
+
* backend `configuration.digitalIds` object (`{ enabled, methods: [...] }`);
|
|
3190
|
+
* for the raw shape the provider comes from the backend-enriched
|
|
3191
|
+
* `providerId`/`flowType` when present, else from the persisted method name
|
|
3192
|
+
* via the digital-ID registry (`IDIN` → `trinsic_netherlands_idin`).
|
|
3193
|
+
*/
|
|
3194
|
+
function getDigitalIdRedirectMethod(config, providerId) {
|
|
3195
|
+
for (const method of normalizeDigitalIdMethods(config)) {
|
|
3196
|
+
const provider = resolveRedirectProviderId(method);
|
|
3197
|
+
if (!provider || providerId !== void 0 && provider !== providerId) continue;
|
|
3198
|
+
return toRedirectMethod(method, provider);
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
/**
|
|
3202
|
+
* The digital-ID web-redirect providers that get their own chooser card: one
|
|
3203
|
+
* per enabled redirect method in `config.digitalIds`, in backend (dashboard)
|
|
3204
|
+
* order, deduped by provider. Wallet-funnel fallbacks (the Trinsic mDL leg)
|
|
3205
|
+
* are excluded — they surface through the Digital ID tile instead.
|
|
3206
|
+
*
|
|
3207
|
+
* Card display data (`displayName`, `logoUrl`, `country`) is whatever the
|
|
3208
|
+
* backend enriched the method with; the UI falls back to generic copy / icon
|
|
3209
|
+
* when absent.
|
|
3210
|
+
*/
|
|
3211
|
+
function getAvailableDigitalIdRedirectOptions(config) {
|
|
3212
|
+
const options = [];
|
|
3213
|
+
for (const method of normalizeDigitalIdMethods(config)) {
|
|
3214
|
+
const providerId = resolveRedirectProviderId(method);
|
|
3215
|
+
if (!providerId || !isStandaloneRedirectProvider(providerId) || options.some((option) => option.providerId === providerId)) continue;
|
|
3216
|
+
options.push({
|
|
3217
|
+
providerId,
|
|
3218
|
+
method: method.method,
|
|
3219
|
+
displayName: method.displayName,
|
|
3220
|
+
logoUrl: method.logoUrl,
|
|
3221
|
+
country: method.country ?? method.countries?.[0]
|
|
3222
|
+
});
|
|
3223
|
+
}
|
|
3224
|
+
return options;
|
|
3225
|
+
}
|
|
3226
|
+
/**
|
|
3227
|
+
* Map of config properties received from the backend to adjusted, internal document types.
|
|
3228
|
+
*/
|
|
3229
|
+
const DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP = [
|
|
3230
|
+
["enableId", "id"],
|
|
3231
|
+
["enablePassport", "passport"],
|
|
3232
|
+
["digitalIdsUpload", "digitalIdUpload"]
|
|
3233
|
+
];
|
|
3234
|
+
/**
|
|
3235
|
+
* Returns the list of document types enabled by config for the chooser screen, in display order.
|
|
3236
|
+
* Used to populate chooser state so UI and headless consumers can render the correct options.
|
|
3237
|
+
*
|
|
3238
|
+
* Digital-ID document types (device wallet, Trinsic web-redirect) come from
|
|
3239
|
+
* the digital-ID registry funnel: each registry document type contributes the
|
|
3240
|
+
* tile of its first active implementation. A `deviceWallet: true` config on a
|
|
3241
|
+
* platform without the Credentials API therefore shows the Trinsic fallback
|
|
3242
|
+
* tile when one is configured — or no tile at all, instead of a dead-end one.
|
|
3243
|
+
*
|
|
3244
|
+
* @param config - ID capture configuration (from flow or init)
|
|
3245
|
+
* @param platform - Platform capabilities consulted by the digital-ID funnel.
|
|
3246
|
+
* Defaults to no Credentials API for pure-node callers; the machine passes
|
|
3247
|
+
* the real capability check.
|
|
3248
|
+
* @returns Array of IdDocumentType values that should be shown in the document type chooser
|
|
3249
|
+
*/
|
|
3250
|
+
function getAvailableDocumentTypes(config, platform = { credentialsAvailable: false }) {
|
|
3251
|
+
const adjustedDocumentTypes = [];
|
|
3252
|
+
for (const [configProperty, adjustedType] of DOCUMENT_TYPES_CONFIG_TO_ADJUSTED_MAP) if (config[configProperty]) adjustedDocumentTypes.push(adjustedType);
|
|
3253
|
+
for (const docType of DIGITAL_ID_DOCUMENT_TYPES) {
|
|
3254
|
+
const route = resolveDigitalIdImplementation(docType, config, platform);
|
|
3255
|
+
if (!route) continue;
|
|
3256
|
+
const documentType = route.kind === "incodeWallet" ? "digitalId" : "digitalIdRedirect";
|
|
3257
|
+
if (!adjustedDocumentTypes.includes(documentType)) adjustedDocumentTypes.push(documentType);
|
|
3258
|
+
}
|
|
3259
|
+
if (!adjustedDocumentTypes.includes("digitalIdRedirect") && getAvailableDigitalIdRedirectOptions(config).length > 0) adjustedDocumentTypes.push("digitalIdRedirect");
|
|
3260
|
+
return adjustedDocumentTypes;
|
|
3261
|
+
}
|
|
3262
|
+
/**
|
|
3263
|
+
* Computes `idCaptureMachine`'s terminal output — the downstream module-skip
|
|
3264
|
+
* signal read by the Flow orchestrator (via `runChildModule`'s `MODULE_COMPLETE`).
|
|
3265
|
+
*
|
|
3266
|
+
* `skipFaceMatch` is set ONLY for the US Smart Capture *camera back-only* path:
|
|
3267
|
+
* a back image was captured on-device (`capturedImages.back`) and no front was
|
|
3268
|
+
* (`!capturedImages.front`) — "no front, no ID face, no match".
|
|
3269
|
+
*
|
|
3270
|
+
* Requiring a captured back is deliberate and load-bearing: the digital-ID
|
|
3271
|
+
* upload path submits a full ID (front face present) but does NOT
|
|
3272
|
+
* populate `capturedImages` (only the camera path does). Gating on a captured
|
|
3273
|
+
* back excludes those upload paths so a real ID-vs-selfie match is never
|
|
3274
|
+
* silently skipped. `capturedImages.front`/`forceFrontIdCapture` alone are not
|
|
3275
|
+
* enough (a later front upload clears the request; uploads set neither field).
|
|
3276
|
+
*
|
|
3277
|
+
* Always `false` outside US Smart Capture. The selfie/face capture itself is
|
|
3278
|
+
* unaffected — only the ID-vs-selfie match is skipped.
|
|
3279
|
+
*
|
|
3280
|
+
* Also `true` on the Digital ID web-redirect (Trinsic iDIN/FTN) COMPLETED path
|
|
3281
|
+
* when the scheme returned no portrait (`isDigitalIdRedirect && !portraitPresent`,
|
|
3282
|
+
* FM-1/FM-2): there is no ID face to match the selfie against.
|
|
3283
|
+
*/
|
|
3284
|
+
function computeIdCaptureOutput(context) {
|
|
3285
|
+
const frontIdCaptured = Boolean(context.capturedImages.front);
|
|
3286
|
+
const backIdCaptured = Boolean(context.capturedImages.back);
|
|
3287
|
+
return {
|
|
3288
|
+
frontIdCaptured,
|
|
3289
|
+
skipFaceMatch: context.isDigitalIdRedirect === true && context.portraitPresent !== true || context.config.usSmartCapture === true && backIdCaptured && !frontIdCaptured
|
|
3243
3290
|
};
|
|
3244
|
-
return Object.keys(config).length > 0 ? {
|
|
3245
|
-
target,
|
|
3246
|
-
config
|
|
3247
|
-
} : { target };
|
|
3248
3291
|
}
|
|
3249
3292
|
//#endregion
|
|
3250
3293
|
//#region src/modules/digital-id-redirect/pollCadence.ts
|
|
@@ -3765,9 +3808,6 @@ function getIdErrorCodeFromUnknown(error) {
|
|
|
3765
3808
|
function asPublicIdEvent(event) {
|
|
3766
3809
|
return event;
|
|
3767
3810
|
}
|
|
3768
|
-
function isCaptureOnlyConfig(config) {
|
|
3769
|
-
return "onCapture" in config && typeof config.onCapture === "function";
|
|
3770
|
-
}
|
|
3771
3811
|
function protectedFailure(event) {
|
|
3772
3812
|
return event.type === "PROTECTED_ATTEMPT_FAILED" ? event : null;
|
|
3773
3813
|
}
|
|
@@ -3781,13 +3821,13 @@ const idCaptureMachine = setup({
|
|
|
3781
3821
|
actors: {
|
|
3782
3822
|
checkPermission: checkPermissionActor,
|
|
3783
3823
|
requestPermission: requestPermissionActor,
|
|
3824
|
+
requestMotionPermission: requestMotionPermissionActor,
|
|
3784
3825
|
protectedAttempt: createProtectedIdAttemptActor(),
|
|
3785
3826
|
protectedControllerLifetime: createProtectedIdControllerLifetimeActor(),
|
|
3786
3827
|
captureOnlyDelivery: createIdCaptureOnlyDeliveryActor(),
|
|
3787
3828
|
uploadProgressTicker: uploadProgressTickerActor,
|
|
3788
3829
|
processId: processIdActor,
|
|
3789
3830
|
submitBarcode: submitBarcodeActor,
|
|
3790
|
-
manualUploadMachine,
|
|
3791
3831
|
digitalUploadMachine,
|
|
3792
3832
|
digitalIdRedirectMachine,
|
|
3793
3833
|
deviceWalletMachine,
|
|
@@ -3804,7 +3844,7 @@ const idCaptureMachine = setup({
|
|
|
3804
3844
|
return {};
|
|
3805
3845
|
}),
|
|
3806
3846
|
startProtectedMetadataPreparation: ({ context, self }) => {
|
|
3807
|
-
if (!
|
|
3847
|
+
if (!hasOnCaptureCallback(context.config)) getIdProtectedCaptureController(self).startMetadataPreparation(context);
|
|
3808
3848
|
},
|
|
3809
3849
|
bindProtectedControllerLifetime: sendTo("protectedControllerLifetime", ({ self }) => ({
|
|
3810
3850
|
type: "BIND_PROTECTED_ID_CONTROLLER",
|
|
@@ -3845,7 +3885,7 @@ const idCaptureMachine = setup({
|
|
|
3845
3885
|
requestProtectedManualCommit: sendTo("protectedAttempt", { type: "MANUAL_CAPTURE" }),
|
|
3846
3886
|
finalizeProtectedAttempt: sendTo("protectedAttempt", { type: "FINALIZE" }),
|
|
3847
3887
|
requestProtectedUpload: enqueueActions(({ context, enqueue }) => {
|
|
3848
|
-
if (
|
|
3888
|
+
if (hasOnCaptureCallback(context.config)) return;
|
|
3849
3889
|
enqueue(sendTo("protectedAttempt", {
|
|
3850
3890
|
type: "UPLOAD_PROTECTED",
|
|
3851
3891
|
request: getProtectedIdUploadRequest(context)
|
|
@@ -3863,6 +3903,25 @@ const idCaptureMachine = setup({
|
|
|
3863
3903
|
type: "RELEASE",
|
|
3864
3904
|
reason: "retry"
|
|
3865
3905
|
}),
|
|
3906
|
+
pauseProtectedDetection: sendTo("protectedAttempt", { type: "PAUSE_DETECTION" }),
|
|
3907
|
+
resumeProtectedDetection: sendTo("protectedAttempt", ({ context }) => ({
|
|
3908
|
+
type: "RESUME_DETECTION",
|
|
3909
|
+
reset: !context.manualCaptureTriggered
|
|
3910
|
+
})),
|
|
3911
|
+
resetAutomaticCapture: assign({
|
|
3912
|
+
manualCaptureTriggered: false,
|
|
3913
|
+
detectionStatus: "idle",
|
|
3914
|
+
counterValue: 0,
|
|
3915
|
+
decodedBarcode: null,
|
|
3916
|
+
barcodeFastPathAttempted: false,
|
|
3917
|
+
qualityElements: void 0
|
|
3918
|
+
}),
|
|
3919
|
+
trackSwitchToAutoCapture: ({ context }) => {
|
|
3920
|
+
addEvent({
|
|
3921
|
+
code: context.currentMode === "back" ? "switchToAutoCaptureBackId" : "switchToAutoCaptureFrontId",
|
|
3922
|
+
module: eventModuleNames.idCapture
|
|
3923
|
+
});
|
|
3924
|
+
},
|
|
3866
3925
|
forwardProtectedBackground: sendTo("protectedAttempt", { type: "BACKGROUND" }),
|
|
3867
3926
|
forwardProtectedForeground: sendTo("protectedAttempt", { type: "FOREGROUND" }),
|
|
3868
3927
|
storeProtectedAutoQuality: assign(({ event }) => event.type === "PROTECTED_AUTO_CAPTURE" ? { qualityElements: event.qualityElements } : {}),
|
|
@@ -4047,9 +4106,12 @@ const idCaptureMachine = setup({
|
|
|
4047
4106
|
performStopMediaRecording(context);
|
|
4048
4107
|
},
|
|
4049
4108
|
clearRecordingSession: assign({ recordingSession: () => void 0 }),
|
|
4050
|
-
setSelectedDocument: assign({
|
|
4051
|
-
|
|
4052
|
-
|
|
4109
|
+
setSelectedDocument: assign({
|
|
4110
|
+
selectedDocumentType: ({ event }) => {
|
|
4111
|
+
if ("documentType" in event) return event.documentType;
|
|
4112
|
+
},
|
|
4113
|
+
selectedDigitalIdProviderId: ({ event }) => event.type === "SELECT_DOCUMENT" && event.documentType === "digitalIdRedirect" ? event.providerId : void 0
|
|
4114
|
+
}),
|
|
4053
4115
|
setCurrentMode: assign({ currentMode: ({ event, context }) => getCurrentModeFromEvent(context, asPublicIdEvent(event)) }),
|
|
4054
4116
|
storeCapturedImage: assign(({ context, event }) => getStoreCapturedImageValues(context, asPublicIdEvent(event))),
|
|
4055
4117
|
setCandidateFrame: assign(({ context, event }) => getCandidateFrameValues(context, asPublicIdEvent(event))),
|
|
@@ -4190,6 +4252,22 @@ const idCaptureMachine = setup({
|
|
|
4190
4252
|
digitalIdResumeProviderId: pending?.providerId
|
|
4191
4253
|
};
|
|
4192
4254
|
}),
|
|
4255
|
+
/**
|
|
4256
|
+
* Drops the inputs that belong to one digital-ID attempt: the return-leg
|
|
4257
|
+
* params and the recovered verificationId/providerId, plus the funnel
|
|
4258
|
+
* route. The `digitalIdRedirect` child copies what it needs on entry, so
|
|
4259
|
+
* once it exits nothing reads them — but left in place they are replayed
|
|
4260
|
+
* on the next redirect selection. The return leg would re-submit the
|
|
4261
|
+
* previous provider's result (the user picks iDIN and gets FTN's
|
|
4262
|
+
* cancelled screen back), and a stale route would override the card the
|
|
4263
|
+
* user just picked.
|
|
4264
|
+
*/
|
|
4265
|
+
clearDigitalIdAttempt: assign({
|
|
4266
|
+
digitalIdReturnParams: () => void 0,
|
|
4267
|
+
digitalIdResumeVerificationId: () => void 0,
|
|
4268
|
+
digitalIdResumeProviderId: () => void 0,
|
|
4269
|
+
digitalIdRoute: () => void 0
|
|
4270
|
+
}),
|
|
4193
4271
|
incrementProcessingExpiredAttempts: assign(({ context }) => ({ processingExpiredAttempts: context.processingExpiredAttempts + 1 })),
|
|
4194
4272
|
setSkipProcessId: assign({ skipProcessId: () => true }),
|
|
4195
4273
|
setExpiredFromUpload: assign({ expiredFromUpload: () => true }),
|
|
@@ -4199,7 +4277,7 @@ const idCaptureMachine = setup({
|
|
|
4199
4277
|
clearExpiredFromUpload: assign({ expiredFromUpload: () => false })
|
|
4200
4278
|
},
|
|
4201
4279
|
guards: {
|
|
4202
|
-
isCaptureOnlyDelivery: ({ context }) =>
|
|
4280
|
+
isCaptureOnlyDelivery: ({ context }) => hasOnCaptureCallback(context.config),
|
|
4203
4281
|
isProtectedUploadFailure: ({ event }) => protectedFailure(event)?.failure.stage === "upload",
|
|
4204
4282
|
isProtectedManualRefusal: ({ event }) => protectedFailure(event)?.failure.stage === "manualCommit",
|
|
4205
4283
|
hasShowTutorial: hasShowTutorialGuard,
|
|
@@ -4216,6 +4294,7 @@ const idCaptureMachine = setup({
|
|
|
4216
4294
|
}),
|
|
4217
4295
|
isPermissionDeniedError: ({ event }) => isPermissionDeniedErrorGuard({ event: asPublicIdEvent(event) }),
|
|
4218
4296
|
isPermissionBlocked: isPermissionBlockedGuard,
|
|
4297
|
+
requiresMotionPermissionUserGesture: requiresMotionPermissionUserGestureGuard,
|
|
4219
4298
|
hasAttemptsRemaining: hasAttemptsRemainingGuard,
|
|
4220
4299
|
hasCapturedImage: hasCapturedImageGuard,
|
|
4221
4300
|
hasCandidateFrame: ({ event }) => hasCandidateFrameGuard({ event: asPublicIdEvent(event) }),
|
|
@@ -4229,9 +4308,7 @@ const idCaptureMachine = setup({
|
|
|
4229
4308
|
isDeepsightEnabled: isDeepsightEnabledGuard,
|
|
4230
4309
|
isDeepsightReady: isDeepsightReadyGuard,
|
|
4231
4310
|
needsDeepsightInit: needsDeepsightInitGuard,
|
|
4232
|
-
hasOnlyManualUploadAvailable: hasOnlyManualUploadAvailableGuard,
|
|
4233
4311
|
hasNoDocumentTypesAvailable: hasNoDocumentTypesAvailableGuard,
|
|
4234
|
-
isManualIdUploadSelected: ({ event }) => isManualIdUploadSelectedGuard({ event: asPublicIdEvent(event) }),
|
|
4235
4312
|
isDigitalIdUploadSelected: ({ event }) => isDigitalIdUploadSelectedGuard({ event: asPublicIdEvent(event) }),
|
|
4236
4313
|
isDigitalIdRedirectSelected: ({ event }) => isDigitalIdRedirectSelectedGuard({ event: asPublicIdEvent(event) }),
|
|
4237
4314
|
isDigitalIdSelected: ({ event }) => isDigitalIdSelectedGuard({ event: asPublicIdEvent(event) }),
|
|
@@ -4254,7 +4331,6 @@ const idCaptureMachine = setup({
|
|
|
4254
4331
|
forceFinishAfterProcessing: forceFinishAfterProcessingGuard,
|
|
4255
4332
|
isBackModeInMultiSideFlow: isBackModeInMultiSideFlowGuard,
|
|
4256
4333
|
wasExpiredRedirected: wasExpiredRedirectedGuard,
|
|
4257
|
-
isManualUploadExhausted: ({ event }) => event.output?.result === "exhausted",
|
|
4258
4334
|
isDigitalUploadExhausted: ({ event }) => event.output?.result === "exhausted",
|
|
4259
4335
|
isDigitalUploadSuccessful: ({ event }) => event.output?.result === "success",
|
|
4260
4336
|
isDigitalIdRedirectCompleted: ({ event }) => event.output?.status === "COMPLETED",
|
|
@@ -4303,9 +4379,13 @@ const idCaptureMachine = setup({
|
|
|
4303
4379
|
},
|
|
4304
4380
|
context: ({ input, self }) => {
|
|
4305
4381
|
attachIdProtectedCaptureController(self, createIdProtectedCaptureController());
|
|
4382
|
+
const config = {
|
|
4383
|
+
...input.config,
|
|
4384
|
+
captureAttempts: input.config.captureAttempts ?? 1
|
|
4385
|
+
};
|
|
4306
4386
|
const currentMode = input.config.onlyBack ? "back" : !input.config.enableId && input.config.enablePassport ? "passport" : input.config.usSmartCapture ? "back" : "front";
|
|
4307
4387
|
return {
|
|
4308
|
-
config
|
|
4388
|
+
config,
|
|
4309
4389
|
captureFeedbackMode: input.captureFeedbackMode ?? "countdown",
|
|
4310
4390
|
captureWindowMs: input.captureWindowMs,
|
|
4311
4391
|
optimizingDwellMs: input.optimizingDwellMs,
|
|
@@ -4325,7 +4405,7 @@ const idCaptureMachine = setup({
|
|
|
4325
4405
|
barcodeFastPathAttempted: false,
|
|
4326
4406
|
barcodeFastPathCaptured: false,
|
|
4327
4407
|
recordingSession: void 0,
|
|
4328
|
-
attemptsRemaining:
|
|
4408
|
+
attemptsRemaining: config.captureAttempts,
|
|
4329
4409
|
expiredAttempts: 0,
|
|
4330
4410
|
expiredRedirected: false,
|
|
4331
4411
|
processingExpiredAttempts: 0,
|
|
@@ -4359,6 +4439,8 @@ const idCaptureMachine = setup({
|
|
|
4359
4439
|
disableIpify: getDisableIpify(),
|
|
4360
4440
|
deepsightInitAttempted: false,
|
|
4361
4441
|
availableDocumentTypes: getAvailableDocumentTypes(input.config, { credentialsAvailable: input.dependencies?.credentials?.isAvailable() ?? false }),
|
|
4442
|
+
digitalIdRedirectOptions: getAvailableDigitalIdRedirectOptions(input.config),
|
|
4443
|
+
selectedDigitalIdProviderId: void 0,
|
|
4362
4444
|
captureResolution: void 0,
|
|
4363
4445
|
cameraFallbackLevel: void 0,
|
|
4364
4446
|
usingBackCamera: void 0
|
|
@@ -4379,10 +4461,6 @@ const idCaptureMachine = setup({
|
|
|
4379
4461
|
guard: "hasNoDocumentTypesAvailable",
|
|
4380
4462
|
actions: [() => console.error(ID_CAPTURE_NO_DOCUMENT_TYPES_ERROR), assign({ error: () => ID_CAPTURE_NO_DOCUMENT_TYPES_ERROR })]
|
|
4381
4463
|
},
|
|
4382
|
-
{
|
|
4383
|
-
target: "manualIdUpload",
|
|
4384
|
-
guard: "hasOnlyManualUploadAvailable"
|
|
4385
|
-
},
|
|
4386
4464
|
{
|
|
4387
4465
|
target: "chooser",
|
|
4388
4466
|
guard: "hasShowDocumentChooser"
|
|
@@ -4413,11 +4491,6 @@ const idCaptureMachine = setup({
|
|
|
4413
4491
|
guard: "isDigitalIdUploadSelected",
|
|
4414
4492
|
actions: ["setSelectedDocument"]
|
|
4415
4493
|
},
|
|
4416
|
-
{
|
|
4417
|
-
target: "manualIdUpload",
|
|
4418
|
-
guard: "isManualIdUploadSelected",
|
|
4419
|
-
actions: ["setSelectedDocument"]
|
|
4420
|
-
},
|
|
4421
4494
|
{
|
|
4422
4495
|
target: "ageVerification",
|
|
4423
4496
|
guard: "hasAgeAssurance",
|
|
@@ -4494,6 +4567,14 @@ const idCaptureMachine = setup({
|
|
|
4494
4567
|
}]
|
|
4495
4568
|
},
|
|
4496
4569
|
on: {
|
|
4570
|
+
CONTINUE_TO_PERMISSION: [{
|
|
4571
|
+
target: "requestingMotionPermission",
|
|
4572
|
+
guard: "requiresMotionPermissionUserGesture",
|
|
4573
|
+
actions: "trackContinue"
|
|
4574
|
+
}, {
|
|
4575
|
+
target: "#idCapture.permissions",
|
|
4576
|
+
actions: "trackContinue"
|
|
4577
|
+
}],
|
|
4497
4578
|
NEXT_STEP: {
|
|
4498
4579
|
target: "#idCapture.capture",
|
|
4499
4580
|
actions: "trackContinue"
|
|
@@ -4506,6 +4587,14 @@ const idCaptureMachine = setup({
|
|
|
4506
4587
|
},
|
|
4507
4588
|
initializingCamera: {
|
|
4508
4589
|
type: "parallel",
|
|
4590
|
+
on: { CONTINUE_TO_PERMISSION: [{
|
|
4591
|
+
target: "requestingMotionPermission",
|
|
4592
|
+
guard: "requiresMotionPermissionUserGesture",
|
|
4593
|
+
actions: "trackContinue"
|
|
4594
|
+
}, {
|
|
4595
|
+
target: "#idCapture.permissions",
|
|
4596
|
+
actions: "trackContinue"
|
|
4597
|
+
}] },
|
|
4509
4598
|
states: {
|
|
4510
4599
|
cameraInit: {
|
|
4511
4600
|
initial: "initializingStream",
|
|
@@ -4547,6 +4636,14 @@ const idCaptureMachine = setup({
|
|
|
4547
4636
|
onDone: { target: "#idCapture.capture" }
|
|
4548
4637
|
},
|
|
4549
4638
|
ready: { on: {
|
|
4639
|
+
CONTINUE_TO_PERMISSION: [{
|
|
4640
|
+
target: "requestingMotionPermission",
|
|
4641
|
+
guard: "requiresMotionPermissionUserGesture",
|
|
4642
|
+
actions: "trackContinue"
|
|
4643
|
+
}, {
|
|
4644
|
+
target: "#idCapture.permissions",
|
|
4645
|
+
actions: "trackContinue"
|
|
4646
|
+
}],
|
|
4550
4647
|
NEXT_STEP: {
|
|
4551
4648
|
target: "waitingForPermission",
|
|
4552
4649
|
actions: "trackContinue"
|
|
@@ -4587,6 +4684,15 @@ const idCaptureMachine = setup({
|
|
|
4587
4684
|
actions: assign({ permissionResult: ({ event }) => event.output })
|
|
4588
4685
|
}
|
|
4589
4686
|
]
|
|
4687
|
+
} },
|
|
4688
|
+
requestingMotionPermission: { invoke: {
|
|
4689
|
+
id: "requestTutorialMotionPermission",
|
|
4690
|
+
src: "requestMotionPermission",
|
|
4691
|
+
onDone: [{
|
|
4692
|
+
target: "#idCapture.permissions.denied",
|
|
4693
|
+
guard: ({ event }) => event.output === "denied"
|
|
4694
|
+
}, { target: "#idCapture.permissions" }],
|
|
4695
|
+
onError: { target: "#idCapture.permissions.denied" }
|
|
4590
4696
|
} }
|
|
4591
4697
|
}
|
|
4592
4698
|
},
|
|
@@ -4642,6 +4748,7 @@ const idCaptureMachine = setup({
|
|
|
4642
4748
|
} },
|
|
4643
4749
|
motionOnly: { on: {
|
|
4644
4750
|
REQUEST_PERMISSION: "requesting",
|
|
4751
|
+
GO_TO_LEARN_MORE: "learnMore",
|
|
4645
4752
|
BACK: {
|
|
4646
4753
|
target: "#idCapture.tutorial.ready",
|
|
4647
4754
|
guard: "hasShowTutorial"
|
|
@@ -4755,6 +4862,7 @@ const idCaptureMachine = setup({
|
|
|
4755
4862
|
}],
|
|
4756
4863
|
entry: [assign({ detectionStatus: () => "detecting" })],
|
|
4757
4864
|
on: {
|
|
4865
|
+
OPEN_HELP: { target: "help" },
|
|
4758
4866
|
DETECTION_UPDATE: { actions: "setDetectionStatus" },
|
|
4759
4867
|
PROTECTED_AUTO_CAPTURE: { actions: ["storeProtectedAutoQuality", "requestProtectedAutoCommit"] },
|
|
4760
4868
|
PROTECTED_AUTO_COMMITTED_SIGNAL: {
|
|
@@ -4819,6 +4927,7 @@ const idCaptureMachine = setup({
|
|
|
4819
4927
|
initial: "searching",
|
|
4820
4928
|
states: {
|
|
4821
4929
|
searching: { on: {
|
|
4930
|
+
OPEN_HELP: { target: "#idCapture.capture.help" },
|
|
4822
4931
|
DETECTION_UPDATE: { actions: "setDetectionStatus" },
|
|
4823
4932
|
ID_SIDE_CHANGE: { actions: assign({ detectionStatus: ({ context, event }) => getDetectionStatusFromSideChange(context, event.side) }) },
|
|
4824
4933
|
BARCODE_DECODED: [{
|
|
@@ -4856,7 +4965,34 @@ const idCaptureMachine = setup({
|
|
|
4856
4965
|
}
|
|
4857
4966
|
}
|
|
4858
4967
|
},
|
|
4968
|
+
help: {
|
|
4969
|
+
entry: "pauseProtectedDetection",
|
|
4970
|
+
on: {
|
|
4971
|
+
CLOSE_HELP: [{
|
|
4972
|
+
guard: "hasManualCaptureTriggered",
|
|
4973
|
+
target: "manualCaptureWaiting",
|
|
4974
|
+
actions: "resumeProtectedDetection"
|
|
4975
|
+
}, {
|
|
4976
|
+
target: "choosingDetectionStrategy",
|
|
4977
|
+
actions: ["resetAutomaticCapture", "resumeProtectedDetection"]
|
|
4978
|
+
}],
|
|
4979
|
+
SWITCH_TO_MANUAL_CAPTURE: { actions: assign({
|
|
4980
|
+
manualCaptureTriggered: true,
|
|
4981
|
+
detectionStatus: "manualCapture"
|
|
4982
|
+
}) },
|
|
4983
|
+
SWITCH_TO_AUTO_CAPTURE: {
|
|
4984
|
+
guard: "hasManualCaptureTriggered",
|
|
4985
|
+
target: "releasingForRetry",
|
|
4986
|
+
actions: ["trackSwitchToAutoCapture", "resetAutomaticCapture"]
|
|
4987
|
+
}
|
|
4988
|
+
}
|
|
4989
|
+
},
|
|
4859
4990
|
manualCaptureWaiting: { on: {
|
|
4991
|
+
OPEN_HELP: { target: "help" },
|
|
4992
|
+
SWITCH_TO_AUTO_CAPTURE: {
|
|
4993
|
+
target: "releasingForRetry",
|
|
4994
|
+
actions: ["trackSwitchToAutoCapture", "resetAutomaticCapture"]
|
|
4995
|
+
},
|
|
4860
4996
|
MANUAL_CAPTURE: { actions: "requestProtectedManualCommit" },
|
|
4861
4997
|
PROTECTED_MANUAL_COMMITTED_SIGNAL: {
|
|
4862
4998
|
target: "capturingManual",
|
|
@@ -4962,7 +5098,7 @@ const idCaptureMachine = setup({
|
|
|
4962
5098
|
id: "captureOnlyDelivery",
|
|
4963
5099
|
src: "captureOnlyDelivery",
|
|
4964
5100
|
input: ({ context }) => {
|
|
4965
|
-
if (!
|
|
5101
|
+
if (!hasOnCaptureCallback(context.config)) return { mode: "protected" };
|
|
4966
5102
|
return { mode: "captureOnly" };
|
|
4967
5103
|
}
|
|
4968
5104
|
}],
|
|
@@ -5264,35 +5400,6 @@ const idCaptureMachine = setup({
|
|
|
5264
5400
|
actions: "resetContext"
|
|
5265
5401
|
} }
|
|
5266
5402
|
},
|
|
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
5403
|
digitalIdUpload: {
|
|
5297
5404
|
invoke: {
|
|
5298
5405
|
id: "digitalIdUpload",
|
|
@@ -5351,28 +5458,38 @@ const idCaptureMachine = setup({
|
|
|
5351
5458
|
},
|
|
5352
5459
|
{
|
|
5353
5460
|
target: "chooser",
|
|
5354
|
-
guard: "hasShowDocumentChooser"
|
|
5461
|
+
guard: "hasShowDocumentChooser",
|
|
5462
|
+
actions: ["clearDigitalIdAttempt"]
|
|
5355
5463
|
},
|
|
5356
|
-
{
|
|
5464
|
+
{
|
|
5465
|
+
target: "loading",
|
|
5466
|
+
actions: ["clearDigitalIdAttempt"]
|
|
5467
|
+
}
|
|
5357
5468
|
],
|
|
5358
5469
|
onError: [{
|
|
5359
5470
|
target: "chooser",
|
|
5360
|
-
guard: "hasShowDocumentChooser"
|
|
5361
|
-
|
|
5471
|
+
guard: "hasShowDocumentChooser",
|
|
5472
|
+
actions: ["clearDigitalIdAttempt"]
|
|
5473
|
+
}, {
|
|
5474
|
+
target: "loading",
|
|
5475
|
+
actions: ["clearDigitalIdAttempt"]
|
|
5476
|
+
}]
|
|
5362
5477
|
},
|
|
5363
5478
|
on: { QUIT: { target: "closed" } }
|
|
5364
5479
|
},
|
|
5365
5480
|
digitalIdRedirect: {
|
|
5481
|
+
exit: "clearDigitalIdAttempt",
|
|
5366
5482
|
invoke: {
|
|
5367
5483
|
id: "digitalIdRedirect",
|
|
5368
5484
|
src: "digitalIdRedirectMachine",
|
|
5369
5485
|
input: ({ context }) => {
|
|
5370
|
-
const method = getDigitalIdRedirectMethod(context.config);
|
|
5371
5486
|
const resuming = context.digitalIdReturnParams !== void 0 && context.digitalIdResumeVerificationId !== void 0;
|
|
5372
5487
|
const routedProvider = context.digitalIdRoute?.kind === "trinsicRedirect" ? context.digitalIdRoute.providerId : void 0;
|
|
5488
|
+
const presetProvider = (resuming ? context.digitalIdResumeProviderId : void 0) ?? routedProvider ?? context.selectedDigitalIdProviderId;
|
|
5489
|
+
const method = presetProvider !== void 0 ? getDigitalIdRedirectMethod(context.config, presetProvider) : getDigitalIdRedirectMethod(context.config);
|
|
5373
5490
|
return {
|
|
5374
5491
|
config: {
|
|
5375
|
-
provider:
|
|
5492
|
+
provider: presetProvider ?? method?.provider,
|
|
5376
5493
|
returnUrl: context.config.digitalIdReturnUrl,
|
|
5377
5494
|
country: method?.country
|
|
5378
5495
|
},
|
|
@@ -5479,4 +5596,4 @@ function provideIdProtectedCaptureController(machine, controller) {
|
|
|
5479
5596
|
});
|
|
5480
5597
|
}
|
|
5481
5598
|
//#endregion
|
|
5482
|
-
export {
|
|
5599
|
+
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 };
|