@incodetech/core 2.3.2-rc.4 → 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-B5Fxc_y9.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--p429c2X.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-CWmZMFJH.esm.js → authenticationManager-SaiAxqvS.esm.js} +6 -6
- package/dist/{authenticationStateMachine-BQ7ZW-8a.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-uhDPdU6i.d.ts → consentManager-DgzWQpAR.d.ts} +11 -12
- 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-BtYvACzG.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-66GzzBTx.esm.js → dynamicFormsManager-5uIXobxi.esm.js} +3 -3
- package/dist/{dynamicFormsManager-D5R_uxLQ.d.ts → dynamicFormsManager-C0dHs1ty.d.ts} +3 -3
- package/dist/{dynamicFormsStateMachine-DLnr2ZtX.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-CsQMgJDL.esm.js → ekybManager-CazShiQz.esm.js} +23 -27
- package/dist/{ekybStateMachine-DBeQNOMo.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-Boj_xbGN.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-BKpeQIZu.esm.js → faceCaptureManagerFactory-uFm1AcaY.esm.js} +19 -54
- package/dist/{faceCaptureSetup-DOrt8-Sn.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-zY6FcYx_.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-CBa6YyI5.esm.js → flowCompletionService-xnn_SlJU.esm.js} +2 -2
- package/dist/{flowServices-JW6uRaUt.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-DD5J1T_p.esm.js → geolocationManager-CqNLY45e.esm.js} +6 -7
- package/dist/{geolocationManager-Cz744E5S.d.ts → geolocationManager-Dn24g1fl.d.ts} +2 -3
- package/dist/{geolocationStateMachine-DoelwBqs.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-Chne8cyb.esm.js → idCaptureDefaults-CBg73RnV.esm.js} +8 -5
- package/dist/{idCaptureManager-BHwL2Z0V.d.ts → idCaptureManager-BY97SRCV.d.ts} +242 -98
- package/dist/{idCaptureManager-0504dfcD.esm.js → idCaptureManager-D4V8vXtY.esm.js} +276 -210
- package/dist/{idCaptureServices-B-Ynn67N.esm.js → idCaptureServices-DJ33k3-p.esm.js} +21 -39
- package/dist/{idCaptureStateMachine-B7ET-hfq.esm.js → idCaptureStateMachine-PJt0yzom.esm.js} +989 -872
- package/dist/{idOcrManager-BF_cXZq8.d.ts → idOcrManager-BTdHlJ9D.d.ts} +3 -4
- 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-v2TH5g7e.d.ts → identityReuseManager-ooAbp6Kc.d.ts} +162 -44
- 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-BYRnWbIC.d.ts → mandatoryConsentManager-TkX57U6f.d.ts} +8 -9
- 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-CZU29-IV.esm.js → runChildModule-vdxQMCmO.esm.js} +13 -12
- package/dist/safeStorage-UxDrnjwa.esm.js +35 -0
- package/dist/{sdkVersion-DOhxIxQQ.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-CWhbwRdb.esm.js → selfieManager-26pENXxw.esm.js} +6 -6
- package/dist/selfieStateMachine-BhfKsl3I.esm.js +41 -0
- package/dist/{session-CctUSSCx.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-DmB0JHAB.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-Ce9zO78j.esm.js → thumbmark.esm-CRc0cYvz.esm.js} +33 -776
- package/dist/{trueSightService-oMFESSSb.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-D_4NwYM-.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-CtMCi4KZ.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
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { a as setWebApiHttpTransport, f as deriveSiblingJsPath, i as initializeWasmWebClient, o as setupWasmConnection, p as WASM_MODEL_FILES, r as executeWasmRequest, t as WasmWebClientError, v as buildModelVariantSources } from "./wasmWebClient-
|
|
1
|
+
import { a as setWebApiHttpTransport, f as deriveSiblingJsPath, i as initializeWasmWebClient, o as setupWasmConnection, p as WASM_MODEL_FILES, r as executeWasmRequest, t as WasmWebClientError, v as buildModelVariantSources } from "./wasmWebClient-kbYZ2sxw.esm.js";
|
|
2
2
|
import { t as getTimestamp } from "./IBrowserEnvironmentCapability-DEaRRk-R.esm.js";
|
|
3
|
+
import { n as eventModuleNames } from "./events-CAgFE-k3.esm.js";
|
|
3
4
|
import { i as isApiConfigured, n as getApi, o as setClient, r as getToken, t as api } from "./api-Bx3gKW_y.esm.js";
|
|
4
|
-
import {
|
|
5
|
-
import { t as SDK_VERSION } from "./sdkVersion-
|
|
6
|
-
import { t as
|
|
5
|
+
import { t as endpoints } from "./endpoints-DHzlkQNe.esm.js";
|
|
6
|
+
import { t as SDK_VERSION } from "./sdkVersion-F5YZbjip.esm.js";
|
|
7
|
+
import { n as reportHttpError, t as HttpRequestError } from "./HttpRequestError-Bh0pNGSC.esm.js";
|
|
7
8
|
//#region ../infra/src/wasm/wasmDefaults.ts
|
|
8
9
|
const WASM_CDN_BASE_URL = "https://cdn.incodesmile.com/ml-wasm-kit-release";
|
|
9
10
|
/** The WASM version bundled and tested with this SDK release. */
|
|
@@ -131,6 +132,7 @@ function resolveWasmConfig(overrides) {
|
|
|
131
132
|
glueCodeSimdPath: pickPath("glueCodeSimdPath", overrides, glueCodeSimdDefault),
|
|
132
133
|
modelsBasePath: pickPath("modelsBasePath", overrides, modelsDefault),
|
|
133
134
|
useSimd: overrides.useSimd,
|
|
135
|
+
showLogs: overrides.showLogs,
|
|
134
136
|
pipelines: overrides.pipelines,
|
|
135
137
|
pipelineModels: overrides.pipelineModels,
|
|
136
138
|
modelUrls: overrides.modelUrls,
|
|
@@ -142,970 +144,961 @@ function resolveWasmConfig(overrides) {
|
|
|
142
144
|
validateWasmPaths(merged);
|
|
143
145
|
return merged;
|
|
144
146
|
}
|
|
147
|
+
/** Hard cap per log message, UTF-8 bytes (contract). */
|
|
148
|
+
const MESSAGE_MAX_BYTES = 8 * 1024;
|
|
149
|
+
const TRUESIGHT_SDK_ID = "IncdOnboarding";
|
|
150
|
+
/** localStorage key prefix for persisted sealed snapshots (A3: one slot per session). */
|
|
151
|
+
const PENDING_STORAGE_KEY_PREFIX = "incode.truesight.pending.";
|
|
145
152
|
//#endregion
|
|
146
|
-
//#region
|
|
147
|
-
var FetchHttpError = class extends Error {
|
|
148
|
-
constructor(status, statusText, url, method, headers, data) {
|
|
149
|
-
super(`HTTP ${status} ${statusText}`);
|
|
150
|
-
this.ok = false;
|
|
151
|
-
this.status = status;
|
|
152
|
-
this.statusText = statusText;
|
|
153
|
-
this.url = url;
|
|
154
|
-
this.method = method;
|
|
155
|
-
this.headers = headers;
|
|
156
|
-
this.data = data;
|
|
157
|
-
this.name = "FetchHttpError";
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
const buildQueryString$1 = (query) => {
|
|
161
|
-
if (!query) return "";
|
|
162
|
-
const params = new URLSearchParams();
|
|
163
|
-
Object.entries(query).forEach(([key, value]) => {
|
|
164
|
-
if (value !== void 0 && value !== null) params.append(key, String(value));
|
|
165
|
-
});
|
|
166
|
-
const str = params.toString();
|
|
167
|
-
return str ? `?${str}` : "";
|
|
168
|
-
};
|
|
169
|
-
const buildUrl$1 = (baseURL, url, query) => {
|
|
170
|
-
const queryString = buildQueryString$1(query);
|
|
171
|
-
if (url.startsWith("http://") || url.startsWith("https://")) return `${url}${queryString}`;
|
|
172
|
-
return `${baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL}${url.startsWith("/") ? url : `/${url}`}${queryString}`;
|
|
173
|
-
};
|
|
174
|
-
const prepareBody$1 = (body) => {
|
|
175
|
-
if (body === null || body === void 0) return null;
|
|
176
|
-
if (body instanceof FormData || body instanceof Blob || body instanceof ArrayBuffer) return body;
|
|
177
|
-
if (typeof body === "object") return JSON.stringify(body);
|
|
178
|
-
return String(body);
|
|
179
|
-
};
|
|
180
|
-
const parseResponse = async (response, parseType) => {
|
|
181
|
-
if (parseType === "response") return response;
|
|
182
|
-
if (parseType === "blob") return await response.blob();
|
|
183
|
-
if (parseType === "arrayBuffer") return await response.arrayBuffer();
|
|
184
|
-
if (parseType === "text") return await response.text();
|
|
185
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
186
|
-
if (parseType === "json" || contentType.includes("application/json")) {
|
|
187
|
-
const raw = await response.text();
|
|
188
|
-
if (raw.length === 0) return "";
|
|
189
|
-
try {
|
|
190
|
-
return JSON.parse(raw);
|
|
191
|
-
} catch {
|
|
192
|
-
return raw;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
return await response.text();
|
|
196
|
-
};
|
|
197
|
-
const requestWithXHR = (fullUrl, method, mergedHeaders, requestBody, timeout, signal, onUploadProgress) => {
|
|
198
|
-
return new Promise((resolve, reject) => {
|
|
199
|
-
const xhr = new XMLHttpRequest();
|
|
200
|
-
xhr.open(method, fullUrl, true);
|
|
201
|
-
Object.entries(mergedHeaders).forEach(([key, value]) => {
|
|
202
|
-
xhr.setRequestHeader(key, value);
|
|
203
|
-
});
|
|
204
|
-
xhr.timeout = timeout;
|
|
205
|
-
xhr.upload.onprogress = (event) => {
|
|
206
|
-
if (event.lengthComputable) {
|
|
207
|
-
const percentComplete = event.loaded / event.total * 100;
|
|
208
|
-
onUploadProgress(Math.round(percentComplete));
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
xhr.onload = () => {
|
|
212
|
-
const responseHeaders = {};
|
|
213
|
-
xhr.getAllResponseHeaders().split("\r\n").forEach((line) => {
|
|
214
|
-
const parts = line.split(": ");
|
|
215
|
-
if (parts.length === 2) responseHeaders[parts[0].toLowerCase()] = parts[1];
|
|
216
|
-
});
|
|
217
|
-
let data;
|
|
218
|
-
try {
|
|
219
|
-
if ((xhr.getResponseHeader("content-type") ?? "").includes("application/json")) data = JSON.parse(xhr.responseText);
|
|
220
|
-
else data = xhr.responseText;
|
|
221
|
-
} catch {
|
|
222
|
-
data = xhr.responseText;
|
|
223
|
-
}
|
|
224
|
-
if (xhr.status >= 200 && xhr.status < 300) resolve({
|
|
225
|
-
ok: true,
|
|
226
|
-
status: xhr.status,
|
|
227
|
-
statusText: xhr.statusText,
|
|
228
|
-
url: fullUrl,
|
|
229
|
-
headers: responseHeaders,
|
|
230
|
-
data
|
|
231
|
-
});
|
|
232
|
-
else reject(new FetchHttpError(xhr.status, xhr.statusText, fullUrl, method, responseHeaders, data));
|
|
233
|
-
};
|
|
234
|
-
xhr.onerror = () => {
|
|
235
|
-
reject(new FetchHttpError(0, "Network Error", fullUrl, method, {}, null));
|
|
236
|
-
};
|
|
237
|
-
xhr.ontimeout = () => {
|
|
238
|
-
reject(new FetchHttpError(0, "Request timeout", fullUrl, method, {}, null));
|
|
239
|
-
};
|
|
240
|
-
if (signal) signal.addEventListener("abort", () => {
|
|
241
|
-
xhr.abort();
|
|
242
|
-
reject(new FetchHttpError(0, "Request aborted", fullUrl, method, {}, null));
|
|
243
|
-
});
|
|
244
|
-
xhr.send(requestBody);
|
|
245
|
-
});
|
|
246
|
-
};
|
|
247
|
-
const createApi = (config) => {
|
|
248
|
-
const headers = {
|
|
249
|
-
"Content-Type": "application/json",
|
|
250
|
-
Accept: "application/json",
|
|
251
|
-
"api-version": "1.0",
|
|
252
|
-
...config.customHeaders ?? {}
|
|
253
|
-
};
|
|
254
|
-
const defaults = {
|
|
255
|
-
baseURL: config.apiURL,
|
|
256
|
-
headers
|
|
257
|
-
};
|
|
258
|
-
const client = {
|
|
259
|
-
defaults,
|
|
260
|
-
async request(requestConfig) {
|
|
261
|
-
const { method = "GET", url, headers = {}, query, params, body, signal, timeout: timeoutOverride, parse, onUploadProgress, keepalive } = requestConfig;
|
|
262
|
-
const fullUrl = buildUrl$1(defaults.baseURL, url, params ?? query);
|
|
263
|
-
const mergedHeaders = {
|
|
264
|
-
...defaults.headers,
|
|
265
|
-
...headers
|
|
266
|
-
};
|
|
267
|
-
const requestBody = prepareBody$1(body);
|
|
268
|
-
const timeout = timeoutOverride ?? config.timeout;
|
|
269
|
-
let finalHeaders = mergedHeaders;
|
|
270
|
-
if (requestBody === null && (method === "POST" || method === "PUT" || method === "PATCH")) {
|
|
271
|
-
const { "Content-Type": _, ...headersWithoutContentType } = mergedHeaders;
|
|
272
|
-
finalHeaders = headersWithoutContentType;
|
|
273
|
-
}
|
|
274
|
-
if (onUploadProgress) {
|
|
275
|
-
if (requestBody !== null && typeof ReadableStream !== "undefined" && requestBody instanceof ReadableStream) throw new Error("Upload progress tracking is not supported for ReadableStream bodies");
|
|
276
|
-
return requestWithXHR(fullUrl, method, finalHeaders, requestBody, timeout ?? 0, signal, onUploadProgress);
|
|
277
|
-
}
|
|
278
|
-
const controller = new AbortController();
|
|
279
|
-
if (signal) if (signal.aborted) controller.abort();
|
|
280
|
-
else signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
281
|
-
const abortSignal = controller.signal;
|
|
282
|
-
const timeoutId = timeout === void 0 ? void 0 : setTimeout(() => controller.abort(), timeout);
|
|
283
|
-
try {
|
|
284
|
-
const response = await fetch(fullUrl, {
|
|
285
|
-
method,
|
|
286
|
-
headers: finalHeaders,
|
|
287
|
-
body: requestBody,
|
|
288
|
-
signal: abortSignal,
|
|
289
|
-
keepalive
|
|
290
|
-
});
|
|
291
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
292
|
-
const responseHeaders = {};
|
|
293
|
-
response.headers.forEach((value, key) => {
|
|
294
|
-
responseHeaders[key] = value;
|
|
295
|
-
});
|
|
296
|
-
const data = await parseResponse(response, parse);
|
|
297
|
-
if (!response.ok) throw new FetchHttpError(response.status, response.statusText, fullUrl, method, responseHeaders, data);
|
|
298
|
-
return {
|
|
299
|
-
ok: true,
|
|
300
|
-
status: response.status,
|
|
301
|
-
statusText: response.statusText,
|
|
302
|
-
url: fullUrl,
|
|
303
|
-
headers: responseHeaders,
|
|
304
|
-
data
|
|
305
|
-
};
|
|
306
|
-
} catch (error) {
|
|
307
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
308
|
-
if (error instanceof FetchHttpError) throw error;
|
|
309
|
-
if (error instanceof Error && error.name === "AbortError") throw new FetchHttpError(0, "Request timeout", fullUrl, method, {}, null);
|
|
310
|
-
throw error;
|
|
311
|
-
}
|
|
312
|
-
},
|
|
313
|
-
get(url, config) {
|
|
314
|
-
return client.request({
|
|
315
|
-
...config,
|
|
316
|
-
url,
|
|
317
|
-
method: "GET"
|
|
318
|
-
});
|
|
319
|
-
},
|
|
320
|
-
post(url, body, config) {
|
|
321
|
-
return client.request({
|
|
322
|
-
...config,
|
|
323
|
-
url,
|
|
324
|
-
body,
|
|
325
|
-
method: "POST"
|
|
326
|
-
});
|
|
327
|
-
},
|
|
328
|
-
put(url, body, config) {
|
|
329
|
-
return client.request({
|
|
330
|
-
...config,
|
|
331
|
-
url,
|
|
332
|
-
body,
|
|
333
|
-
method: "PUT"
|
|
334
|
-
});
|
|
335
|
-
},
|
|
336
|
-
patch(url, body, config) {
|
|
337
|
-
return client.request({
|
|
338
|
-
...config,
|
|
339
|
-
url,
|
|
340
|
-
body,
|
|
341
|
-
method: "PATCH"
|
|
342
|
-
});
|
|
343
|
-
},
|
|
344
|
-
delete(url, config) {
|
|
345
|
-
return client.request({
|
|
346
|
-
...config,
|
|
347
|
-
url,
|
|
348
|
-
method: "DELETE"
|
|
349
|
-
});
|
|
350
|
-
},
|
|
351
|
-
head(url, config) {
|
|
352
|
-
return client.request({
|
|
353
|
-
...config,
|
|
354
|
-
url,
|
|
355
|
-
method: "HEAD"
|
|
356
|
-
});
|
|
357
|
-
},
|
|
358
|
-
options(url, config) {
|
|
359
|
-
return client.request({
|
|
360
|
-
...config,
|
|
361
|
-
url,
|
|
362
|
-
method: "OPTIONS"
|
|
363
|
-
});
|
|
364
|
-
},
|
|
365
|
-
setHeader(name, value) {
|
|
366
|
-
defaults.headers[name] = value;
|
|
367
|
-
}
|
|
368
|
-
};
|
|
369
|
-
return client;
|
|
370
|
-
};
|
|
371
|
-
//#endregion
|
|
372
|
-
//#region ../infra/src/http/createWasmApi.ts
|
|
373
|
-
const WASM_TIMEOUT_CEILING_MS = 36e5;
|
|
374
|
-
const RSA_OAEP_SHA256_SCHEME = "RSA/NONE/OAEPWITHSHA-256ANDMGF1PADDING";
|
|
153
|
+
//#region src/internal/trueSight/sanitize.ts
|
|
375
154
|
/**
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
155
|
+
* Deny-by-default message scrubber — runs at INGESTION (inside the log buffer's
|
|
156
|
+
* `append`), so the buffer, every persisted snapshot, and every upload are
|
|
157
|
+
* already clean; there is no code path around it (ENG-48677 plan §1.2).
|
|
158
|
+
*
|
|
159
|
+
* Ordered pipeline. Two deliberate deviations from the plan's original rule
|
|
160
|
+
* order, both from the P1-A adversarial review (2026-07-23, recorded in the
|
|
161
|
+
* plan's Operating-decisions section):
|
|
162
|
+
* - Inputs are pre-clamped to 2× the message cap BEFORE any regex runs — the
|
|
163
|
+
* unanchored patterns are quadratic on pathological non-matching runs
|
|
164
|
+
* (measured ~4.5 s on a 100 KB run), so regex cost must be bounded first.
|
|
165
|
+
* The final 8 KB cap still runs last.
|
|
166
|
+
* - The base64-blob rule runs BEFORE the digit-run rule — a digit run inside a
|
|
167
|
+
* blob would otherwise split it into sub-64-char fragments that escape
|
|
168
|
+
* redaction.
|
|
169
|
+
*
|
|
170
|
+
* The regex table ships in the P1-A PR description for privacy sign-off (see
|
|
171
|
+
* .agents/guides/privacy.md). Known hardening backlog (D4, Phase 4): formatted
|
|
172
|
+
* phone numbers, unicode digits/emails, fuzz/property tests.
|
|
379
173
|
*/
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
174
|
+
/** Three dot-joined base64url segments — JWT/JWS shape. */
|
|
175
|
+
const JWT_PATTERN = /\b[\w-]{8,}\.[\w-]{8,}\.[\w-]{8,}\b/g;
|
|
176
|
+
/**
|
|
177
|
+
* Credential-ish key with a `:`/`=` value (quoted, `Bearer …`, or bare token).
|
|
178
|
+
* The key may carry prefixes (`access_token`, `x-api-key`, `sessionToken`) —
|
|
179
|
+
* a plain \b boundary would miss `_token` since `_` is a word character.
|
|
180
|
+
*/
|
|
181
|
+
const CREDENTIAL_KV_PATTERN = /([\w-]*(?:token|api[-_]?key|authorization|auth|secret|password|passwd))\s*[:=]\s*("[^"]*"|'[^']*'|(?:Bearer\s+)?[^\s,;&]+)/gi;
|
|
182
|
+
/** Userinfo credentials in an absolute URL (`https://user:pass@host/…`). */
|
|
183
|
+
const URL_USERINFO_PATTERN = /(\bhttps?:\/\/)[^\s/@]*(?::[^\s/@]*)?@/gi;
|
|
184
|
+
/** Query string / fragment of an absolute URL — kills signed URLs. */
|
|
185
|
+
const URL_TAIL_PATTERN = /(https?:\/\/[^\s?#]+)[?#][^\s]*/g;
|
|
186
|
+
const EMAIL_PATTERN = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
|
|
187
|
+
/** base64-ish blobs (media, keys) — 64+ chars of the base64/base64url alphabet. */
|
|
188
|
+
const BASE64_BLOB_PATTERN = /[-A-Za-z0-9+/_]{64,}={0,2}/g;
|
|
189
|
+
/** Runs of 8+ digits — phones, CURP, document numbers. */
|
|
190
|
+
const DIGIT_RUN_PATTERN = /\d{8,}/g;
|
|
191
|
+
const TRUNCATION_SUFFIX = "…[truncated]";
|
|
192
|
+
/** Regex-cost bound: clamp raw input before any pattern runs (see header note). */
|
|
193
|
+
const REGEX_INPUT_MAX_BYTES = MESSAGE_MAX_BYTES * 2;
|
|
194
|
+
function sanitizeMessage(message) {
|
|
195
|
+
return truncateUtf8(truncateUtf8(message, REGEX_INPUT_MAX_BYTES).replace(JWT_PATTERN, "[jwt]").replace(CREDENTIAL_KV_PATTERN, "$1=[redacted]").replace(URL_USERINFO_PATTERN, "$1[redacted]@").replace(URL_TAIL_PATTERN, "$1").replace(EMAIL_PATTERN, "[email]").replace(BASE64_BLOB_PATTERN, (match) => `[blob:${match.length}]`).replace(DIGIT_RUN_PATTERN, "[digits]"), MESSAGE_MAX_BYTES);
|
|
387
196
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
if (
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
return str ? `?${str}` : "";
|
|
416
|
-
};
|
|
417
|
-
const buildUrl = (baseURL, url, query) => {
|
|
418
|
-
const queryString = buildQueryString(query);
|
|
419
|
-
if (url.startsWith("http://") || url.startsWith("https://")) return `${url}${queryString}`;
|
|
420
|
-
return `${baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL}${url.startsWith("/") ? url : `/${url}`}${queryString}`;
|
|
421
|
-
};
|
|
422
|
-
const prepareBody = (body) => {
|
|
423
|
-
if (body === null || body === void 0) return void 0;
|
|
424
|
-
if (body instanceof FormData || body instanceof Blob || body instanceof ArrayBuffer || body instanceof Uint8Array || typeof body === "string") return body;
|
|
425
|
-
if (typeof body === "object") return body;
|
|
426
|
-
return String(body);
|
|
427
|
-
};
|
|
428
|
-
const normalizeMethod = (method) => {
|
|
429
|
-
const upper = method.toUpperCase();
|
|
430
|
-
if (!HTTP_METHODS.has(upper)) throw new Error(`Unsupported HTTP method for WASM client: ${method}`);
|
|
431
|
-
return upper;
|
|
432
|
-
};
|
|
433
|
-
const getErrorStatus = (error) => {
|
|
434
|
-
if (error instanceof WasmWebClientError) return error.statusCode;
|
|
435
|
-
if (typeof error === "object" && error !== null) {
|
|
436
|
-
const record = error;
|
|
437
|
-
if (typeof record.statusCode === "number") return record.statusCode;
|
|
438
|
-
if (typeof record.status === "number") return record.status;
|
|
197
|
+
/**
|
|
198
|
+
* UTF-8 byte length without TextEncoder (banned browser global in L1 —
|
|
199
|
+
* see the no-browser-api-in-core lint rule). Counts by code point.
|
|
200
|
+
*/
|
|
201
|
+
function utf8ByteLength(value) {
|
|
202
|
+
let bytes = 0;
|
|
203
|
+
for (const char of value) bytes += codePointByteLength(char);
|
|
204
|
+
return bytes;
|
|
205
|
+
}
|
|
206
|
+
function codePointByteLength(char) {
|
|
207
|
+
const codePoint = char.codePointAt(0) ?? 0;
|
|
208
|
+
if (codePoint < 128) return 1;
|
|
209
|
+
if (codePoint < 2048) return 2;
|
|
210
|
+
if (codePoint < 65536) return 3;
|
|
211
|
+
return 4;
|
|
212
|
+
}
|
|
213
|
+
/** Cuts on a code-point boundary so no surrogate half ever reaches the wire. */
|
|
214
|
+
function truncateUtf8(value, maxBytes) {
|
|
215
|
+
if (utf8ByteLength(value) <= maxBytes) return value;
|
|
216
|
+
const budget = maxBytes - utf8ByteLength(TRUNCATION_SUFFIX);
|
|
217
|
+
let bytes = 0;
|
|
218
|
+
let result = "";
|
|
219
|
+
for (const char of value) {
|
|
220
|
+
const charBytes = codePointByteLength(char);
|
|
221
|
+
if (bytes + charBytes > budget) break;
|
|
222
|
+
bytes += charBytes;
|
|
223
|
+
result += char;
|
|
439
224
|
}
|
|
440
|
-
return
|
|
441
|
-
}
|
|
442
|
-
const getErrorData = (error) => {
|
|
443
|
-
if (error instanceof WasmWebClientError) return error.response?.data ?? null;
|
|
444
|
-
return null;
|
|
445
|
-
};
|
|
446
|
-
const getErrorMessage = (error) => {
|
|
447
|
-
if (error instanceof Error) return error.message;
|
|
448
|
-
return "WasmWebClient request failed";
|
|
449
|
-
};
|
|
450
|
-
const withAbortSignal = async (promise, signal, error) => {
|
|
451
|
-
if (!signal) return await promise;
|
|
452
|
-
if (signal.aborted) throw error;
|
|
453
|
-
return await new Promise((resolve, reject) => {
|
|
454
|
-
const onAbort = () => reject(error);
|
|
455
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
456
|
-
promise.then(resolve, reject).finally(() => {
|
|
457
|
-
signal.removeEventListener("abort", onAbort);
|
|
458
|
-
});
|
|
459
|
-
});
|
|
460
|
-
};
|
|
461
|
-
const createWasmApi = async (config) => {
|
|
462
|
-
const headers = buildWasmDefaultHeaders(config.customHeaders);
|
|
463
|
-
const isEncryptionEnabled = config.isEncryptionEnabled ?? (() => false);
|
|
464
|
-
const useSha256 = config.mgf1 === "sha256";
|
|
465
|
-
await initializeWasmWebClient(config.wasm);
|
|
466
|
-
await setupWasmConnection(config.apiURL, "", config.encryptionEnabled ?? false, headers, useSha256);
|
|
467
|
-
const defaults = {
|
|
468
|
-
baseURL: config.apiURL,
|
|
469
|
-
headers
|
|
470
|
-
};
|
|
471
|
-
const client = {
|
|
472
|
-
defaults,
|
|
473
|
-
async request(requestConfig) {
|
|
474
|
-
const { method = "GET", url, headers: requestHeaders = {}, query, params, body, signal, timeout: timeoutOverride, onUploadProgress, ie = false } = requestConfig;
|
|
475
|
-
const upperMethod = normalizeMethod(method);
|
|
476
|
-
const requestParams = params ?? query;
|
|
477
|
-
const fullUrl = buildUrl(defaults.baseURL, url, requestParams);
|
|
478
|
-
const needsSchemeHeader = useSha256 && isEncryptionEnabled();
|
|
479
|
-
const mergedHeaders = {
|
|
480
|
-
...defaults.headers,
|
|
481
|
-
...needsSchemeHeader ? { "X-RSA-Encryption-Scheme": RSA_OAEP_SHA256_SCHEME } : {},
|
|
482
|
-
...requestHeaders
|
|
483
|
-
};
|
|
484
|
-
const requestBody = prepareBody(body);
|
|
485
|
-
const timeout = timeoutOverride ?? config.timeout ?? WASM_TIMEOUT_CEILING_MS;
|
|
486
|
-
const wasmProgress = onUploadProgress ? (progress) => {
|
|
487
|
-
if (progress.total > 0) onUploadProgress(Math.round(progress.loaded / progress.total * 100));
|
|
488
|
-
} : void 0;
|
|
489
|
-
const abortError = new WasmHttpError(0, "Request aborted", fullUrl, upperMethod, {}, null);
|
|
490
|
-
if (signal?.aborted) throw abortError;
|
|
491
|
-
try {
|
|
492
|
-
const response = await withAbortSignal(executeWasmRequest(upperMethod, url, requestBody, mergedHeaders, requestParams, timeout, wasmProgress, ie), signal, abortError);
|
|
493
|
-
if (response.status < 200 || response.status >= 300) throw new WasmHttpError(response.status, "", fullUrl, upperMethod, {}, response.data);
|
|
494
|
-
return {
|
|
495
|
-
ok: true,
|
|
496
|
-
status: response.status,
|
|
497
|
-
statusText: "",
|
|
498
|
-
url: fullUrl,
|
|
499
|
-
headers: {},
|
|
500
|
-
data: response.data
|
|
501
|
-
};
|
|
502
|
-
} catch (error) {
|
|
503
|
-
if (error instanceof WasmHttpError) throw error;
|
|
504
|
-
throw new WasmHttpError(getErrorStatus(error), getErrorMessage(error), fullUrl, upperMethod, {}, getErrorData(error));
|
|
505
|
-
}
|
|
506
|
-
},
|
|
507
|
-
get(url, requestConfig) {
|
|
508
|
-
return client.request({
|
|
509
|
-
...requestConfig,
|
|
510
|
-
url,
|
|
511
|
-
method: "GET"
|
|
512
|
-
});
|
|
513
|
-
},
|
|
514
|
-
post(url, body, requestConfig) {
|
|
515
|
-
return client.request({
|
|
516
|
-
...requestConfig,
|
|
517
|
-
url,
|
|
518
|
-
body,
|
|
519
|
-
method: "POST"
|
|
520
|
-
});
|
|
521
|
-
},
|
|
522
|
-
put(url, body, requestConfig) {
|
|
523
|
-
return client.request({
|
|
524
|
-
...requestConfig,
|
|
525
|
-
url,
|
|
526
|
-
body,
|
|
527
|
-
method: "PUT"
|
|
528
|
-
});
|
|
529
|
-
},
|
|
530
|
-
patch(url, body, requestConfig) {
|
|
531
|
-
return client.request({
|
|
532
|
-
...requestConfig,
|
|
533
|
-
url,
|
|
534
|
-
body,
|
|
535
|
-
method: "PATCH"
|
|
536
|
-
});
|
|
537
|
-
},
|
|
538
|
-
delete(url, requestConfig) {
|
|
539
|
-
return client.request({
|
|
540
|
-
...requestConfig,
|
|
541
|
-
url,
|
|
542
|
-
method: "DELETE"
|
|
543
|
-
});
|
|
544
|
-
},
|
|
545
|
-
head() {
|
|
546
|
-
return Promise.reject(/* @__PURE__ */ new Error("HEAD is not supported by the WASM HTTP client"));
|
|
547
|
-
},
|
|
548
|
-
options() {
|
|
549
|
-
return Promise.reject(/* @__PURE__ */ new Error("OPTIONS is not supported by the WASM HTTP client"));
|
|
550
|
-
},
|
|
551
|
-
setHeader(name, value) {
|
|
552
|
-
defaults.headers[name] = value;
|
|
553
|
-
}
|
|
554
|
-
};
|
|
555
|
-
return client;
|
|
556
|
-
};
|
|
225
|
+
return result + TRUNCATION_SUFFIX;
|
|
226
|
+
}
|
|
557
227
|
//#endregion
|
|
558
|
-
//#region src/
|
|
228
|
+
//#region ../infra/src/crypto/randomUUID.ts
|
|
559
229
|
/**
|
|
560
|
-
*
|
|
561
|
-
* adapter. Lets the on-device face-results POST flow through the same
|
|
562
|
-
* `httpClient.request()` pipeline as every other endpoint — header
|
|
563
|
-
* injection, encryption-state handling, default headers, timeout — instead
|
|
564
|
-
* of bypassing it via `executeWasmRequest` directly.
|
|
230
|
+
* Cryptographically-strong UUID v4 (RFC 4122).
|
|
565
231
|
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
* host called `setup()` without `wasm` and warmed WASM separately), swap to
|
|
571
|
-
* the WASM client first. The module is already loaded — the payload came
|
|
572
|
-
* out of it — so the swap only creates the `WebClient`.
|
|
232
|
+
* Lives in infra (L0) so Core (L1) can mint secure identifiers without touching
|
|
233
|
+
* the `crypto` browser API directly — Core delegates here, keeping it free of
|
|
234
|
+
* browser globals (enforced by the `no-browser-api-in-core` lint rule). Backed
|
|
235
|
+
* by `crypto.randomUUID`, available in every browser the SDK targets.
|
|
573
236
|
*/
|
|
574
|
-
function
|
|
575
|
-
return
|
|
576
|
-
const response = await (config.ie === true && storedHttpConfig && !storedHttpConfig.isWasm ? await ensureWasmHttpClient() : client).request({
|
|
577
|
-
method: "POST",
|
|
578
|
-
url,
|
|
579
|
-
body,
|
|
580
|
-
headers: config.headers,
|
|
581
|
-
params: config.params,
|
|
582
|
-
timeout: config.timeout,
|
|
583
|
-
ie: config.ie
|
|
584
|
-
});
|
|
585
|
-
return {
|
|
586
|
-
data: response.data,
|
|
587
|
-
status: response.status
|
|
588
|
-
};
|
|
589
|
-
};
|
|
237
|
+
function randomUUID() {
|
|
238
|
+
return crypto.randomUUID();
|
|
590
239
|
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region ../infra/src/time/epochMsToIsoString.ts
|
|
242
|
+
/**
|
|
243
|
+
* Converts an epoch-milliseconds timestamp to a full ISO-8601 UTC string
|
|
244
|
+
* (e.g. `2026-07-23T09:41:00.000Z`).
|
|
245
|
+
*
|
|
246
|
+
* Lives in Infra (L0) so Core can format wire timestamps without touching the
|
|
247
|
+
* `Date` global directly — banned in Core by the `no-browser-api-in-core` lint
|
|
248
|
+
* rule — mirroring the `crypto/randomUUID.ts` free-function precedent.
|
|
249
|
+
* (`DateFormattingProvider.utcToIsoDateString` is date-only and not suitable.)
|
|
250
|
+
*/
|
|
251
|
+
function epochMsToIsoString(epochMs) {
|
|
252
|
+
return new Date(epochMs).toISOString();
|
|
594
253
|
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
254
|
+
//#endregion
|
|
255
|
+
//#region src/internal/trueSight/recordBuilder.ts
|
|
256
|
+
/**
|
|
257
|
+
* Assembles the exact plaintext contract record — the ONLY place a diagnostics
|
|
258
|
+
* payload is shaped. Pure: same function serves final records, interrupted
|
|
259
|
+
* snapshots, and future incremental slices (ENG-48677 plan §1.1).
|
|
260
|
+
*
|
|
261
|
+
* Deny-by-default is structural here: every field is an explicit literal —
|
|
262
|
+
* nothing is spread from internal state, so no unexpected field can ever leak
|
|
263
|
+
* into an upload.
|
|
264
|
+
*
|
|
265
|
+
* Hard gates enforced:
|
|
266
|
+
* - empty/missing `sessionId` or `startedAt` → returns `null` (upload skipped —
|
|
267
|
+
* expected for sessions that die before `/omni/start`).
|
|
268
|
+
* - `failureReason` present if-and-only-if `outcome === 'failure'` (defaults to
|
|
269
|
+
* `'unknown'` when a failure arrives without one, rather than dropping the record).
|
|
270
|
+
* - fresh record `id` per build; `endedAt` stamped at build time.
|
|
271
|
+
*/
|
|
272
|
+
function buildDiagnosticsRecord(meta, logs, outcome, failureReason, recordId) {
|
|
273
|
+
if (!meta.sessionId || meta.startedAtMs === null) return null;
|
|
274
|
+
const flowType = meta.flowType ?? deriveFlowTypeFromSurface(meta.integrationType);
|
|
275
|
+
if (flowType === null) return null;
|
|
276
|
+
return {
|
|
277
|
+
schemaVersion: "1.0",
|
|
278
|
+
id: recordId ?? randomUUID(),
|
|
279
|
+
session: {
|
|
280
|
+
sessionId: meta.sessionId,
|
|
281
|
+
sdkId: TRUESIGHT_SDK_ID,
|
|
282
|
+
sdkVersion: SDK_VERSION,
|
|
283
|
+
platform: "web",
|
|
284
|
+
sdkMode: null,
|
|
285
|
+
browser: meta.browser,
|
|
286
|
+
osVersion: meta.osVersion,
|
|
287
|
+
osLanguage: meta.osLanguage,
|
|
288
|
+
sdkLanguage: meta.sdkLanguage,
|
|
289
|
+
integrationType: meta.integrationType,
|
|
290
|
+
flowType,
|
|
291
|
+
flowId: meta.flowId,
|
|
292
|
+
workflowId: meta.workflowId,
|
|
293
|
+
outcome,
|
|
294
|
+
...outcome === "failure" ? { failureReason: failureReason ?? "unknown" } : {},
|
|
295
|
+
startedAt: epochMsToIsoString(meta.startedAtMs),
|
|
296
|
+
endedAt: epochMsToIsoString(getTimestamp()),
|
|
297
|
+
testing: meta.testing,
|
|
298
|
+
e2eEncryptionEnabled: meta.e2eEncryptionEnabled,
|
|
299
|
+
configurationId: meta.hasConfigurationId,
|
|
300
|
+
externalCustomerId: meta.hasExternalCustomerId,
|
|
301
|
+
hasProvidedSessionId: meta.hasProvidedSessionId,
|
|
302
|
+
token: meta.hasToken,
|
|
303
|
+
externalToken: meta.hasExternalToken
|
|
304
|
+
},
|
|
305
|
+
logs: logs.map(toContractEntry)
|
|
306
|
+
};
|
|
598
307
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
308
|
+
/**
|
|
309
|
+
* Wire `flowType` when no orchestrator was OBSERVED (an observed one — set by
|
|
310
|
+
* the bridge on any flow event — always wins). Stage ingest requires a
|
|
311
|
+
* non-null enum (probe 2026-07-23: null/omitted/off-enum all 400), so the
|
|
312
|
+
* entry surface decides, and the mapping is deliberately exhaustive:
|
|
313
|
+
*
|
|
314
|
+
* - `startWorkflow` → 'workflow' (Webflows engine entered, died pre-ready)
|
|
315
|
+
* - `startFlow` → 'flow' (flow/orchestrated manager, died pre-ready)
|
|
316
|
+
* - `startOnboarding`→ 'flow' (self-loading UI wraps the flow engine)
|
|
317
|
+
* - `startOnboardingSection` → null → the BUILD ABORTS (record withheld):
|
|
318
|
+
* a standalone session has no truthful flowType, and mislabeling it as a
|
|
319
|
+
* flow session is worse than skipping the upload. Withheld until the
|
|
320
|
+
* DECIDED BE ask ships (`flowType:"standalone"`, not nullable) — then this
|
|
321
|
+
* branch returns 'standalone' and standalone diagnostics start flowing,
|
|
322
|
+
* coordinated with the BE deploy since off-enum values 400 today.
|
|
323
|
+
*/
|
|
324
|
+
function deriveFlowTypeFromSurface(integrationType) {
|
|
325
|
+
switch (integrationType) {
|
|
326
|
+
case "startWorkflow": return "workflow";
|
|
327
|
+
case "startFlow":
|
|
328
|
+
case "startOnboarding": return "flow";
|
|
329
|
+
case "startOnboardingSection": return null;
|
|
330
|
+
}
|
|
604
331
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
332
|
+
function toContractEntry(entry) {
|
|
333
|
+
return {
|
|
334
|
+
index: entry.index,
|
|
335
|
+
timestamp: epochMsToIsoString(entry.timestampMs),
|
|
336
|
+
level: entry.level,
|
|
337
|
+
thread: "main",
|
|
338
|
+
message: entry.message,
|
|
339
|
+
subsystem: entry.subsystem,
|
|
340
|
+
category: entry.category
|
|
341
|
+
};
|
|
608
342
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
343
|
+
function createInitialState() {
|
|
344
|
+
return {
|
|
345
|
+
sessionId: null,
|
|
346
|
+
startedAtMs: null,
|
|
347
|
+
browser: null,
|
|
348
|
+
osVersion: null,
|
|
349
|
+
osLanguage: null,
|
|
350
|
+
sdkLanguage: "en-US",
|
|
351
|
+
integrationType: "startOnboardingSection",
|
|
352
|
+
flowType: null,
|
|
353
|
+
flowId: null,
|
|
354
|
+
workflowId: null,
|
|
355
|
+
testing: false,
|
|
356
|
+
devModeSignal: void 0,
|
|
357
|
+
apiUrlSignal: void 0,
|
|
358
|
+
hasConfigurationId: false,
|
|
359
|
+
hasExternalCustomerId: false,
|
|
360
|
+
hasProvidedSessionId: false,
|
|
361
|
+
hasExternalToken: false
|
|
362
|
+
};
|
|
613
363
|
}
|
|
364
|
+
let state = createInitialState();
|
|
365
|
+
let sources = {};
|
|
366
|
+
/** Tap for `createSession` — sessionId comes from the returned `interviewId`. */
|
|
367
|
+
function noteSessionCreated(session, options = {}) {}
|
|
368
|
+
function noteEnvironment(environment) {}
|
|
614
369
|
/**
|
|
615
|
-
*
|
|
616
|
-
*
|
|
617
|
-
*
|
|
618
|
-
* is
|
|
370
|
+
* `testing` heuristic: devMode OR non-prod API host pattern. Always a boolean —
|
|
371
|
+
* the contract requires the field present on every record. Signals MERGE across
|
|
372
|
+
* calls (a later apiUrl-only call must not erase an earlier devMode signal);
|
|
373
|
+
* `testing` is recomputed from the merged pair.
|
|
619
374
|
*/
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
})) : createApi({
|
|
630
|
-
apiURL,
|
|
631
|
-
customHeaders: options.customHeaders,
|
|
632
|
-
timeout: options.timeout
|
|
633
|
-
}));
|
|
634
|
-
storedHttpConfig = {
|
|
635
|
-
apiURL,
|
|
636
|
-
customHeaders: options.customHeaders,
|
|
637
|
-
timeout: options.timeout,
|
|
638
|
-
isWasm: Boolean(effectiveWasm),
|
|
639
|
-
encryption
|
|
640
|
-
};
|
|
375
|
+
function noteTestingSignals(signals) {}
|
|
376
|
+
/**
|
|
377
|
+
* Live read of the merged testing signal (devMode OR non-prod host). Used to
|
|
378
|
+
* gate host-console self-health noise so production host pages stay quiet while
|
|
379
|
+
* staging/dev keeps the console signal (the record always captures it either
|
|
380
|
+
* way via `trueSightLog`). Same signal the overflow-flush staging gate uses.
|
|
381
|
+
*/
|
|
382
|
+
function isTrueSightTesting() {
|
|
383
|
+
return state.testing;
|
|
641
384
|
}
|
|
642
385
|
/**
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
647
|
-
* No-op when no apiURL was previously configured, or when the active client
|
|
648
|
-
* is already WASM-backed. The encryption state (enabled + MGF1 scheme) is
|
|
649
|
-
* preserved across the swap — this is *not* a user-facing encryption change.
|
|
650
|
-
*
|
|
651
|
-
* @internal NOT a public API. Application code should use
|
|
652
|
-
* `setup({ wasm: {...} })` instead.
|
|
386
|
+
* Wiring tap for every `initializeSession({ token })`: a token activated
|
|
387
|
+
* before any `createSession` was observed on this page is host-minted, i.e.
|
|
388
|
+
* external. (The exact `token`/`externalToken` web-semantics are a pending
|
|
389
|
+
* Phase 0 contract ask — this inference is the interim mapping.)
|
|
653
390
|
*/
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
391
|
+
function noteTokenActivated() {}
|
|
392
|
+
/** Explicit literal — the metadata half handed to the record builder. */
|
|
393
|
+
function buildSessionMetadata() {
|
|
394
|
+
return {
|
|
395
|
+
sessionId: state.sessionId,
|
|
396
|
+
startedAtMs: state.startedAtMs,
|
|
397
|
+
browser: state.browser,
|
|
398
|
+
osVersion: state.osVersion,
|
|
399
|
+
osLanguage: state.osLanguage,
|
|
400
|
+
sdkLanguage: state.sdkLanguage,
|
|
401
|
+
integrationType: state.integrationType,
|
|
402
|
+
flowType: state.flowType,
|
|
403
|
+
flowId: state.flowId,
|
|
404
|
+
workflowId: state.workflowId,
|
|
405
|
+
testing: state.testing,
|
|
406
|
+
e2eEncryptionEnabled: readE2eEncryptionEnabled(),
|
|
407
|
+
hasConfigurationId: state.hasConfigurationId,
|
|
408
|
+
hasExternalCustomerId: state.hasExternalCustomerId,
|
|
409
|
+
hasProvidedSessionId: state.hasProvidedSessionId,
|
|
410
|
+
hasToken: readHasToken(),
|
|
411
|
+
hasExternalToken: state.hasExternalToken
|
|
412
|
+
};
|
|
675
413
|
}
|
|
676
|
-
/**
|
|
677
|
-
|
|
678
|
-
* RSA/AES handshake so its rejection surfaces as a single, descriptive error
|
|
679
|
-
* with the original error preserved as `cause`. Pass-through otherwise.
|
|
680
|
-
*/
|
|
681
|
-
async function withHandshakeFailureContext(wantsEncryption, fn) {
|
|
682
|
-
if (!wantsEncryption) return fn();
|
|
414
|
+
/** Fail-open: diagnostics must never throw into the host flow. */
|
|
415
|
+
function readE2eEncryptionEnabled() {
|
|
683
416
|
try {
|
|
684
|
-
return
|
|
685
|
-
} catch
|
|
686
|
-
|
|
687
|
-
error.cause = cause;
|
|
688
|
-
throw error;
|
|
417
|
+
return sources.getE2eEncryptionEnabled?.() ?? false;
|
|
418
|
+
} catch {
|
|
419
|
+
return false;
|
|
689
420
|
}
|
|
690
421
|
}
|
|
691
|
-
/**
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
422
|
+
/** Fail-open, like readE2eEncryptionEnabled. */
|
|
423
|
+
function readHasToken() {
|
|
424
|
+
try {
|
|
425
|
+
return sources.getHasToken?.() ?? false;
|
|
426
|
+
} catch {
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function resetTrueSightMetadata() {
|
|
431
|
+
state = createInitialState();
|
|
432
|
+
sources = {};
|
|
433
|
+
}
|
|
696
434
|
//#endregion
|
|
697
|
-
//#region src/internal/trueSight/
|
|
435
|
+
//#region src/internal/trueSight/pendingEnvelopeStore.ts
|
|
436
|
+
/** Index slot listing sessionIds with pending entries (no enumeration API). */
|
|
437
|
+
const PENDING_INDEX_KEY = `${PENDING_STORAGE_KEY_PREFIX}index`;
|
|
438
|
+
function slotKey(sessionId) {
|
|
439
|
+
return `${PENDING_STORAGE_KEY_PREFIX}${sessionId}`;
|
|
440
|
+
}
|
|
698
441
|
/**
|
|
699
|
-
*
|
|
700
|
-
*
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
* Ordered pipeline. Two deliberate deviations from the plan's original rule
|
|
704
|
-
* order, both from the P1-A adversarial review (2026-07-23, recorded in the
|
|
705
|
-
* plan's Operating-decisions section):
|
|
706
|
-
* - Inputs are pre-clamped to 2× the message cap BEFORE any regex runs — the
|
|
707
|
-
* unanchored patterns are quadratic on pathological non-matching runs
|
|
708
|
-
* (measured ~4.5 s on a 100 KB run), so regex cost must be bounded first.
|
|
709
|
-
* The final 8 KB cap still runs last.
|
|
710
|
-
* - The base64-blob rule runs BEFORE the digit-run rule — a digit run inside a
|
|
711
|
-
* blob would otherwise split it into sub-64-char fragments that escape
|
|
712
|
-
* redaction.
|
|
713
|
-
*
|
|
714
|
-
* The regex table ships in the P1-A PR description for privacy sign-off (see
|
|
715
|
-
* .agents/guides/privacy.md). Known hardening backlog (D4, Phase 4): formatted
|
|
716
|
-
* phone numbers, unicode digits/emails, fuzz/property tests.
|
|
442
|
+
* Adds the session to the pending index. Called once at collection start —
|
|
443
|
+
* long before any page-hide — so the hide path never needs the index
|
|
444
|
+
* read-modify-write and stays a single synchronous-effective write.
|
|
717
445
|
*/
|
|
718
|
-
|
|
719
|
-
|
|
446
|
+
async function registerPendingSlot(sessionId, deps) {
|
|
447
|
+
try {
|
|
448
|
+
const index = await readIndex(deps.storage);
|
|
449
|
+
if (index.includes(sessionId)) return;
|
|
450
|
+
await deps.storage.set(PENDING_INDEX_KEY, [...index, sessionId]);
|
|
451
|
+
} catch {}
|
|
452
|
+
}
|
|
720
453
|
/**
|
|
721
|
-
*
|
|
722
|
-
*
|
|
723
|
-
*
|
|
454
|
+
* Writes the sealed snapshot into the session's slot. `BrowserStorageProvider`
|
|
455
|
+
* executes the underlying `localStorage.setItem` synchronously in the first
|
|
456
|
+
* slice of the async call, which is what makes this safe to fire (void) from
|
|
457
|
+
* a page-hide handler.
|
|
724
458
|
*/
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
const
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
const REGEX_INPUT_MAX_BYTES = MESSAGE_MAX_BYTES * 2;
|
|
738
|
-
function sanitizeMessage(message) {
|
|
739
|
-
return truncateUtf8(truncateUtf8(message, REGEX_INPUT_MAX_BYTES).replace(JWT_PATTERN, "[jwt]").replace(CREDENTIAL_KV_PATTERN, "$1=[redacted]").replace(URL_USERINFO_PATTERN, "$1[redacted]@").replace(URL_TAIL_PATTERN, "$1").replace(EMAIL_PATTERN, "[email]").replace(BASE64_BLOB_PATTERN, (match) => `[blob:${match.length}]`).replace(DIGIT_RUN_PATTERN, "[digits]"), MESSAGE_MAX_BYTES);
|
|
459
|
+
async function writePendingEnvelope(sessionId, entry, deps) {
|
|
460
|
+
try {
|
|
461
|
+
await deps.storage.set(slotKey(sessionId), entry);
|
|
462
|
+
} catch {}
|
|
463
|
+
}
|
|
464
|
+
/** Removes the entry and its index membership (terminal upload dispatched). */
|
|
465
|
+
async function clearPending(sessionId, deps) {
|
|
466
|
+
try {
|
|
467
|
+
await deps.storage.remove(slotKey(sessionId));
|
|
468
|
+
const index = await readIndex(deps.storage);
|
|
469
|
+
if (index.includes(sessionId)) await deps.storage.set(PENDING_INDEX_KEY, index.filter((candidate) => candidate !== sessionId));
|
|
470
|
+
} catch {}
|
|
740
471
|
}
|
|
741
472
|
/**
|
|
742
|
-
*
|
|
743
|
-
*
|
|
473
|
+
* Next-load recovery, invoked from the first-token-observed hook (A1 — never
|
|
474
|
+
* at `setup()`, which has no auth). For each foreign, old-enough entry: the
|
|
475
|
+
* slot is cleared AT DISPATCH, then the envelope is posted fire-and-forget —
|
|
476
|
+
* no 200-tracking, no retries (A2; a crash between clear and fire loses that
|
|
477
|
+
* record, consistent with no-retry). Entries at/past the retention ceiling
|
|
478
|
+
* are deleted unsent (A4). Never rejects; returns the A5 loss counters.
|
|
744
479
|
*/
|
|
745
|
-
function
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
480
|
+
async function recoverPendingEnvelopes(options) {
|
|
481
|
+
const { storage, post, currentSessionId } = options;
|
|
482
|
+
const now = options.now ?? getTimestamp;
|
|
483
|
+
const counters = {
|
|
484
|
+
recovered: 0,
|
|
485
|
+
gcExpired: 0
|
|
486
|
+
};
|
|
487
|
+
try {
|
|
488
|
+
const index = await readIndex(storage);
|
|
489
|
+
if (index.length === 0) return counters;
|
|
490
|
+
const keptInIndex = [];
|
|
491
|
+
for (const sessionId of index) {
|
|
492
|
+
if (sessionId === currentSessionId) {
|
|
493
|
+
keptInIndex.push(sessionId);
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
const entry = await readEntry(storage, sessionId);
|
|
497
|
+
if (entry === "missing") continue;
|
|
498
|
+
if (entry === "corrupt") {
|
|
499
|
+
counters.gcExpired += 1;
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
const age = now() - entry.persistedAt;
|
|
503
|
+
if (age >= 6048e5) {
|
|
504
|
+
counters.gcExpired += 1;
|
|
505
|
+
await storage.remove(slotKey(sessionId));
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
if (age < 12e4) {
|
|
509
|
+
keptInIndex.push(sessionId);
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
await storage.remove(slotKey(sessionId));
|
|
513
|
+
counters.recovered += 1;
|
|
514
|
+
post(endpoints.diagnosticsData, entry.envelope, {}).catch(() => {});
|
|
515
|
+
}
|
|
516
|
+
await storage.set(PENDING_INDEX_KEY, keptInIndex);
|
|
517
|
+
} catch {}
|
|
518
|
+
return counters;
|
|
749
519
|
}
|
|
750
|
-
function
|
|
751
|
-
const
|
|
752
|
-
if (
|
|
753
|
-
|
|
754
|
-
if (codePoint < 65536) return 3;
|
|
755
|
-
return 4;
|
|
520
|
+
async function readIndex(storage) {
|
|
521
|
+
const index = await storage.get(PENDING_INDEX_KEY);
|
|
522
|
+
if (!Array.isArray(index)) return [];
|
|
523
|
+
return index.filter((value) => typeof value === "string");
|
|
756
524
|
}
|
|
757
|
-
/**
|
|
758
|
-
function
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
525
|
+
/** Reads one entry; malformed slots are pruned and reported as corrupt. */
|
|
526
|
+
async function readEntry(storage, sessionId) {
|
|
527
|
+
try {
|
|
528
|
+
const value = await storage.get(slotKey(sessionId));
|
|
529
|
+
if (value === null) return "missing";
|
|
530
|
+
if (typeof value === "object" && value.v === 1 && typeof value.persistedAt === "number" && typeof value.envelope === "object") return value;
|
|
531
|
+
await storage.remove(slotKey(sessionId));
|
|
532
|
+
return "corrupt";
|
|
533
|
+
} catch {
|
|
534
|
+
try {
|
|
535
|
+
await storage.remove(slotKey(sessionId));
|
|
536
|
+
} catch {}
|
|
537
|
+
return "corrupt";
|
|
768
538
|
}
|
|
769
|
-
return result + TRUNCATION_SUFFIX;
|
|
770
539
|
}
|
|
771
540
|
//#endregion
|
|
772
|
-
//#region
|
|
541
|
+
//#region src/internal/featureConfig/featureConfigService.ts
|
|
542
|
+
let cachedFeatures = null;
|
|
773
543
|
/**
|
|
774
|
-
*
|
|
775
|
-
*
|
|
776
|
-
* Lives in infra (L0) so Core (L1) can mint secure identifiers without touching
|
|
777
|
-
* the `crypto` browser API directly — Core delegates here, keeping it free of
|
|
778
|
-
* browser globals (enforced by the `no-browser-api-in-core` lint rule). Backed
|
|
779
|
-
* by `crypto.randomUUID`, available in every browser the SDK targets.
|
|
544
|
+
* Checks if a feature is enabled in the feature config.
|
|
780
545
|
*/
|
|
781
|
-
function
|
|
782
|
-
return
|
|
546
|
+
function isFeatureEnabled(feature, features) {
|
|
547
|
+
return features?.find((f) => f.feature === feature)?.enabled ?? false;
|
|
783
548
|
}
|
|
784
|
-
//#endregion
|
|
785
|
-
//#region ../infra/src/time/epochMsToIsoString.ts
|
|
786
549
|
/**
|
|
787
|
-
*
|
|
788
|
-
*
|
|
789
|
-
*
|
|
790
|
-
* Lives in Infra (L0) so Core can format wire timestamps without touching the
|
|
791
|
-
* `Date` global directly — banned in Core by the `no-browser-api-in-core` lint
|
|
792
|
-
* rule — mirroring the `crypto/randomUUID.ts` free-function precedent.
|
|
793
|
-
* (`DateFormattingProvider.utcToIsoDateString` is date-only and not suitable.)
|
|
550
|
+
* Fetches feature configuration from the backend.
|
|
551
|
+
* Results are cached for the session lifetime.
|
|
794
552
|
*/
|
|
795
|
-
function
|
|
796
|
-
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
*
|
|
804
|
-
*
|
|
805
|
-
* Deny-by-default is structural here: every field is an explicit literal —
|
|
806
|
-
* nothing is spread from internal state, so no unexpected field can ever leak
|
|
807
|
-
* into an upload.
|
|
808
|
-
*
|
|
809
|
-
* Hard gates enforced:
|
|
810
|
-
* - empty/missing `sessionId` or `startedAt` → returns `null` (upload skipped —
|
|
811
|
-
* expected for sessions that die before `/omni/start`).
|
|
812
|
-
* - `failureReason` present if-and-only-if `outcome === 'failure'` (defaults to
|
|
813
|
-
* `'unknown'` when a failure arrives without one, rather than dropping the record).
|
|
814
|
-
* - fresh record `id` per build; `endedAt` stamped at build time.
|
|
553
|
+
async function fetchFeatureConfig(signal) {
|
|
554
|
+
if (cachedFeatures) return cachedFeatures;
|
|
555
|
+
const response = await api.get(endpoints.featureConfig, { signal });
|
|
556
|
+
if (!response.ok) throw new Error(`Failed to fetch feature config: ${response.status} ${response.statusText}`);
|
|
557
|
+
cachedFeatures = response.data;
|
|
558
|
+
return cachedFeatures;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Resets the cached feature config (useful for testing).
|
|
815
562
|
*/
|
|
816
|
-
function
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
563
|
+
function resetFeatureConfigCache() {
|
|
564
|
+
cachedFeatures = null;
|
|
565
|
+
}
|
|
566
|
+
//#endregion
|
|
567
|
+
//#region ../infra/src/http/createApi.ts
|
|
568
|
+
var FetchHttpError = class extends HttpRequestError {
|
|
569
|
+
constructor(..._args) {
|
|
570
|
+
super(..._args);
|
|
571
|
+
this.name = "FetchHttpError";
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
const buildQueryString$1 = (query) => {
|
|
575
|
+
if (!query) return "";
|
|
576
|
+
const params = new URLSearchParams();
|
|
577
|
+
Object.entries(query).forEach(([key, value]) => {
|
|
578
|
+
if (value !== void 0 && value !== null) params.append(key, String(value));
|
|
579
|
+
});
|
|
580
|
+
const str = params.toString();
|
|
581
|
+
return str ? `?${str}` : "";
|
|
582
|
+
};
|
|
583
|
+
const buildUrl$1 = (baseURL, url, query) => {
|
|
584
|
+
const queryString = buildQueryString$1(query);
|
|
585
|
+
if (url.startsWith("http://") || url.startsWith("https://")) return `${url}${queryString}`;
|
|
586
|
+
return `${baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL}${url.startsWith("/") ? url : `/${url}`}${queryString}`;
|
|
587
|
+
};
|
|
588
|
+
const prepareBody$1 = (body) => {
|
|
589
|
+
if (body === null || body === void 0) return null;
|
|
590
|
+
if (body instanceof FormData || body instanceof Blob || body instanceof ArrayBuffer) return body;
|
|
591
|
+
if (typeof body === "object") return JSON.stringify(body);
|
|
592
|
+
return String(body);
|
|
593
|
+
};
|
|
594
|
+
const parseResponse = async (response, parseType) => {
|
|
595
|
+
if (parseType === "response") return response;
|
|
596
|
+
if (parseType === "blob") return await response.blob();
|
|
597
|
+
if (parseType === "arrayBuffer") return await response.arrayBuffer();
|
|
598
|
+
if (parseType === "text") return await response.text();
|
|
599
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
600
|
+
if (parseType === "json" || contentType.includes("application/json")) {
|
|
601
|
+
const raw = await response.text();
|
|
602
|
+
if (raw.length === 0) return "";
|
|
603
|
+
try {
|
|
604
|
+
return JSON.parse(raw);
|
|
605
|
+
} catch {
|
|
606
|
+
return raw;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return await response.text();
|
|
610
|
+
};
|
|
611
|
+
const requestWithXHR = (fullUrl, method, mergedHeaders, requestBody, timeout, signal, onUploadProgress) => {
|
|
612
|
+
return new Promise((resolve, reject) => {
|
|
613
|
+
const xhr = new XMLHttpRequest();
|
|
614
|
+
xhr.open(method, fullUrl, true);
|
|
615
|
+
Object.entries(mergedHeaders).forEach(([key, value]) => {
|
|
616
|
+
xhr.setRequestHeader(key, value);
|
|
617
|
+
});
|
|
618
|
+
xhr.timeout = timeout;
|
|
619
|
+
xhr.upload.onprogress = (event) => {
|
|
620
|
+
if (event.lengthComputable) {
|
|
621
|
+
const percentComplete = event.loaded / event.total * 100;
|
|
622
|
+
onUploadProgress(Math.round(percentComplete));
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
xhr.onload = () => {
|
|
626
|
+
const responseHeaders = {};
|
|
627
|
+
xhr.getAllResponseHeaders().split("\r\n").forEach((line) => {
|
|
628
|
+
const parts = line.split(": ");
|
|
629
|
+
if (parts.length === 2) responseHeaders[parts[0].toLowerCase()] = parts[1];
|
|
630
|
+
});
|
|
631
|
+
let data;
|
|
632
|
+
try {
|
|
633
|
+
if ((xhr.getResponseHeader("content-type") ?? "").includes("application/json")) data = JSON.parse(xhr.responseText);
|
|
634
|
+
else data = xhr.responseText;
|
|
635
|
+
} catch {
|
|
636
|
+
data = xhr.responseText;
|
|
637
|
+
}
|
|
638
|
+
if (xhr.status >= 200 && xhr.status < 300) resolve({
|
|
639
|
+
ok: true,
|
|
640
|
+
status: xhr.status,
|
|
641
|
+
statusText: xhr.statusText,
|
|
642
|
+
url: fullUrl,
|
|
643
|
+
headers: responseHeaders,
|
|
644
|
+
data
|
|
645
|
+
});
|
|
646
|
+
else reject(reportHttpError(new FetchHttpError(xhr.status, xhr.statusText, fullUrl, method, responseHeaders, data), mergedHeaders));
|
|
647
|
+
};
|
|
648
|
+
xhr.onerror = () => {
|
|
649
|
+
reject(new FetchHttpError(0, "Network Error", fullUrl, method, {}, null));
|
|
650
|
+
};
|
|
651
|
+
xhr.ontimeout = () => {
|
|
652
|
+
reject(new FetchHttpError(0, "Request timeout", fullUrl, method, {}, null));
|
|
653
|
+
};
|
|
654
|
+
if (signal) signal.addEventListener("abort", () => {
|
|
655
|
+
xhr.abort();
|
|
656
|
+
reject(new FetchHttpError(0, "Request aborted", fullUrl, method, {}, null));
|
|
657
|
+
});
|
|
658
|
+
xhr.send(requestBody);
|
|
659
|
+
});
|
|
660
|
+
};
|
|
661
|
+
const createApi = (config) => {
|
|
662
|
+
const headers = {
|
|
663
|
+
"Content-Type": "application/json",
|
|
664
|
+
Accept: "application/json",
|
|
665
|
+
"api-version": "1.0",
|
|
666
|
+
...config.customHeaders ?? {}
|
|
667
|
+
};
|
|
668
|
+
const defaults = {
|
|
669
|
+
baseURL: config.apiURL,
|
|
670
|
+
headers
|
|
671
|
+
};
|
|
672
|
+
const client = {
|
|
673
|
+
defaults,
|
|
674
|
+
async request(requestConfig) {
|
|
675
|
+
const { method = "GET", url, headers = {}, query, params, body, signal, timeout: timeoutOverride, parse, onUploadProgress, keepalive } = requestConfig;
|
|
676
|
+
const fullUrl = buildUrl$1(defaults.baseURL, url, params ?? query);
|
|
677
|
+
const mergedHeaders = {
|
|
678
|
+
...defaults.headers,
|
|
679
|
+
...headers
|
|
680
|
+
};
|
|
681
|
+
const requestBody = prepareBody$1(body);
|
|
682
|
+
const timeout = timeoutOverride ?? config.timeout;
|
|
683
|
+
let finalHeaders = mergedHeaders;
|
|
684
|
+
if (requestBody === null && (method === "POST" || method === "PUT" || method === "PATCH")) {
|
|
685
|
+
const { "Content-Type": _, ...headersWithoutContentType } = mergedHeaders;
|
|
686
|
+
finalHeaders = headersWithoutContentType;
|
|
687
|
+
}
|
|
688
|
+
if (onUploadProgress) {
|
|
689
|
+
if (requestBody !== null && typeof ReadableStream !== "undefined" && requestBody instanceof ReadableStream) throw new Error("Upload progress tracking is not supported for ReadableStream bodies");
|
|
690
|
+
return requestWithXHR(fullUrl, method, finalHeaders, requestBody, timeout ?? 0, signal, onUploadProgress);
|
|
691
|
+
}
|
|
692
|
+
const controller = new AbortController();
|
|
693
|
+
if (signal) if (signal.aborted) controller.abort();
|
|
694
|
+
else signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
695
|
+
const abortSignal = controller.signal;
|
|
696
|
+
const timeoutId = timeout === void 0 ? void 0 : setTimeout(() => controller.abort(), timeout);
|
|
697
|
+
try {
|
|
698
|
+
const response = await fetch(fullUrl, {
|
|
699
|
+
method,
|
|
700
|
+
headers: finalHeaders,
|
|
701
|
+
body: requestBody,
|
|
702
|
+
signal: abortSignal,
|
|
703
|
+
keepalive
|
|
704
|
+
});
|
|
705
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
706
|
+
const responseHeaders = {};
|
|
707
|
+
response.headers.forEach((value, key) => {
|
|
708
|
+
responseHeaders[key] = value;
|
|
709
|
+
});
|
|
710
|
+
const data = await parseResponse(response, parse);
|
|
711
|
+
if (!response.ok) throw reportHttpError(new FetchHttpError(response.status, response.statusText, fullUrl, method, responseHeaders, data), mergedHeaders);
|
|
712
|
+
return {
|
|
713
|
+
ok: true,
|
|
714
|
+
status: response.status,
|
|
715
|
+
statusText: response.statusText,
|
|
716
|
+
url: fullUrl,
|
|
717
|
+
headers: responseHeaders,
|
|
718
|
+
data
|
|
719
|
+
};
|
|
720
|
+
} catch (error) {
|
|
721
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
722
|
+
if (error instanceof FetchHttpError) throw error;
|
|
723
|
+
if (error instanceof Error && error.name === "AbortError") throw new FetchHttpError(0, "Request timeout", fullUrl, method, {}, null);
|
|
724
|
+
throw error;
|
|
725
|
+
}
|
|
848
726
|
},
|
|
849
|
-
|
|
727
|
+
get(url, config) {
|
|
728
|
+
return client.request({
|
|
729
|
+
...config,
|
|
730
|
+
url,
|
|
731
|
+
method: "GET"
|
|
732
|
+
});
|
|
733
|
+
},
|
|
734
|
+
post(url, body, config) {
|
|
735
|
+
return client.request({
|
|
736
|
+
...config,
|
|
737
|
+
url,
|
|
738
|
+
body,
|
|
739
|
+
method: "POST"
|
|
740
|
+
});
|
|
741
|
+
},
|
|
742
|
+
put(url, body, config) {
|
|
743
|
+
return client.request({
|
|
744
|
+
...config,
|
|
745
|
+
url,
|
|
746
|
+
body,
|
|
747
|
+
method: "PUT"
|
|
748
|
+
});
|
|
749
|
+
},
|
|
750
|
+
patch(url, body, config) {
|
|
751
|
+
return client.request({
|
|
752
|
+
...config,
|
|
753
|
+
url,
|
|
754
|
+
body,
|
|
755
|
+
method: "PATCH"
|
|
756
|
+
});
|
|
757
|
+
},
|
|
758
|
+
delete(url, config) {
|
|
759
|
+
return client.request({
|
|
760
|
+
...config,
|
|
761
|
+
url,
|
|
762
|
+
method: "DELETE"
|
|
763
|
+
});
|
|
764
|
+
},
|
|
765
|
+
head(url, config) {
|
|
766
|
+
return client.request({
|
|
767
|
+
...config,
|
|
768
|
+
url,
|
|
769
|
+
method: "HEAD"
|
|
770
|
+
});
|
|
771
|
+
},
|
|
772
|
+
options(url, config) {
|
|
773
|
+
return client.request({
|
|
774
|
+
...config,
|
|
775
|
+
url,
|
|
776
|
+
method: "OPTIONS"
|
|
777
|
+
});
|
|
778
|
+
},
|
|
779
|
+
setHeader(name, value) {
|
|
780
|
+
defaults.headers[name] = value;
|
|
781
|
+
}
|
|
850
782
|
};
|
|
851
|
-
|
|
783
|
+
return client;
|
|
784
|
+
};
|
|
785
|
+
//#endregion
|
|
786
|
+
//#region ../infra/src/http/createWasmApi.ts
|
|
787
|
+
const WASM_TIMEOUT_CEILING_MS = 36e5;
|
|
788
|
+
const RSA_OAEP_SHA256_SCHEME = "RSA/NONE/OAEPWITHSHA-256ANDMGF1PADDING";
|
|
852
789
|
/**
|
|
853
|
-
*
|
|
854
|
-
*
|
|
855
|
-
*
|
|
856
|
-
* entry surface decides, and the mapping is deliberately exhaustive:
|
|
857
|
-
*
|
|
858
|
-
* - `startWorkflow` → 'workflow' (Webflows engine entered, died pre-ready)
|
|
859
|
-
* - `startFlow` → 'flow' (flow/orchestrated manager, died pre-ready)
|
|
860
|
-
* - `startOnboarding`→ 'flow' (self-loading UI wraps the flow engine)
|
|
861
|
-
* - `startOnboardingSection` → null → the BUILD ABORTS (record withheld):
|
|
862
|
-
* a standalone session has no truthful flowType, and mislabeling it as a
|
|
863
|
-
* flow session is worse than skipping the upload. Withheld until the
|
|
864
|
-
* DECIDED BE ask ships (`flowType:"standalone"`, not nullable) — then this
|
|
865
|
-
* branch returns 'standalone' and standalone diagnostics start flowing,
|
|
866
|
-
* coordinated with the BE deploy since off-enum values 400 today.
|
|
790
|
+
* Builds the base set of HTTP headers that the WASM WebClient sends on every
|
|
791
|
+
* request (including the internal `/e2ee/key/v2` and `/e2ee/key` handshake
|
|
792
|
+
* calls).
|
|
867
793
|
*/
|
|
868
|
-
function
|
|
869
|
-
switch (integrationType) {
|
|
870
|
-
case "startWorkflow": return "workflow";
|
|
871
|
-
case "startFlow":
|
|
872
|
-
case "startOnboarding": return "flow";
|
|
873
|
-
case "startOnboardingSection": return null;
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
function toContractEntry(entry) {
|
|
794
|
+
function buildWasmDefaultHeaders(customHeaders) {
|
|
877
795
|
return {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
message: entry.message,
|
|
883
|
-
subsystem: entry.subsystem,
|
|
884
|
-
category: entry.category
|
|
796
|
+
"Content-Type": "application/json",
|
|
797
|
+
Accept: "application/json",
|
|
798
|
+
"api-version": "1.0",
|
|
799
|
+
...customHeaders ?? {}
|
|
885
800
|
};
|
|
886
801
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
802
|
+
var WasmHttpError = class extends HttpRequestError {
|
|
803
|
+
constructor(..._args) {
|
|
804
|
+
super(..._args);
|
|
805
|
+
this.name = "WasmHttpError";
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
const HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
809
|
+
"GET",
|
|
810
|
+
"POST",
|
|
811
|
+
"PUT",
|
|
812
|
+
"PATCH",
|
|
813
|
+
"DELETE"
|
|
814
|
+
]);
|
|
815
|
+
const buildQueryString = (query) => {
|
|
816
|
+
if (!query) return "";
|
|
817
|
+
const params = new URLSearchParams();
|
|
818
|
+
Object.entries(query).forEach(([key, value]) => {
|
|
819
|
+
if (value !== void 0 && value !== null) params.append(key, String(value));
|
|
820
|
+
});
|
|
821
|
+
const str = params.toString();
|
|
822
|
+
return str ? `?${str}` : "";
|
|
823
|
+
};
|
|
824
|
+
const buildUrl = (baseURL, url, query) => {
|
|
825
|
+
const queryString = buildQueryString(query);
|
|
826
|
+
if (url.startsWith("http://") || url.startsWith("https://")) return `${url}${queryString}`;
|
|
827
|
+
return `${baseURL.endsWith("/") ? baseURL.slice(0, -1) : baseURL}${url.startsWith("/") ? url : `/${url}`}${queryString}`;
|
|
828
|
+
};
|
|
829
|
+
const prepareBody = (body) => {
|
|
830
|
+
if (body === null || body === void 0) return void 0;
|
|
831
|
+
if (body instanceof FormData || body instanceof Blob || body instanceof ArrayBuffer || body instanceof Uint8Array || typeof body === "string") return body;
|
|
832
|
+
if (typeof body === "object") return body;
|
|
833
|
+
return String(body);
|
|
834
|
+
};
|
|
835
|
+
const normalizeMethod = (method) => {
|
|
836
|
+
const upper = method.toUpperCase();
|
|
837
|
+
if (!HTTP_METHODS.has(upper)) throw new Error(`Unsupported HTTP method for WASM client: ${method}`);
|
|
838
|
+
return upper;
|
|
839
|
+
};
|
|
840
|
+
const getErrorStatus = (error) => {
|
|
841
|
+
if (error instanceof WasmWebClientError) return error.statusCode;
|
|
842
|
+
if (typeof error === "object" && error !== null) {
|
|
843
|
+
const record = error;
|
|
844
|
+
if (typeof record.statusCode === "number") return record.statusCode;
|
|
845
|
+
if (typeof record.status === "number") return record.status;
|
|
846
|
+
}
|
|
847
|
+
return 0;
|
|
848
|
+
};
|
|
849
|
+
const getErrorData = (error) => {
|
|
850
|
+
if (error instanceof WasmWebClientError) return error.response?.data ?? null;
|
|
851
|
+
return null;
|
|
852
|
+
};
|
|
853
|
+
const getErrorMessage = (error) => {
|
|
854
|
+
if (error instanceof Error) return error.message;
|
|
855
|
+
return "WasmWebClient request failed";
|
|
856
|
+
};
|
|
857
|
+
const withAbortSignal = async (promise, signal, error) => {
|
|
858
|
+
if (!signal) return await promise;
|
|
859
|
+
if (signal.aborted) throw error();
|
|
860
|
+
return await new Promise((resolve, reject) => {
|
|
861
|
+
const onAbort = () => reject(error());
|
|
862
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
863
|
+
promise.then(resolve, reject).finally(() => {
|
|
864
|
+
signal.removeEventListener("abort", onAbort);
|
|
865
|
+
});
|
|
866
|
+
});
|
|
867
|
+
};
|
|
868
|
+
const createWasmApi = async (config) => {
|
|
869
|
+
const headers = buildWasmDefaultHeaders(config.customHeaders);
|
|
870
|
+
const isEncryptionEnabled = config.isEncryptionEnabled ?? (() => false);
|
|
871
|
+
const useSha256 = config.mgf1 === "sha256";
|
|
872
|
+
await initializeWasmWebClient(config.wasm);
|
|
873
|
+
try {
|
|
874
|
+
await setupWasmConnection(config.apiURL, "", config.encryptionEnabled ?? false, headers, useSha256);
|
|
875
|
+
} catch (error) {
|
|
876
|
+
if (!(error instanceof WasmWebClientError)) throw error;
|
|
877
|
+
throw reportHttpError(new WasmHttpError(error.statusCode, "", config.apiURL, "POST", {}, getErrorData(error)), headers);
|
|
878
|
+
}
|
|
879
|
+
const defaults = {
|
|
880
|
+
baseURL: config.apiURL,
|
|
881
|
+
headers
|
|
906
882
|
};
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
883
|
+
const client = {
|
|
884
|
+
defaults,
|
|
885
|
+
async request(requestConfig) {
|
|
886
|
+
const { method = "GET", url, headers: requestHeaders = {}, query, params, body, signal, timeout: timeoutOverride, onUploadProgress, ie = false } = requestConfig;
|
|
887
|
+
const upperMethod = normalizeMethod(method);
|
|
888
|
+
const requestParams = params ?? query;
|
|
889
|
+
const fullUrl = buildUrl(defaults.baseURL, url, requestParams);
|
|
890
|
+
const needsSchemeHeader = useSha256 && isEncryptionEnabled();
|
|
891
|
+
const mergedHeaders = {
|
|
892
|
+
...defaults.headers,
|
|
893
|
+
...needsSchemeHeader ? { "X-RSA-Encryption-Scheme": RSA_OAEP_SHA256_SCHEME } : {},
|
|
894
|
+
...requestHeaders
|
|
895
|
+
};
|
|
896
|
+
const requestBody = prepareBody(body);
|
|
897
|
+
const timeout = timeoutOverride ?? config.timeout ?? WASM_TIMEOUT_CEILING_MS;
|
|
898
|
+
const wasmProgress = onUploadProgress ? (progress) => {
|
|
899
|
+
if (progress.total > 0) onUploadProgress(Math.round(progress.loaded / progress.total * 100));
|
|
900
|
+
} : void 0;
|
|
901
|
+
const abortError = () => new WasmHttpError(0, "Request aborted", fullUrl, upperMethod, {}, null);
|
|
902
|
+
if (signal?.aborted) throw abortError();
|
|
903
|
+
try {
|
|
904
|
+
const response = await withAbortSignal(executeWasmRequest(upperMethod, url, requestBody, mergedHeaders, requestParams, timeout, wasmProgress, ie), signal, abortError);
|
|
905
|
+
if (response.status < 200 || response.status >= 300) throw reportHttpError(new WasmHttpError(response.status, "", fullUrl, upperMethod, {}, response.data), mergedHeaders);
|
|
906
|
+
return {
|
|
907
|
+
ok: true,
|
|
908
|
+
status: response.status,
|
|
909
|
+
statusText: "",
|
|
910
|
+
url: fullUrl,
|
|
911
|
+
headers: {},
|
|
912
|
+
data: response.data
|
|
913
|
+
};
|
|
914
|
+
} catch (error) {
|
|
915
|
+
if (error instanceof WasmHttpError) throw error;
|
|
916
|
+
throw reportHttpError(new WasmHttpError(getErrorStatus(error), getErrorMessage(error), fullUrl, upperMethod, {}, getErrorData(error)), mergedHeaders);
|
|
917
|
+
}
|
|
918
|
+
},
|
|
919
|
+
get(url, requestConfig) {
|
|
920
|
+
return client.request({
|
|
921
|
+
...requestConfig,
|
|
922
|
+
url,
|
|
923
|
+
method: "GET"
|
|
924
|
+
});
|
|
925
|
+
},
|
|
926
|
+
post(url, body, requestConfig) {
|
|
927
|
+
return client.request({
|
|
928
|
+
...requestConfig,
|
|
929
|
+
url,
|
|
930
|
+
body,
|
|
931
|
+
method: "POST"
|
|
932
|
+
});
|
|
933
|
+
},
|
|
934
|
+
put(url, body, requestConfig) {
|
|
935
|
+
return client.request({
|
|
936
|
+
...requestConfig,
|
|
937
|
+
url,
|
|
938
|
+
body,
|
|
939
|
+
method: "PUT"
|
|
940
|
+
});
|
|
941
|
+
},
|
|
942
|
+
patch(url, body, requestConfig) {
|
|
943
|
+
return client.request({
|
|
944
|
+
...requestConfig,
|
|
945
|
+
url,
|
|
946
|
+
body,
|
|
947
|
+
method: "PATCH"
|
|
948
|
+
});
|
|
949
|
+
},
|
|
950
|
+
delete(url, requestConfig) {
|
|
951
|
+
return client.request({
|
|
952
|
+
...requestConfig,
|
|
953
|
+
url,
|
|
954
|
+
method: "DELETE"
|
|
955
|
+
});
|
|
956
|
+
},
|
|
957
|
+
head() {
|
|
958
|
+
return Promise.reject(/* @__PURE__ */ new Error("HEAD is not supported by the WASM HTTP client"));
|
|
959
|
+
},
|
|
960
|
+
options() {
|
|
961
|
+
return Promise.reject(/* @__PURE__ */ new Error("OPTIONS is not supported by the WASM HTTP client"));
|
|
962
|
+
},
|
|
963
|
+
setHeader(name, value) {
|
|
964
|
+
defaults.headers[name] = value;
|
|
965
|
+
}
|
|
956
966
|
};
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
function readE2eEncryptionEnabled() {
|
|
960
|
-
try {
|
|
961
|
-
return sources.getE2eEncryptionEnabled?.() ?? false;
|
|
962
|
-
} catch {
|
|
963
|
-
return false;
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
/** Fail-open, like readE2eEncryptionEnabled. */
|
|
967
|
-
function readHasToken() {
|
|
968
|
-
try {
|
|
969
|
-
return sources.getHasToken?.() ?? false;
|
|
970
|
-
} catch {
|
|
971
|
-
return false;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
function resetTrueSightMetadata() {
|
|
975
|
-
state = createInitialState();
|
|
976
|
-
sources = {};
|
|
977
|
-
}
|
|
967
|
+
return client;
|
|
968
|
+
};
|
|
978
969
|
//#endregion
|
|
979
|
-
//#region src/internal/
|
|
980
|
-
/** Index slot listing sessionIds with pending entries (no enumeration API). */
|
|
981
|
-
const PENDING_INDEX_KEY = `${PENDING_STORAGE_KEY_PREFIX}index`;
|
|
982
|
-
function slotKey(sessionId) {
|
|
983
|
-
return `${PENDING_STORAGE_KEY_PREFIX}${sessionId}`;
|
|
984
|
-
}
|
|
970
|
+
//#region src/internal/http/clientLifecycle.ts
|
|
985
971
|
/**
|
|
986
|
-
*
|
|
987
|
-
*
|
|
988
|
-
*
|
|
972
|
+
* Wraps the active HttpClient as a transport for the C++ `WebApi` host
|
|
973
|
+
* adapter. Lets the on-device face-results POST flow through the same
|
|
974
|
+
* `httpClient.request()` pipeline as every other endpoint — header
|
|
975
|
+
* injection, encryption-state handling, default headers, timeout — instead
|
|
976
|
+
* of bypassing it via `executeWasmRequest` directly.
|
|
977
|
+
*
|
|
978
|
+
* Protected captures arrive with `ie === true`: the C++ `WebApi` already
|
|
979
|
+
* encrypted the body inline, and only the WASM `WebClient` can unwrap it. A
|
|
980
|
+
* plain fetch client would post the ciphertext as JSON and the backend
|
|
981
|
+
* answers 406. If the plain client is still installed at that point (the
|
|
982
|
+
* host called `setup()` without `wasm` and warmed WASM separately), swap to
|
|
983
|
+
* the WASM client first. The module is already loaded — the payload came
|
|
984
|
+
* out of it — so the swap only creates the `WebClient`.
|
|
989
985
|
*/
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
const
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
986
|
+
function bindWebApiTransport(client) {
|
|
987
|
+
return async (url, body, config) => {
|
|
988
|
+
const response = await (config.ie === true && storedHttpConfig && !storedHttpConfig.isWasm ? await ensureWasmHttpClient() : client).request({
|
|
989
|
+
method: "POST",
|
|
990
|
+
url,
|
|
991
|
+
body,
|
|
992
|
+
headers: config.headers,
|
|
993
|
+
params: config.params,
|
|
994
|
+
timeout: config.timeout,
|
|
995
|
+
ie: config.ie
|
|
996
|
+
});
|
|
997
|
+
return {
|
|
998
|
+
data: response.data,
|
|
999
|
+
status: response.status
|
|
1000
|
+
};
|
|
1001
|
+
};
|
|
996
1002
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
* slice of the async call, which is what makes this safe to fire (void) from
|
|
1001
|
-
* a page-hide handler.
|
|
1002
|
-
*/
|
|
1003
|
-
async function writePendingEnvelope(sessionId, entry, deps) {
|
|
1004
|
-
try {
|
|
1005
|
-
await deps.storage.set(slotKey(sessionId), entry);
|
|
1006
|
-
} catch {}
|
|
1003
|
+
function installClient(client) {
|
|
1004
|
+
setClient(client);
|
|
1005
|
+
setWebApiHttpTransport(bindWebApiTransport(client));
|
|
1007
1006
|
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
await deps.storage.remove(slotKey(sessionId));
|
|
1012
|
-
const index = await readIndex(deps.storage);
|
|
1013
|
-
if (index.includes(sessionId)) await deps.storage.set(PENDING_INDEX_KEY, index.filter((candidate) => candidate !== sessionId));
|
|
1014
|
-
} catch {}
|
|
1007
|
+
async function ensureWasmHttpClient() {
|
|
1008
|
+
await upgradeToWasmHttpClient(resolveWasmConfig());
|
|
1009
|
+
return getApi();
|
|
1015
1010
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
* record, consistent with no-retry). Entries at/past the retention ceiling
|
|
1022
|
-
* are deleted unsent (A4). Never rejects; returns the A5 loss counters.
|
|
1023
|
-
*/
|
|
1024
|
-
async function recoverPendingEnvelopes(options) {
|
|
1025
|
-
const { storage, post, currentSessionId } = options;
|
|
1026
|
-
const now = options.now ?? getTimestamp;
|
|
1027
|
-
const counters = {
|
|
1028
|
-
recovered: 0,
|
|
1029
|
-
gcExpired: 0
|
|
1030
|
-
};
|
|
1031
|
-
try {
|
|
1032
|
-
const index = await readIndex(storage);
|
|
1033
|
-
if (index.length === 0) return counters;
|
|
1034
|
-
const keptInIndex = [];
|
|
1035
|
-
for (const sessionId of index) {
|
|
1036
|
-
if (sessionId === currentSessionId) {
|
|
1037
|
-
keptInIndex.push(sessionId);
|
|
1038
|
-
continue;
|
|
1039
|
-
}
|
|
1040
|
-
const entry = await readEntry(storage, sessionId);
|
|
1041
|
-
if (entry === "missing") continue;
|
|
1042
|
-
if (entry === "corrupt") {
|
|
1043
|
-
counters.gcExpired += 1;
|
|
1044
|
-
continue;
|
|
1045
|
-
}
|
|
1046
|
-
const age = now() - entry.persistedAt;
|
|
1047
|
-
if (age >= 6048e5) {
|
|
1048
|
-
counters.gcExpired += 1;
|
|
1049
|
-
await storage.remove(slotKey(sessionId));
|
|
1050
|
-
continue;
|
|
1051
|
-
}
|
|
1052
|
-
if (age < 12e4) {
|
|
1053
|
-
keptInIndex.push(sessionId);
|
|
1054
|
-
continue;
|
|
1055
|
-
}
|
|
1056
|
-
await storage.remove(slotKey(sessionId));
|
|
1057
|
-
counters.recovered += 1;
|
|
1058
|
-
post(endpoints.diagnosticsData, entry.envelope, {}).catch(() => {});
|
|
1059
|
-
}
|
|
1060
|
-
await storage.set(PENDING_INDEX_KEY, keptInIndex);
|
|
1061
|
-
} catch {}
|
|
1062
|
-
return counters;
|
|
1011
|
+
let storedHttpConfig;
|
|
1012
|
+
let pendingUpgrade;
|
|
1013
|
+
/** Reads the current HTTP-client config (or `undefined` if none installed). */
|
|
1014
|
+
function getStoredHttpConfig() {
|
|
1015
|
+
return storedHttpConfig;
|
|
1063
1016
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
return index.filter((value) => typeof value === "string");
|
|
1017
|
+
/** Whether encryption is currently active on the installed HTTP client. */
|
|
1018
|
+
function isHttpEncrypted() {
|
|
1019
|
+
return storedHttpConfig?.encryption.enabled ?? false;
|
|
1068
1020
|
}
|
|
1069
|
-
/**
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
if (value === null) return "missing";
|
|
1074
|
-
if (typeof value === "object" && value.v === 1 && typeof value.persistedAt === "number" && typeof value.envelope === "object") return value;
|
|
1075
|
-
await storage.remove(slotKey(sessionId));
|
|
1076
|
-
return "corrupt";
|
|
1077
|
-
} catch {
|
|
1078
|
-
try {
|
|
1079
|
-
await storage.remove(slotKey(sessionId));
|
|
1080
|
-
} catch {}
|
|
1081
|
-
return "corrupt";
|
|
1082
|
-
}
|
|
1021
|
+
/** Clears all HTTP-client state. Called by `reset()`. */
|
|
1022
|
+
function resetHttpClientState() {
|
|
1023
|
+
storedHttpConfig = void 0;
|
|
1024
|
+
setWebApiHttpTransport(null);
|
|
1083
1025
|
}
|
|
1084
|
-
//#endregion
|
|
1085
|
-
//#region src/internal/featureConfig/featureConfigService.ts
|
|
1086
|
-
let cachedFeatures = null;
|
|
1087
1026
|
/**
|
|
1088
|
-
*
|
|
1027
|
+
* Builds (or replaces) the HTTP client when `setup()` receives an `apiURL`.
|
|
1028
|
+
* Picks `createWasmApi` when `effectiveWasm` is set, otherwise plain
|
|
1029
|
+
* `createApi`. Wraps the call in handshake-failure context when encryption
|
|
1030
|
+
* is requested.
|
|
1089
1031
|
*/
|
|
1090
|
-
function
|
|
1091
|
-
|
|
1032
|
+
async function installFreshHttpClient(apiURL, options, effectiveWasm, encryption) {
|
|
1033
|
+
installClient(effectiveWasm ? await withHandshakeFailureContext(encryption.enabled, () => createWasmApi({
|
|
1034
|
+
apiURL,
|
|
1035
|
+
customHeaders: options.customHeaders,
|
|
1036
|
+
timeout: options.timeout,
|
|
1037
|
+
wasm: effectiveWasm,
|
|
1038
|
+
encryptionEnabled: encryption.enabled,
|
|
1039
|
+
mgf1: encryption.mgf1,
|
|
1040
|
+
isEncryptionEnabled: isHttpEncrypted
|
|
1041
|
+
})) : createApi({
|
|
1042
|
+
apiURL,
|
|
1043
|
+
customHeaders: options.customHeaders,
|
|
1044
|
+
timeout: options.timeout
|
|
1045
|
+
}));
|
|
1046
|
+
storedHttpConfig = {
|
|
1047
|
+
apiURL,
|
|
1048
|
+
customHeaders: options.customHeaders,
|
|
1049
|
+
timeout: options.timeout,
|
|
1050
|
+
isWasm: Boolean(effectiveWasm),
|
|
1051
|
+
encryption
|
|
1052
|
+
};
|
|
1092
1053
|
}
|
|
1093
1054
|
/**
|
|
1094
|
-
*
|
|
1095
|
-
*
|
|
1055
|
+
* Replaces the active HTTP client with the WASM-backed one. Used internally
|
|
1056
|
+
* by lazy-loading UI components (`<incode-flow>`, `<incode-workflow>`) when
|
|
1057
|
+
* WASM finishes warming up.
|
|
1058
|
+
*
|
|
1059
|
+
* No-op when no apiURL was previously configured, or when the active client
|
|
1060
|
+
* is already WASM-backed. The encryption state (enabled + MGF1 scheme) is
|
|
1061
|
+
* preserved across the swap — this is *not* a user-facing encryption change.
|
|
1062
|
+
*
|
|
1063
|
+
* @internal NOT a public API. Application code should use
|
|
1064
|
+
* `setup({ wasm: {...} })` instead.
|
|
1096
1065
|
*/
|
|
1097
|
-
async function
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1066
|
+
async function upgradeToWasmHttpClient(resolved) {
|
|
1067
|
+
const stored = storedHttpConfig;
|
|
1068
|
+
if (!stored || stored.isWasm) return;
|
|
1069
|
+
pendingUpgrade ??= (async () => {
|
|
1070
|
+
installClient(await createWasmApi({
|
|
1071
|
+
apiURL: stored.apiURL,
|
|
1072
|
+
customHeaders: stored.customHeaders,
|
|
1073
|
+
timeout: stored.timeout,
|
|
1074
|
+
wasm: resolved,
|
|
1075
|
+
encryptionEnabled: stored.encryption.enabled,
|
|
1076
|
+
mgf1: stored.encryption.mgf1,
|
|
1077
|
+
isEncryptionEnabled: isHttpEncrypted
|
|
1078
|
+
}));
|
|
1079
|
+
storedHttpConfig = {
|
|
1080
|
+
...stored,
|
|
1081
|
+
isWasm: true
|
|
1082
|
+
};
|
|
1083
|
+
})().finally(() => {
|
|
1084
|
+
pendingUpgrade = void 0;
|
|
1085
|
+
});
|
|
1086
|
+
return pendingUpgrade;
|
|
1103
1087
|
}
|
|
1104
1088
|
/**
|
|
1105
|
-
*
|
|
1089
|
+
* When `wantsEncryption` is true, wraps a call that triggers the in-binary
|
|
1090
|
+
* RSA/AES handshake so its rejection surfaces as a single, descriptive error
|
|
1091
|
+
* with the original error preserved as `cause`. Pass-through otherwise.
|
|
1106
1092
|
*/
|
|
1107
|
-
function
|
|
1108
|
-
|
|
1093
|
+
async function withHandshakeFailureContext(wantsEncryption, fn) {
|
|
1094
|
+
if (!wantsEncryption) return fn();
|
|
1095
|
+
try {
|
|
1096
|
+
return await fn();
|
|
1097
|
+
} catch (cause) {
|
|
1098
|
+
const error = /* @__PURE__ */ new Error("Failed to establish encrypted transport. The /e2ee/key handshake did not complete. Verify the apiURL is reachable and that the environment supports E2EE.");
|
|
1099
|
+
error.cause = cause;
|
|
1100
|
+
throw error;
|
|
1101
|
+
}
|
|
1109
1102
|
}
|
|
1110
1103
|
eventModuleNames.selfie, eventModuleNames.faceCapture, eventModuleNames.authentication, eventModuleNames.authFace, eventModuleNames.mlConsent, eventModuleNames.combinedConsent, eventModuleNames.curpValidation, eventModuleNames.faceMatch, eventModuleNames.qr, eventModuleNames.videoSelfie, eventModuleNames.id, eventModuleNames.idCapture, eventModuleNames.idVerification, eventModuleNames.idOcr, eventModuleNames.document, eventModuleNames.creditCard, eventModuleNames.creditCardBack, eventModuleNames.conference, eventModuleNames.otp, eventModuleNames.signature, eventModuleNames.ekyc, eventModuleNames.watchlist, eventModuleNames.globalWatchList, eventModuleNames.customWatchList, eventModuleNames.email, eventModuleNames.phone, eventModuleNames.instantVerifyEmail, eventModuleNames.instantVerifyConsent, eventModuleNames.forms, eventModuleNames.customModule, eventModuleNames.geolocation, eventModuleNames.ekyb, eventModuleNames.identityReuse, eventModuleNames.antifraud, eventModuleNames.aeSignature, eventModuleNames.qeSignature, eventModuleNames.crossDocumentDataMatch, eventModuleNames.customFields, eventModuleNames.fieldComparison, eventModuleNames.personhood, eventModuleNames.watchlistForBusiness, eventModuleNames.trustGraph, eventModuleNames.certificateIssuance, eventModuleNames.governmentValidation, eventModuleNames.documentUpload, eventModuleNames.home, eventModuleNames.workflow, eventModuleNames.fiscalQr;
|
|
1111
1104
|
eventModuleNames.id, eventModuleNames.idCapture, eventModuleNames.idVerification, eventModuleNames.idOcr, eventModuleNames.document, eventModuleNames.documentUpload, eventModuleNames.creditCard, eventModuleNames.creditCardBack, eventModuleNames.curpValidation;
|
|
@@ -1508,4 +1501,4 @@ function modulePosition(payload) {
|
|
|
1508
1501
|
return `${typeof moduleIndex === "number" ? ` index=${moduleIndex}` : ""}${typeof totalModules === "number" ? ` total=${totalModules}` : ""}`;
|
|
1509
1502
|
}
|
|
1510
1503
|
//#endregion
|
|
1511
|
-
export { DEFAULT_WASM_VERSION as C, resolveWasmConfig as D, getBarcodeEnhanceModelUrl as E,
|
|
1504
|
+
export { DEFAULT_WASM_VERSION as C, resolveWasmConfig as D, getBarcodeEnhanceModelUrl as E, noteTokenActivated as S, buildWasmConfigFromBasePath as T, resetFeatureConfigCache as _, notifyTrueSightManagerStopped as a, noteSessionCreated as b, trueSightHintTransition as c, getStoredHttpConfig as d, installFreshHttpClient as f, isFeatureEnabled as g, fetchFeatureConfig as h, notifyTrueSightFlowEvent as i, trueSightLog as l, upgradeToWasmHttpClient as m, initializeTrueSightDiagnostics as n, resetTrueSight as o, resetHttpClientState as p, noteTrueSightCaptureActivity as r, startTrueSightCollection as s, finalizeTrueSight as t, categoryForEndpoint as u, isTrueSightTesting as v, buildDefaultWasmConfig as w, noteTestingSignals as x, noteEnvironment as y };
|