@incodetech/core 2.1.0-rc.2 → 2.1.0-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/dist/3dAvatarProvider-9zb-7MLE.esm.js +28214 -0
  2. package/dist/{BrowserStorageProvider-D5xc7Lqo.esm.js → BrowserStorageProvider-CBXGCHnK.esm.js} +1 -25
  3. package/dist/BrowserVisibilityObserverProvider-B04zvOXW.esm.js +25 -0
  4. package/dist/Face2DProvider-DqFSo9Ls.esm.js +824 -0
  5. package/dist/FaceDetectionProvider-BcPv1ruX.d.ts +119 -0
  6. package/dist/IVisibilityObserverCapability-BxPj7hsu.d.ts +12 -0
  7. package/dist/IWasmUtilCapability-Bf91iomn.d.ts +145 -0
  8. package/dist/{Manager-B2OEDYqf.d.ts → Manager-BfBOhrjh.d.ts} +1 -4
  9. package/dist/{OpenViduRecordingProvider-DF7A4ZNJ.esm.js → OpenViduRecordingProvider-DmA__QfK.esm.js} +1 -1
  10. package/dist/PrivacyLensProvider-CfmaSQy3.esm.js +339 -0
  11. package/dist/StateMachine-20ahmASR.d.ts +2 -0
  12. package/dist/{StreamCanvasCapture-Dr5n_iK1.esm.js → StreamCanvasCapture-CRk7c7u7.esm.js} +1 -1
  13. package/dist/StreamCanvasCapture-DHDxv6hH.d.ts +42 -0
  14. package/dist/{WasmUtilProvider-CIu373BZ.esm.js → WasmUtilProvider-ADG54T6M.esm.js} +16 -1
  15. package/dist/{addressSearch-BH96a3fq.esm.js → addressSearch-B9iJdbn8.esm.js} +4 -4
  16. package/dist/{ae-signature-CDEN8y-w.esm.js → ae-signature-Pp4oCAHD.esm.js} +1 -1
  17. package/dist/ae-signature.d.ts +4 -3
  18. package/dist/ae-signature.esm.js +9 -9
  19. package/dist/antifraud.d.ts +4 -3
  20. package/dist/antifraud.esm.js +6 -6
  21. package/dist/{antifraudManager-DZifA5zX.esm.js → antifraudManager-5KA84wtF.esm.js} +3 -3
  22. package/dist/{antifraudManager-B7WQTIdu.d.ts → antifraudManager-D-nGY1T9.d.ts} +2 -2
  23. package/dist/{antifraudStateMachine-DlKrK2hL.esm.js → antifraudStateMachine-BQVw46N5.esm.js} +3 -3
  24. package/dist/{api-DUZwyz0o.esm.js → api-DsbUi7TO.esm.js} +21 -2
  25. package/dist/authentication.d.ts +19 -12
  26. package/dist/authentication.esm.js +32 -27
  27. package/dist/{authenticationManager-Dve7mGLe.d.ts → authenticationManager-BnAY9lOO.d.ts} +3 -3
  28. package/dist/{authenticationManager-BM4LzyV7.esm.js → authenticationManager-BnPgoiL_.esm.js} +6 -6
  29. package/dist/{authenticationStateMachine-Chx3ySdT.esm.js → authenticationStateMachine-D50Q6Nvp.esm.js} +8 -8
  30. package/dist/avatar.d.ts +3 -0
  31. package/dist/avatar.esm.js +3 -0
  32. package/dist/{backCameraStream-iftkf3rd.esm.js → backCameraStream-POavVKz4.esm.js} +3 -3
  33. package/dist/{browser-DlFgHpoC-7tbRR1aR.esm.js → browser-DlFgHpoC-CR6x7ypG.esm.js} +1 -1
  34. package/dist/{browserSimulation-CGjpdNA1.esm.js → browserSimulation-DFpmweuc.esm.js} +153 -1216
  35. package/dist/camera-B0yWS33x.esm.js +79 -0
  36. package/dist/camera.d.ts +7 -1
  37. package/dist/camera.esm.js +4 -4
  38. package/dist/{StreamCanvasCapture-Ctgyx-oD.d.ts → canvas-pLrXU1id.d.ts} +1 -41
  39. package/dist/certificate-issuance.d.ts +31 -30
  40. package/dist/certificate-issuance.esm.js +7 -7
  41. package/dist/{certificateIssuanceStateMachine-CLNXtXaC.esm.js → certificateIssuanceStateMachine-CpewPqas.esm.js} +4 -4
  42. package/dist/clientLifecycle-Ct7h9uxx.esm.js +534 -0
  43. package/dist/consent.d.ts +4 -3
  44. package/dist/consent.esm.js +6 -6
  45. package/dist/{consentManager-BqUGU_YD.d.ts → consentManager-BuiDVAGn.d.ts} +52 -52
  46. package/dist/{consentManager-psDCeJ0E.esm.js → consentManager-DL93cPSU.esm.js} +3 -3
  47. package/dist/{consentStateMachine-DRsFFSHE.esm.js → consentStateMachine-DnqwsZ7o.esm.js} +3 -3
  48. package/dist/cpf-ocr.d.ts +4 -3
  49. package/dist/cpf-ocr.esm.js +6 -6
  50. package/dist/{cpfOcrManager-BxcgxvgO.esm.js → cpfOcrManager-BW8wlEU_.esm.js} +5 -5
  51. package/dist/{cpfOcrManager-B2u9hMzd.d.ts → cpfOcrManager-D_cnGuB7.d.ts} +19 -19
  52. package/dist/createFaceAvatar-CpmQJA8E.esm.js +46 -0
  53. package/dist/createFaceAvatar-DNMSIcRb.d.ts +401 -0
  54. package/dist/cross-document-data-match.d.ts +2 -1
  55. package/dist/cross-document-data-match.esm.js +5 -5
  56. package/dist/curp-validation.d.ts +10 -7
  57. package/dist/curp-validation.esm.js +6 -6
  58. package/dist/{curpValidationManager-Bt6CVD8b.d.ts → curpValidationManager-CJdVrCex.d.ts} +3 -3
  59. package/dist/{curpValidationManager-BgLDw0Ub.esm.js → curpValidationManager-u2FkvveY.esm.js} +3 -3
  60. package/dist/{curpValidationStateMachine-BK_wJ48C.esm.js → curpValidationStateMachine-CeqDh2V5.esm.js} +3 -3
  61. package/dist/custom-fields.d.ts +3 -2
  62. package/dist/custom-fields.esm.js +5 -5
  63. package/dist/custom-watchlist.d.ts +2 -1
  64. package/dist/custom-watchlist.esm.js +5 -5
  65. package/dist/{customWatchlistStateMachine-Bi4P59HM.esm.js → customWatchlistStateMachine-dovMwTLv.esm.js} +3 -3
  66. package/dist/{deepsightLoader-BMmvk0X6.esm.js → deepsightLoader-CgK9h2KF.esm.js} +20 -14
  67. package/dist/{deepsightService-CEZrdiW0.esm.js → deepsightService-BsLpJT8o.esm.js} +13 -42
  68. package/dist/deepsightService-CbaqT7bP.d.ts +69 -0
  69. package/dist/device.d.ts +9 -1
  70. package/dist/device.esm.js +5 -5
  71. package/dist/document-capture.d.ts +179 -178
  72. package/dist/document-capture.esm.js +13 -13
  73. package/dist/document-upload.d.ts +48 -47
  74. package/dist/document-upload.esm.js +8 -8
  75. package/dist/{documentCaptureStateMachine-MpwpJO7t.esm.js → documentCaptureStateMachine-DK3nD2UZ.esm.js} +7 -7
  76. package/dist/dynamic-forms.d.ts +4 -192
  77. package/dist/dynamic-forms.esm.js +7 -160
  78. package/dist/dynamicFormsManager-B_4qA_CB.d.ts +239 -0
  79. package/dist/dynamicFormsManager-CNg60mlv.esm.js +167 -0
  80. package/dist/{dynamicFormsStateMachine-Do84A4uU.esm.js → dynamicFormsStateMachine-BfLLcxua.esm.js} +4 -4
  81. package/dist/ekyb.d.ts +9 -6
  82. package/dist/ekyb.esm.js +17 -17
  83. package/dist/{ekybStateMachine-nsuPOw3f.esm.js → ekybStateMachine-DJ9lWfdc.esm.js} +5 -5
  84. package/dist/ekyc.d.ts +4 -3
  85. package/dist/ekyc.esm.js +8 -8
  86. package/dist/{ekycStateMachine-DcynX0rj.esm.js → ekycStateMachine-BcPEEqMA.esm.js} +5 -5
  87. package/dist/electronic-signature.d.ts +4 -3
  88. package/dist/electronic-signature.esm.js +8 -8
  89. package/dist/{electronicSignatureManager-B63aAuI5.esm.js → electronicSignatureManager-DESRgObX.esm.js} +49 -87
  90. package/dist/email.d.ts +5 -4
  91. package/dist/email.esm.js +8 -8
  92. package/dist/{emailManager-DxHjAe5u.esm.js → emailManager-C9O7k0-m.esm.js} +4 -4
  93. package/dist/{emailManager-C6D2u4mQ.d.ts → emailManager-CTOXMlVd.d.ts} +3 -3
  94. package/dist/{emailStateMachine-758f34gg.esm.js → emailStateMachine-Bk4pkysV.esm.js} +5 -5
  95. package/dist/{endpoints-BM2_j_IE.esm.js → endpoints-CwrFQfW7.esm.js} +13 -0
  96. package/dist/{events-DN-u67gb.esm.js → events-1wxZ97yf.esm.js} +3 -1
  97. package/dist/events.d.ts +2 -0
  98. package/dist/events.esm.js +2 -2
  99. package/dist/extensibility.d.ts +37 -26
  100. package/dist/extensibility.esm.js +71 -59
  101. package/dist/{externalFetch-crimxkN9.esm.js → externalFetch-hvmz_npP.esm.js} +1 -1
  102. package/dist/face-match.d.ts +2 -2
  103. package/dist/face-match.esm.js +5 -5
  104. package/dist/faceCaptureManagerFactory-DKBvmRxO.d.ts +400 -0
  105. package/dist/{faceCaptureManagerFactory-BNXZchWX.esm.js → faceCaptureManagerFactory-bJiqzRoj.esm.js} +24 -16
  106. package/dist/{faceCaptureSetup-Dqb09D24.esm.js → faceCaptureSetup-jYJNhw2K.esm.js} +97 -13
  107. package/dist/{faceMatchStateMachine-FikRaUZH.esm.js → faceMatchStateMachine-C6J09ygk.esm.js} +3 -3
  108. package/dist/field-comparison.d.ts +4 -3
  109. package/dist/field-comparison.esm.js +5 -5
  110. package/dist/{fieldComparisonManager-BXc6-DJv.d.ts → fieldComparisonManager-BOEgiOw_.d.ts} +2 -2
  111. package/dist/{fieldComparisonManager-Dic0DVgl.esm.js → fieldComparisonManager-kk2RkWeb.esm.js} +4 -4
  112. package/dist/fiscal-qr.d.ts +5 -3
  113. package/dist/fiscal-qr.esm.js +12 -12
  114. package/dist/flow-events.d.ts +8 -6
  115. package/dist/flow.d.ts +21 -13
  116. package/dist/flow.esm.js +25 -19
  117. package/dist/{flowCompletionService-D_CsiDZM.esm.js → flowCompletionService-BDcDfyoA.esm.js} +3 -3
  118. package/dist/{flowCompletionService-CdGDKv0z.d.ts → flowCompletionService-nF7e8At0.d.ts} +2 -1
  119. package/dist/{flowServices-ar5DXv71.esm.js → flowServices-DTQUals9.esm.js} +24 -9
  120. package/dist/geolocation.d.ts +4 -127
  121. package/dist/geolocation.esm.js +7 -115
  122. package/dist/geolocationManager-B3lahU1a.d.ts +156 -0
  123. package/dist/geolocationManager-CVKUo6a4.esm.js +122 -0
  124. package/dist/{geolocationStateMachine-BWjrMGS_.esm.js → geolocationStateMachine-CdYh-pwi.esm.js} +4 -4
  125. package/dist/{getDeviceClass-rXKlXywy.esm.js → getDeviceClass-QxbJwsOO.esm.js} +1 -1
  126. package/dist/government-validation.d.ts +4 -3
  127. package/dist/government-validation.esm.js +7 -7
  128. package/dist/{governmentValidationStateMachine-BoF7U1of.esm.js → governmentValidationStateMachine-CjCs0_fG.esm.js} +5 -5
  129. package/dist/home.d.ts +18 -15
  130. package/dist/home.esm.js +3 -3
  131. package/dist/http.esm.js +2 -2
  132. package/dist/id-ocr.d.ts +4 -625
  133. package/dist/id-ocr.esm.js +7 -84
  134. package/dist/id-verification.d.ts +28 -27
  135. package/dist/id-verification.esm.js +5 -5
  136. package/dist/id.d.ts +16 -11
  137. package/dist/id.esm.js +36 -32
  138. package/dist/idCaptureDefaults-DJmo-U3D.esm.js +188 -0
  139. package/dist/{idCaptureManager-BvGUSN2e.d.ts → idCaptureManager-58R91WU3.d.ts} +40 -10
  140. package/dist/{idCaptureManager-Bm6Wm6Qv.esm.js → idCaptureManager-Cd7THjha.esm.js} +13 -11
  141. package/dist/{idCaptureStateMachine-D1YhOj6n.esm.js → idCaptureStateMachine-BFMIWmBu.esm.js} +395 -382
  142. package/dist/idOcrManager-CDIHkP-v.d.ts +641 -0
  143. package/dist/idOcrManager-CiEzYor8.esm.js +91 -0
  144. package/dist/{idOcrStateMachine-YMCDGplq.esm.js → idOcrStateMachine-CGeY01rX.esm.js} +5 -5
  145. package/dist/{idVerificationStateMachine-Bo1IYuZH.esm.js → idVerificationStateMachine-B6Ccvut4.esm.js} +3 -3
  146. package/dist/identity-reuse.d.ts +4 -3
  147. package/dist/identity-reuse.esm.js +6 -6
  148. package/dist/{identityReuseManager-DcWSvC-A.d.ts → identityReuseManager-BlJpsh9U.d.ts} +33 -33
  149. package/dist/{identityReuseManager-D0knIrOy.esm.js → identityReuseManager-CrbjKac7.esm.js} +3 -3
  150. package/dist/{identityReuseStateMachine-CSQfZOqD.esm.js → identityReuseStateMachine-Do_M-z6z.esm.js} +3 -3
  151. package/dist/{index-DV134v62.d.ts → index-BgJYOyFO.d.ts} +175 -295
  152. package/dist/{index-BgxYUYuD.d.ts → index-CVgIGwUy.d.ts} +2 -2
  153. package/dist/index.d.ts +3 -3
  154. package/dist/index.esm.js +13 -13
  155. package/dist/{invokeOnCaptureCallback-Dzemudhk.esm.js → invokeOnCaptureCallback-gKRaO24Q.esm.js} +1 -1
  156. package/dist/{lib-7ZQ9BdKH.esm.js → lib-TRTXfron.esm.js} +1 -1
  157. package/dist/mandatory-consent.d.ts +10 -7
  158. package/dist/mandatory-consent.esm.js +6 -6
  159. package/dist/{mandatoryConsentManager-Tzl5Qd35.d.ts → mandatoryConsentManager-Da8pFx0L.d.ts} +53 -53
  160. package/dist/{mandatoryConsentManager-Lon46nPQ.esm.js → mandatoryConsentManager-b1QKgIKi.esm.js} +3 -3
  161. package/dist/{mandatoryConsentStateMachine-D_dZ7IF6.esm.js → mandatoryConsentStateMachine-VPbrLLfo.esm.js} +3 -3
  162. package/dist/mediaRecorderOptions-BIn657lu.esm.js +42 -0
  163. package/dist/mediapipeShared-yKDdOf_V.esm.js +67 -0
  164. package/dist/{recordingService-CxMJP4tQ.esm.js → onDeviceFaceResults-BdfKrQrf.esm.js} +71 -389
  165. package/dist/{openviduLazy-oAXXI9w_.esm.js → openviduLazy-BXDnVFe2.esm.js} +2 -2
  166. package/dist/openviduLazy-lAZzee_g.esm.js +3 -0
  167. package/dist/{permissionGuards-D-Z-lgNj.esm.js → permissionGuards-CaZl9t7f.esm.js} +1 -1
  168. package/dist/{permissionServices-CPDboRoE.esm.js → permissionServices-D9lmzFYc.esm.js} +7 -4
  169. package/dist/personhood.d.ts +534 -0
  170. package/dist/personhood.esm.js +1500 -0
  171. package/dist/phone.d.ts +5 -4
  172. package/dist/phone.esm.js +8 -8
  173. package/dist/{phoneManager-TSq1Ief6.d.ts → phoneManager-CG1vTJiG.d.ts} +3 -3
  174. package/dist/{phoneManager-Blt4Oc2P.esm.js → phoneManager-DNTrIq-D.esm.js} +4 -4
  175. package/dist/{phoneStateMachine-W3c6Z8sj.esm.js → phoneStateMachine-MqNDf1Nh.esm.js} +5 -5
  176. package/dist/{qe-signature-CQLK6LKE.esm.js → qe-signature-CVnJ4RaW.esm.js} +1 -1
  177. package/dist/qe-signature.d.ts +4 -3
  178. package/dist/qe-signature.esm.js +9 -9
  179. package/dist/recordingService-B5QNBYnv.esm.js +347 -0
  180. package/dist/redirect-to-mobile.d.ts +4 -3
  181. package/dist/redirect-to-mobile.esm.js +8 -8
  182. package/dist/{redirectToMobileManager-yOHAmwg-.d.ts → redirectToMobileManager-D7U9k-Xs.d.ts} +2 -2
  183. package/dist/{redirectToMobileManager-DCvpKdkD.esm.js → redirectToMobileManager-DuD03ggR.esm.js} +4 -4
  184. package/dist/{redirectToMobileStateMachine-DC9z4Vfu.esm.js → redirectToMobileStateMachine-WVg-n2is.esm.js} +10 -12
  185. package/dist/{runChildModule-C9G0wfVC.esm.js → runChildModule-XHWWqs39.esm.js} +3 -3
  186. package/dist/selfie.d.ts +19 -12
  187. package/dist/selfie.esm.js +33 -28
  188. package/dist/{selfieManager-imY2dAcH.d.ts → selfieManager-CXmUuCSV.d.ts} +3 -3
  189. package/dist/{selfieManager-BRL6c_Oc.esm.js → selfieManager-Cw29cKuL.esm.js} +6 -6
  190. package/dist/{selfieStateMachine-D2Q0uwDK.esm.js → selfieStateMachine-DUruCKBS.esm.js} +4 -4
  191. package/dist/{session-Be_IA1e0.esm.js → session-BWCjVIr6.esm.js} +3 -3
  192. package/dist/session.d.ts +7 -5
  193. package/dist/session.esm.js +13 -14
  194. package/dist/{sessionInitializer-CaiGA8GP.esm.js → sessionInitializer-CzPdr0Q1.esm.js} +73 -10
  195. package/dist/{setup-BJZAkajt.d.ts → setup-BbAMk9Rg.d.ts} +31 -3
  196. package/dist/setup-hKBHwm6K.esm.js +564 -0
  197. package/dist/signature.d.ts +3 -2
  198. package/dist/signature.esm.js +5 -5
  199. package/dist/{signatureStateMachine-DAxXmMrk.esm.js → signatureStateMachine-iT9BhNUf.esm.js} +3 -3
  200. package/dist/{stats-DntyIiGr.esm.js → stats-BVy52wLy.esm.js} +2 -2
  201. package/dist/stats.esm.js +3 -3
  202. package/dist/thumbmarkAdapter-CVyiGp0-.esm.js +1194 -0
  203. package/dist/{tri-CtxWthxz.esm.js → tri-CFBjqf5E.esm.js} +12 -2
  204. package/dist/tri.d.ts +1 -1
  205. package/dist/{tri.esm-CrWAulDi.esm.js → tri.esm-BzYyqlPa.esm.js} +27 -23
  206. package/dist/tri.esm.js +2 -2
  207. package/dist/trust-graph.d.ts +4 -3
  208. package/dist/trust-graph.esm.js +3 -3
  209. package/dist/{types-Z9wv19v2.d.ts → types-B_YCuHZx.d.ts} +1 -1
  210. package/dist/{types-DpTWgfKY.d.ts → types-CRPns2d9.d.ts} +1 -1
  211. package/dist/{types-Dv-9WPJX.d.ts → types-Cyi3gwPK.d.ts} +39 -3
  212. package/dist/types-DWmubDie.d.ts +132 -0
  213. package/dist/video-DXf5H9rY.esm.js +36 -0
  214. package/dist/video-selfie.d.ts +351 -0
  215. package/dist/video-selfie.esm.js +1506 -0
  216. package/dist/videoSelfieSteps-C6E7mKFt.esm.js +58 -0
  217. package/dist/{warmup--6HA3yUR.d.ts → warmup-DzJ0I4Kv.d.ts} +5 -1
  218. package/dist/wasm.d.ts +4 -4
  219. package/dist/wasm.esm.js +14 -14
  220. package/dist/watchlist-for-business.d.ts +2 -1
  221. package/dist/watchlist-for-business.esm.js +5 -5
  222. package/dist/watchlist.d.ts +2 -1
  223. package/dist/watchlist.esm.js +5 -5
  224. package/dist/{watchlistForBusinessStateMachine-DtefJb-D.esm.js → watchlistForBusinessStateMachine-CyhTEi3N.esm.js} +3 -3
  225. package/dist/{watchlistStateMachine-B0aIS2_n.esm.js → watchlistStateMachine-CgKG-KSf.esm.js} +3 -3
  226. package/dist/workflow.d.ts +232 -100
  227. package/dist/workflow.esm.js +120 -79
  228. package/dist/{xstate.esm-Dkm1jy5u.esm.js → xstate.esm-nY3M5UYm.esm.js} +41 -1
  229. package/package.json +18 -3
  230. package/dist/IpifyProvider-oZf7Ke1O.esm.js +0 -167
  231. package/dist/camera-x4LjGTjZ.esm.js +0 -22
  232. package/dist/deepsightService-ByNKY5Jv.d.ts +0 -276
  233. package/dist/faceCaptureManagerFactory-CL-7T_vH.d.ts +0 -731
  234. package/dist/getBrowser-Dv8LZyHE.esm.js +0 -8
  235. package/dist/openviduLazy-B_s6jnEk.esm.js +0 -3
  236. package/dist/setup-C7tintPc.esm.js +0 -1064
  237. /package/dist/{Actor-fIPLXfoi.d.ts → Actor-DYjXVMQm.d.ts} +0 -0
  238. /package/dist/{BrowserTimerProvider-BVgutW_b.esm.js → BrowserTimerProvider-CHloo0eQ.esm.js} +0 -0
  239. /package/dist/{ITimerCapability-BvH0pDwp.esm.js → ITimerCapability-G7lQg-be.esm.js} +0 -0
  240. /package/dist/{MotionSensorProvider-C9fPAJdS.esm.js → MotionSensorProvider-BkHKMCPE.esm.js} +0 -0
  241. /package/dist/{apiError-D-GTvFrH.esm.js → apiError-DkOXfFBu.esm.js} +0 -0
  242. /package/dist/{camera-biGPWlmx.d.ts → camera-CWO06Lu5.d.ts} +0 -0
  243. /package/dist/{canvas-7uX2izHb.esm.js → canvas-DsJa51yU.esm.js} +0 -0
  244. /package/dist/{chunk-BK1xu56N.esm.js → chunk-CIKcdghV.esm.js} +0 -0
  245. /package/dist/{cpf-xBg-DFNn.esm.js → cpf-B9htWzDt.esm.js} +0 -0
  246. /package/dist/{dateUtils-8dCcuArE.esm.js → dateUtils-PXB_WRYL.esm.js} +0 -0
  247. /package/dist/{getDeviceClass-C0zrM97a.esm.js → getDeviceClass-BdgmyOOu.esm.js} +0 -0
  248. /package/dist/{http-CfVTgMfU.esm.js → http-CBbBcnBa.esm.js} +0 -0
  249. /package/dist/{index-52_qi4bd.d.ts → index-CCG6MnCO.d.ts} +0 -0
  250. /package/dist/{otp-BHJnjEEc.d.ts → otp-CETbFjXH.d.ts} +0 -0
  251. /package/dist/{otp-D87RTwrx.esm.js → otp-DepQPUIA.esm.js} +0 -0
  252. /package/dist/{platform-BfoqeM61.esm.js → platform-BoeUeUrV.esm.js} +0 -0
  253. /package/dist/{types-F0IXbaCB.d.ts → types-BOiKESZY.d.ts} +0 -0
  254. /package/dist/{types-DYZja-k9.d.ts → types-CTnn7kUK.d.ts} +0 -0
  255. /package/dist/{types-BdVOWGGW.esm.js → types-Db2ooXIu.esm.js} +0 -0
  256. /package/dist/{urlUtils-8RNHyW3x.esm.js → urlUtils-CpiYwn7w.esm.js} +0 -0
@@ -0,0 +1,1500 @@
1
+ import { t as WasmUtilProvider } from "./WasmUtilProvider-ADG54T6M.esm.js";
2
+ import { t as BrowserTimerProvider } from "./BrowserTimerProvider-CHloo0eQ.esm.js";
3
+ import { t as api } from "./api-DsbUi7TO.esm.js";
4
+ import { a as createApi_default, t as getStoredHttpConfig } from "./clientLifecycle-Ct7h9uxx.esm.js";
5
+ import { n as eventModuleNames } from "./events-1wxZ97yf.esm.js";
6
+ import { t as endpoints } from "./endpoints-CwrFQfW7.esm.js";
7
+ import "./stats-BVy52wLy.esm.js";
8
+ import { n as isBrowserSimulation, o as BrowserEnvironmentProvider } from "./browserSimulation-DFpmweuc.esm.js";
9
+ import { n as getFingerprintEnabled, u as getDeviceFingerprintInfo } from "./sessionInitializer-CzPdr0Q1.esm.js";
10
+ import { t as getThumbmarkId } from "./thumbmarkAdapter-CVyiGp0-.esm.js";
11
+ import "./platform-BoeUeUrV.esm.js";
12
+ import "./tri-CFBjqf5E.esm.js";
13
+ import { a as fromPromise, i as fromCallback, l as createManager, r as assign, s as createActor, t as setup } from "./xstate.esm-nY3M5UYm.esm.js";
14
+ import "./MotionSensorProvider-BkHKMCPE.esm.js";
15
+ import { i as requestPermission, t as checkPermission } from "./permissionServices-D9lmzFYc.esm.js";
16
+ import { a as stopCameraStream, r as requestCameraAccess } from "./camera-B0yWS33x.esm.js";
17
+ import { t as BrowserStorageProvider } from "./BrowserStorageProvider-CBXGCHnK.esm.js";
18
+ import { b as FaceDetectionProvider, f as stopStream, l as startDetection, s as initializeDeepsightSession } from "./onDeviceFaceResults-BdfKrQrf.esm.js";
19
+ import { t as sleep } from "./ITimerCapability-G7lQg-be.esm.js";
20
+ import "./canvas-DsJa51yU.esm.js";
21
+ import "./backCameraStream-POavVKz4.esm.js";
22
+ import "./video-DXf5H9rY.esm.js";
23
+ import "./getDeviceClass-BdgmyOOu.esm.js";
24
+ import "./deepsightService-BsLpJT8o.esm.js";
25
+ import "./getDeviceClass-QxbJwsOO.esm.js";
26
+ import "./types-Db2ooXIu.esm.js";
27
+ import { t as StreamCanvasCapture } from "./StreamCanvasCapture-CRk7c7u7.esm.js";
28
+
29
+ //#region ../infra/src/crypto/randomUUID.ts
30
+ /**
31
+ * Cryptographically-strong UUID v4 (RFC 4122).
32
+ *
33
+ * Lives in infra (L0) so Core (L1) can mint secure identifiers without touching
34
+ * the `crypto` browser API directly — Core delegates here, keeping it free of
35
+ * browser globals (enforced by the `no-browser-api-in-core` lint rule). Backed
36
+ * by `crypto.randomUUID`, available in every browser the SDK targets.
37
+ */
38
+ function randomUUID() {
39
+ return crypto.randomUUID();
40
+ }
41
+
42
+ //#endregion
43
+ //#region src/modules/personhood/personhoodServices.ts
44
+ /**
45
+ * Config used for the passive liveness pass. Deliberately stripped down from
46
+ * selfie: no recording, no validation rituals, no headwear/mask checks — we
47
+ * want the lowest-friction path to a single head-pose-tracked liveness shot.
48
+ */
49
+ const PERSONHOOD_FACE_CAPTURE_CONFIG = {
50
+ showTutorial: false,
51
+ showPreview: false,
52
+ assistedOnboarding: false,
53
+ enableFaceRecording: false,
54
+ autoCaptureTimeout: 8e3,
55
+ captureAttempts: 2,
56
+ validateLenses: false,
57
+ validateFaceMask: false,
58
+ validateHeadCover: false,
59
+ validateClosedEyes: false,
60
+ validateBrightness: false,
61
+ deepsightLiveness: "SINGLE_FRAME",
62
+ ds: false
63
+ };
64
+ const PERSONHOOD_CAMERA_CONSTRAINTS = {
65
+ video: {
66
+ facingMode: "user",
67
+ height: { ideal: 480 },
68
+ width: { ideal: 640 }
69
+ },
70
+ audio: false
71
+ };
72
+ /**
73
+ * Boots the Deepsight session used to back-stop the on-device liveness check.
74
+ * Independent of `initializePersonhoodCamera` so the two can proceed in
75
+ * parallel during the permission / collect-signals phase.
76
+ */
77
+ async function initializePersonhoodDeepsight(params) {
78
+ return initializeDeepsightSession({
79
+ storage: params.storage,
80
+ ds: false
81
+ });
82
+ }
83
+ /**
84
+ * Boots the camera stream and WASM face-detection pipeline as fast as
85
+ * possible after the user grants permission. Optimized for low latency
86
+ * between "permission granted" and "avatar begins tracking":
87
+ *
88
+ * 1. WASM model loading and `getUserMedia` run **in parallel** — they're
89
+ * independent I/O and were previously sequential, which stacked
90
+ * 50-500ms of avoidable latency.
91
+ * 2. Deepsight PRC warmup (anti-spoof pipeline priming) is fired as a
92
+ * **background task** after the real stream is open. It's not needed
93
+ * for face detection or pose tracking — only for the post-capture
94
+ * `analyzeFrame` step. `analyzeLiveness` degrades gracefully if PRC
95
+ * hasn't finished in time.
96
+ *
97
+ * Earlier versions opened a second hidden camera stream for PRC warmup
98
+ * BEFORE opening the real one, which on Safari/Firefox serialized the
99
+ * two `getUserMedia` calls and added visible lag before the avatar came
100
+ * alive.
101
+ */
102
+ async function initializePersonhoodCamera(params) {
103
+ const provider = new FaceDetectionProvider();
104
+ const [initResult, streamResult] = await Promise.allSettled([provider.initialize({ autocaptureInterval: PERSONHOOD_FACE_CAPTURE_CONFIG.autoCaptureTimeout * 1e3 }), requestCameraAccess(PERSONHOOD_CAMERA_CONSTRAINTS)]);
105
+ if (streamResult.status === "rejected") {
106
+ if (initResult.status === "fulfilled") provider.dispose();
107
+ throw streamResult.reason;
108
+ }
109
+ const stream = streamResult.value;
110
+ if (initResult.status === "rejected") {
111
+ stopCameraStream(stream);
112
+ throw initResult.reason;
113
+ }
114
+ provider.setChecksEnabled({
115
+ lenses: false,
116
+ mask: false,
117
+ closedEyes: false,
118
+ headWear: false,
119
+ occlusion: false
120
+ });
121
+ if (params.deepsightService) params.deepsightService.performPrcCheck({ constraints: PERSONHOOD_CAMERA_CONSTRAINTS }).catch(() => {});
122
+ return {
123
+ stream,
124
+ provider
125
+ };
126
+ }
127
+ /**
128
+ * Wraps the existing face-capture detection loop for the Personhood flow.
129
+ *
130
+ * - Drops the captured canvas (we never upload the raw frame).
131
+ * - Forwards per-frame `onFaceData` into `onPose` so the avatar can mirror
132
+ * the user's head in real time.
133
+ */
134
+ const AUTO_COMPLETE_DEADLINE_MS = 4e3;
135
+ function runPersonhoodDetection(params) {
136
+ let forcedCaptureFired = false;
137
+ const timer = BrowserTimerProvider.getInstance();
138
+ let autoCompleteTimer = null;
139
+ let autoCompleteArmed = false;
140
+ const cancelAutoComplete = () => {
141
+ if (autoCompleteTimer !== null) {
142
+ timer.clearTimeout(autoCompleteTimer);
143
+ autoCompleteTimer = null;
144
+ }
145
+ };
146
+ const fireForceCapture = () => {
147
+ if (forcedCaptureFired) return;
148
+ forcedCaptureFired = true;
149
+ cancelAutoComplete();
150
+ params.provider.forceCapture();
151
+ };
152
+ const armAutoComplete = () => {
153
+ if (autoCompleteArmed) return;
154
+ autoCompleteArmed = true;
155
+ if (!params.autoComplete) return;
156
+ autoCompleteTimer = timer.setTimeout(() => {
157
+ autoCompleteTimer = null;
158
+ fireForceCapture();
159
+ }, AUTO_COMPLETE_DEADLINE_MS);
160
+ };
161
+ const innerResult = startDetection({
162
+ config: PERSONHOOD_FACE_CAPTURE_CONFIG,
163
+ capturer: params.capturer,
164
+ provider: params.provider,
165
+ onUpdate: params.onStatus,
166
+ onFrame: () => armAutoComplete(),
167
+ onPose: (face, frameSize) => {
168
+ let faceSizeRatio;
169
+ if (frameSize && frameSize.width > 0 && frameSize.height > 0 && face.rect.width > 0 && face.rect.height > 0) faceSizeRatio = Math.sqrt(face.rect.width * face.rect.height) / Math.min(frameSize.width, frameSize.height);
170
+ params.onPose({
171
+ pitch: face.pitch,
172
+ yaw: face.yaw,
173
+ roll: face.roll,
174
+ faceSizeRatio
175
+ });
176
+ },
177
+ onSuccess: (canvas) => {
178
+ cancelAutoComplete();
179
+ params.onSuccess(canvas);
180
+ }
181
+ });
182
+ return {
183
+ cleanup: () => {
184
+ cancelAutoComplete();
185
+ innerResult.cleanup();
186
+ },
187
+ reset: innerResult.reset
188
+ };
189
+ }
190
+ /**
191
+ * Runs the Deepsight pipeline against the stream + captured frame and pairs
192
+ * the result with the locally-observed pose motion. All work happens on the
193
+ * device — no network round-trip.
194
+ *
195
+ * The returned `LivenessOutcome` is fed into {@link produceLocalVerdict}:
196
+ * - `virtualCamera: true` → hard reject (OBS/ManyCam)
197
+ * - `analysisStatus !== 'PASS'` → reject with `spoof_suspected`
198
+ * - `yawRange + pitchRange < MIN_POSE_MOTION_DEG` → reject with `no_motion`
199
+ */
200
+ async function analyzeLiveness(params) {
201
+ let virtualCamera = false;
202
+ let analysisStatus = "";
203
+ let motionStatus = "";
204
+ let metadata = "";
205
+ let pipelineState = "";
206
+ const deepsight = params.deepsightService;
207
+ if (deepsight) {
208
+ try {
209
+ const videoTrack = params.stream?.getVideoTracks()[0];
210
+ if (videoTrack) virtualCamera = await deepsight.checkVirtualCamera(videoTrack);
211
+ } catch {}
212
+ try {
213
+ await deepsight.performVirtualCameraCheck(params.token ?? null, "SELFIE");
214
+ } catch {}
215
+ try {
216
+ const imageData = params.capturedImage?.getImageData();
217
+ if (imageData) await deepsight.analyzeFrame(imageData);
218
+ } catch {}
219
+ try {
220
+ analysisStatus = deepsight.getAnalysisStatus();
221
+ motionStatus = deepsight.getMotionStatus();
222
+ pipelineState = deepsight.getPipelineState();
223
+ metadata = deepsight.getMetadata();
224
+ } catch {}
225
+ }
226
+ return {
227
+ virtualCamera,
228
+ analysisStatus,
229
+ motionStatus,
230
+ yawRange: params.yawRange,
231
+ pitchRange: params.pitchRange,
232
+ metadata,
233
+ pipelineState
234
+ };
235
+ }
236
+ /**
237
+ * Minimum combined yaw+pitch range (in degrees) required across the
238
+ * detection window to clear the no-motion guard. A static photo or a
239
+ * face with no head movement will fall below this.
240
+ */
241
+ const MIN_POSE_MOTION_DEG = 4;
242
+ /**
243
+ * Upper bound of motion (degrees) that adds confidence — beyond this,
244
+ * additional head movement doesn't increase our belief that there's a
245
+ * human (and may just be noise from a moving phone).
246
+ */
247
+ const MAX_POSE_MOTION_FOR_BONUS_DEG = 50;
248
+ /**
249
+ * Ceiling for on-device verdicts. Intentionally below 1.0 — nothing short
250
+ * of a signed server round-trip should claim perfect confidence, and the
251
+ * ceiling is strictly below what a server verdict would return so the two
252
+ * paths are distinguishable to integrators.
253
+ */
254
+ const LOCAL_CONFIDENCE_CEILING = .95;
255
+ /**
256
+ * Default pass threshold when `PersonhoodConfig.threshold` is omitted. Single
257
+ * source of truth — keep `PersonhoodConfig.threshold`'s JSDoc and PERSONHOOD.md
258
+ * in sync with this value. (A clean local pass without strong head motion lands
259
+ * around here, so this is the effective on-device gate.)
260
+ */
261
+ const DEFAULT_PERSONHOOD_THRESHOLD = .75;
262
+ /**
263
+ * Produces a verdict entirely on-device using an **additive** confidence
264
+ * model. Each positive signal contributes a measurable amount to the score;
265
+ * penalties subtract. This means clean passes vary — a user who swings
266
+ * through a full head turn scores higher than one who barely moves — which
267
+ * is useful for integrators that want to tune their own thresholds.
268
+ *
269
+ * Positive signals (contribute up to +0.95):
270
+ * - Successful detection → +0.25
271
+ * - Pose motion (linear from min to max) → up to +0.25
272
+ * - Clean device signals (no automation) → +0.05
273
+ * - Deepsight analysis: no explicit spoof → +0.05
274
+ * - Deepsight motion status == PASS → +0.05
275
+ * - Baseline presence → +0.30
276
+ *
277
+ * Penalties (hard rejects or large deductions):
278
+ * - `navigator.webdriver` true → -0.9
279
+ * - Automation markers → -0.9
280
+ * - Headless hints → -0.3
281
+ * - Virtual camera detected → -0.9
282
+ * - Explicit spoof/injection in analysis → -0.4
283
+ * - No head motion (below MIN_POSE_MOTION) → -0.5
284
+ * - Detection didn't reach 'success' → -0.2
285
+ */
286
+ function produceLocalVerdict(params) {
287
+ const threshold = params.threshold ?? DEFAULT_PERSONHOOD_THRESHOLD;
288
+ const reasons = [];
289
+ let confidence = .4;
290
+ if (params.detectionOutcome === "success") confidence += .25;
291
+ else {
292
+ reasons.push(`detection:${params.detectionOutcome}`);
293
+ confidence -= .2;
294
+ }
295
+ if (params.liveness) {
296
+ const motion = params.liveness.yawRange + params.liveness.pitchRange;
297
+ if (motion < MIN_POSE_MOTION_DEG) {
298
+ reasons.push("no_motion");
299
+ confidence -= .5;
300
+ } else {
301
+ const span = MAX_POSE_MOTION_FOR_BONUS_DEG - MIN_POSE_MOTION_DEG;
302
+ const motionRatio = Math.min(1, Math.max(0, (motion - MIN_POSE_MOTION_DEG) / span));
303
+ confidence += .25 * motionRatio;
304
+ }
305
+ if (!hasExplicitSpoofSignal(params.liveness.analysisStatus)) confidence += .05;
306
+ else {
307
+ reasons.push("spoof_suspected");
308
+ confidence -= .4;
309
+ }
310
+ if (isMotionStatusPass(params.liveness.motionStatus)) confidence += .05;
311
+ }
312
+ if (!(params.signals.webdriver || params.signals.emulator || params.signals.headlessHints.length > 0)) confidence += .05;
313
+ if (params.signals.webdriver) {
314
+ reasons.push("webdriver");
315
+ confidence -= .9;
316
+ }
317
+ if (params.signals.emulator) {
318
+ reasons.push("emulator");
319
+ confidence -= .9;
320
+ }
321
+ const SUBSUMED_HINTS = new Set(["navigator.webdriver", "automation-marker"]);
322
+ if (params.signals.headlessHints.filter((hint) => !SUBSUMED_HINTS.has(hint)).length > 0) {
323
+ reasons.push("headless");
324
+ confidence -= .3;
325
+ }
326
+ if (params.liveness?.virtualCamera) {
327
+ reasons.push("virtual_camera");
328
+ confidence -= .9;
329
+ }
330
+ confidence = Math.min(LOCAL_CONFIDENCE_CEILING, Math.max(0, confidence));
331
+ confidence = Math.round(confidence * 1e3) / 1e3;
332
+ if (confidence < threshold && reasons.length === 0) reasons.push("low_confidence");
333
+ const human = confidence >= threshold && reasons.length === 0;
334
+ return {
335
+ human,
336
+ confidence,
337
+ evidenceId: generateEvidenceId(params.siteKey),
338
+ reason: human ? void 0 : reasons.join(","),
339
+ signals: params.signals,
340
+ liveness: params.liveness,
341
+ spoofCheckResults: buildSpoofCheckResults({
342
+ signals: params.signals,
343
+ liveness: params.liveness,
344
+ detectionOutcome: params.detectionOutcome
345
+ })
346
+ };
347
+ }
348
+ function isMotionStatusPass(status) {
349
+ return status.trim().toUpperCase() === "PASS";
350
+ }
351
+ /**
352
+ * Tests whether the Deepsight analysis status contains an explicit spoof /
353
+ * injection / fail signal.
354
+ *
355
+ * The WASM's `getCheck()` returns a pipeline-state blob intended primarily
356
+ * for backend consumption — the server is what turns the blob into a
357
+ * pass/fail. In phase 0 (no session, no backend round-trip) we intentionally
358
+ * only treat the output as a negative signal when it contains an explicit
359
+ * failure token; everything else is indeterminate and we defer to the
360
+ * other local checks (virtual camera + pose motion + device signals).
361
+ *
362
+ * Without this, every clean capture in a session-less dev demo was
363
+ * erroneously flagged as spoof_suspected because the WASM didn't emit
364
+ * literally "PASS".
365
+ */
366
+ function hasExplicitSpoofSignal(status) {
367
+ const normalized = status.toUpperCase();
368
+ return normalized.includes("FAIL") || normalized.includes("SPOOF") || normalized.includes("INJECTION");
369
+ }
370
+ /**
371
+ * Requests a server-side verdict when the browser can't run the on-device
372
+ * liveness pass (no camera, blocked permission, incompatible browser). The
373
+ * same API surface is returned to the widget so integrators see a single
374
+ * universal `{ human, confidence, evidence_id }` shape.
375
+ *
376
+ * The confidence returned by this path is intentionally capped below the
377
+ * on-device ceiling — with no camera we can only score device / behavioural
378
+ * signals, which are weaker evidence of humanness.
379
+ */
380
+ async function requestServerFallbackVerdict(params) {
381
+ if (params.mockFallback) return mockServerFallback(params);
382
+ try {
383
+ const res = await api.post(endpoints.personhoodServerFallback, {
384
+ siteKey: params.siteKey,
385
+ signals: params.signals,
386
+ reason: params.reason
387
+ }, { signal: params.signal });
388
+ if (!res.ok) throw new Error(`POST ${endpoints.personhoodServerFallback} failed: ${res.status} ${res.statusText}`);
389
+ return res.data;
390
+ } catch (error) {
391
+ if (isApiNotConfigured(error)) return mockServerFallback(params);
392
+ throw error;
393
+ }
394
+ }
395
+ async function mockServerFallback(params) {
396
+ await sleep(200);
397
+ const blocked = params.signals.webdriver || params.signals.emulator || params.signals.headlessHints.length > 0;
398
+ const spoofCheckResults = buildSpoofCheckResults({
399
+ signals: params.signals,
400
+ liveness: void 0,
401
+ detectionOutcome: "error"
402
+ });
403
+ if (blocked) return {
404
+ human: false,
405
+ confidence: .1,
406
+ evidenceId: generateEvidenceId(params.siteKey),
407
+ reason: "automation_markers",
408
+ signals: params.signals,
409
+ spoofCheckResults
410
+ };
411
+ return {
412
+ human: true,
413
+ confidence: .72,
414
+ evidenceId: generateEvidenceId(params.siteKey),
415
+ reason: `fallback:${params.reason}`,
416
+ signals: params.signals,
417
+ spoofCheckResults
418
+ };
419
+ }
420
+ /**
421
+ * Pulls a token string out of `/omni/personhood/token`'s response,
422
+ * regardless of which envelope the backend uses. The Incode service
423
+ * surface has historically returned tokens under several keys
424
+ * (`token`, `interviewToken`, `sessionToken`, `access_token`, raw
425
+ * `id`) and a few endpoints return the bare string in the body.
426
+ * Trying each in order and returning the first non-empty value
427
+ * means we don't have to second-guess the contract — when the
428
+ * backend changes shape, the diagnostic log of `res.data` in the
429
+ * caller still surfaces the raw response.
430
+ */
431
+ function extractTokenFromResponse(data) {
432
+ if (typeof data === "string" && data.length > 0) return data;
433
+ if (data && typeof data === "object") {
434
+ const obj = data;
435
+ const candidates = [
436
+ obj.token,
437
+ obj.interviewToken,
438
+ obj.sessionToken,
439
+ obj.access_token,
440
+ obj.accessToken,
441
+ obj.id,
442
+ obj.data?.token,
443
+ obj.data?.interviewToken
444
+ ];
445
+ for (const candidate of candidates) if (typeof candidate === "string" && candidate.length > 0) return candidate;
446
+ }
447
+ }
448
+ /**
449
+ * Pulls the verify endpoint's authoritative pass/fail boolean out
450
+ * of its response, regardless of envelope. Current backend
451
+ * contract: `{ "isHuman": boolean }`. Older / forward-compat
452
+ * shapes also tried so a server-side rename doesn't silently break
453
+ * the client. Returns `undefined` only when no recognizable field
454
+ * is present — caller treats that as "trust the local verdict".
455
+ */
456
+ function extractIsHumanFromResponse(data) {
457
+ if (typeof data === "boolean") return data;
458
+ if (data && typeof data === "object") {
459
+ const obj = data;
460
+ const candidates = [
461
+ obj.isHuman,
462
+ obj.human,
463
+ obj.passed,
464
+ obj.data?.isHuman,
465
+ obj.data?.human,
466
+ obj.result?.isHuman
467
+ ];
468
+ for (const candidate of candidates) if (typeof candidate === "boolean") return candidate;
469
+ }
470
+ }
471
+ /**
472
+ * Mints the personhood `Authorization: Bearer` token via the OAuth2
473
+ * client-credentials grant against {@link endpoints.personhoodOAuthToken}
474
+ * (`POST /omni/oauth2/token`, `application/x-www-form-urlencoded`,
475
+ * `grant_type=client_credentials&scope=openid`). Returns the
476
+ * `access_token` (a signed JWT); the caller (state machine `fetchToken`
477
+ * actor) lands it in actor context where downstream services receive it
478
+ * as an explicit input. No module-level slot — concurrent personhood
479
+ * instances stay isolated, and `actor.stop()` cleans up implicitly.
480
+ *
481
+ * Mock path returns a `mock-token-*` string after a short delay so
482
+ * `mockVerify=true` flows complete without a configured backend.
483
+ *
484
+ * Replaces the removed `GET /omni/personhood/token` (ENG-45783).
485
+ */
486
+ async function fetchPersonhoodAuthToken(params = {}) {
487
+ if (params.mockVerify) {
488
+ await sleep(50);
489
+ return `mock-token-${randomUUID()}`;
490
+ }
491
+ const form = {
492
+ grant_type: "client_credentials",
493
+ scope: "openid"
494
+ };
495
+ if (params.clientId) form.client_id = params.clientId;
496
+ if (params.clientSecret) form.client_secret = params.clientSecret;
497
+ const body = new URLSearchParams(form).toString();
498
+ const authPath = params.authBaseUrl ? endpoints.personhoodOAuthTokenDirect : endpoints.personhoodOAuthToken;
499
+ const reqConfig = {
500
+ signal: params.signal,
501
+ headers: { "Content-Type": "application/x-www-form-urlencoded" }
502
+ };
503
+ try {
504
+ let res;
505
+ if (params.authBaseUrl) res = await createApi_default({
506
+ apiURL: params.authBaseUrl,
507
+ customHeaders: getStoredHttpConfig()?.customHeaders
508
+ }).post(authPath, body, reqConfig);
509
+ else res = await api.post(authPath, body, reqConfig);
510
+ if (!res.ok) throw new Error(`POST ${authPath} failed: ${res.status} ${res.statusText}`);
511
+ const token = extractTokenFromResponse(res.data);
512
+ if (!token) throw new Error(`POST ${authPath} returned no access_token`);
513
+ return token;
514
+ } catch (error) {
515
+ if (isApiNotConfigured(error)) return fetchPersonhoodAuthToken({
516
+ ...params,
517
+ mockVerify: true
518
+ });
519
+ throw error;
520
+ }
521
+ }
522
+ /**
523
+ * Builds the full per-check breakdown that lands on
524
+ * {@link PersonhoodVerdict.spoofCheckResults} and in the verify
525
+ * POST body. One entry per check the SDK ran, with a stable id, a
526
+ * `passed | failed | unknown` outcome, and (on failure) a short
527
+ * tag the server can pattern-match on.
528
+ *
529
+ * This is the single source of truth for "what did the on-device
530
+ * pipeline check?" — both {@link produceLocalVerdict} and the
531
+ * verify POST consume it. Adding a new check here automatically
532
+ * surfaces it to integrators and to the backend without touching
533
+ * the state machine or the verify wire format.
534
+ *
535
+ * Conservative defaults: when a pipeline didn't run (no liveness
536
+ * outcome / Deepsight not initialized), the dependent checks are
537
+ * reported as `unknown`. This lets the server distinguish "we
538
+ * tested and the user passed" from "we couldn't test", which is a
539
+ * meaningful gradient for risk scoring.
540
+ */
541
+ function buildSpoofCheckResults(params) {
542
+ const results = [];
543
+ const { signals, liveness, detectionOutcome } = params;
544
+ if (detectionOutcome === "success") results.push({
545
+ check: "faceDetection",
546
+ result: "passed"
547
+ });
548
+ else results.push({
549
+ check: "faceDetection",
550
+ result: "failed",
551
+ reason: `detection:${detectionOutcome}`
552
+ });
553
+ if (liveness) {
554
+ if (liveness.analysisStatus === "PASS") results.push({
555
+ check: "physicalAttack",
556
+ result: "passed"
557
+ });
558
+ else if (hasExplicitSpoofSignal(liveness.analysisStatus)) results.push({
559
+ check: "physicalAttack",
560
+ result: "failed",
561
+ reason: liveness.analysisStatus || "spoof_suspected"
562
+ });
563
+ else results.push({
564
+ check: "physicalAttack",
565
+ result: "unknown"
566
+ });
567
+ results.push({
568
+ check: "virtualCamera",
569
+ result: liveness.virtualCamera ? "failed" : "passed",
570
+ ...liveness.virtualCamera ? { reason: "virtual_camera" } : {}
571
+ });
572
+ if (liveness.motionStatus === "PASS") results.push({
573
+ check: "motionLiveness",
574
+ result: "passed"
575
+ });
576
+ else if (liveness.motionStatus === "FAIL") results.push({
577
+ check: "motionLiveness",
578
+ result: "failed",
579
+ reason: "no_motion"
580
+ });
581
+ else results.push({
582
+ check: "motionLiveness",
583
+ result: "unknown"
584
+ });
585
+ if (liveness.yawRange + liveness.pitchRange >= MIN_POSE_MOTION_DEG) results.push({
586
+ check: "headMotion",
587
+ result: "passed"
588
+ });
589
+ else results.push({
590
+ check: "headMotion",
591
+ result: "failed",
592
+ reason: "no_motion"
593
+ });
594
+ } else {
595
+ results.push({
596
+ check: "physicalAttack",
597
+ result: "unknown"
598
+ });
599
+ results.push({
600
+ check: "virtualCamera",
601
+ result: "unknown"
602
+ });
603
+ results.push({
604
+ check: "motionLiveness",
605
+ result: "unknown"
606
+ });
607
+ results.push({
608
+ check: "headMotion",
609
+ result: "unknown"
610
+ });
611
+ }
612
+ results.push({
613
+ check: "webdriver",
614
+ result: signals.webdriver ? "failed" : "passed",
615
+ ...signals.webdriver ? { reason: "webdriver" } : {}
616
+ });
617
+ results.push({
618
+ check: "emulator",
619
+ result: signals.emulator ? "failed" : "passed",
620
+ ...signals.emulator ? { reason: "emulator" } : {}
621
+ });
622
+ const independentHeadlessHints = signals.headlessHints.filter((hint) => hint !== "navigator.webdriver" && hint !== "automation-marker");
623
+ results.push({
624
+ check: "headlessBrowser",
625
+ result: independentHeadlessHints.length > 0 ? "failed" : "passed",
626
+ ...independentHeadlessHints.length > 0 ? { reason: independentHeadlessHints.join(",") } : {}
627
+ });
628
+ return results;
629
+ }
630
+ /**
631
+ * Trims the rich client-side {@link SpoofCheckResult} array down to the wire
632
+ * shape the verify POST expects: `check` + `result` only (the `reason` field is
633
+ * dropped — not part of the contract). Entry order is preserved so the server
634
+ * sees them in detection-pipeline order (face → physical → virtual → motion →
635
+ * head → automation). `unknown` results are passed through as-is —
636
+ * `SpoofCheckResultWire.result` is `'passed' | 'failed' | 'unknown'`. (Whether
637
+ * the backend should instead receive only `passed | failed` is an open
638
+ * server-contract question, tracked with the wider verify-contract work.)
639
+ */
640
+ function toWireSpoofCheckResults(results) {
641
+ const wire = [];
642
+ for (const entry of results) wire.push({
643
+ check: entry.check,
644
+ result: entry.result
645
+ });
646
+ return wire;
647
+ }
648
+ /**
649
+ * On-device verify hop — POST `/omni/personhood/verify` with the
650
+ * Deepsight metadata + derived `spoofCheckResults`. The personhood
651
+ * Bearer token (passed in via `params.token`, minted by the OAuth2
652
+ * client-credentials hop and threaded through actor context) is
653
+ * attached as `Authorization: Bearer <token>`.
654
+ *
655
+ * When the server returns a recognizable `isHuman` boolean, that
656
+ * value becomes the authoritative pass/fail on the returned
657
+ * verdict. Otherwise (HTTP error, missing field, network blip,
658
+ * SDK not configured) we fall back to the local on-device verdict
659
+ * the caller passed in — keeping the widget functional in flaky
660
+ * conditions. `mockVerify: true` short-circuits to the fallback
661
+ * verdict without hitting the network.
662
+ */
663
+ async function verifyPersonhoodOnDevice(params) {
664
+ if (params.mockVerify) {
665
+ await sleep(50);
666
+ return params.fallbackVerdict;
667
+ }
668
+ try {
669
+ const personhoodToken = params.token;
670
+ const res = await api.post(endpoints.personhoodOnDeviceVerify, {
671
+ metadata: params.metadata,
672
+ spoofCheckResults: toWireSpoofCheckResults(params.spoofCheckResults)
673
+ }, {
674
+ signal: params.signal,
675
+ ...personhoodToken ? { headers: { Authorization: `Bearer ${personhoodToken}` } } : {}
676
+ });
677
+ if (!res.ok) throw new Error(`POST ${endpoints.personhoodOnDeviceVerify} failed: ${res.status} ${res.statusText}`);
678
+ const serverData = res.data;
679
+ const serverIsHuman = extractIsHumanFromResponse(serverData);
680
+ if (typeof serverIsHuman !== "boolean") return params.fallbackVerdict;
681
+ const finalReason = serverIsHuman ? void 0 : params.fallbackVerdict.reason ?? "server_rejected";
682
+ return {
683
+ ...params.fallbackVerdict,
684
+ human: serverIsHuman,
685
+ confidence: serverIsHuman ? .95 : .05,
686
+ reason: finalReason
687
+ };
688
+ } catch {
689
+ return params.fallbackVerdict;
690
+ }
691
+ }
692
+ function isApiNotConfigured(error) {
693
+ return error instanceof Error && error.message.includes("SDK not configured");
694
+ }
695
+ function generateEvidenceId(siteKey) {
696
+ return `ph_${(siteKey || "site").replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 12)}_${randomUUID().replace(/-/g, "")}`;
697
+ }
698
+
699
+ //#endregion
700
+ //#region src/modules/personhood/personhoodSignals.ts
701
+ /**
702
+ * Returns a placeholder {@link DeviceBehavioralSignals} for the
703
+ * narrow set of code paths that need to operate before the real
704
+ * `collectDeviceBehavioralSignals()` has resolved (or where it
705
+ * errored out and the parallel `signals` branch landed in `done`
706
+ * with `context.signals` still undefined). Single source of truth
707
+ * — every call site that previously inlined this literal now
708
+ * imports from here.
709
+ */
710
+ function emptySignals() {
711
+ return {
712
+ deviceFingerprint: "",
713
+ userAgentClass: "unknown",
714
+ emulator: false,
715
+ webdriver: false,
716
+ headlessHints: []
717
+ };
718
+ }
719
+ /**
720
+ * Collects the device + behavioural bundle returned alongside the human
721
+ * verdict. Intentionally offline-only (no IP geolookup) so a Personhood check
722
+ * does not pay the latency of an external call in the hot path.
723
+ *
724
+ * The bundle is **opaque to the SDK** — the integrator uses these signals for
725
+ * their own dedup/risk logic. Personhood itself does NOT re-identify the human.
726
+ *
727
+ * `deviceFingerprint` is gated by `setup({ fingerprint })` (default enabled)
728
+ * — mirrors how `deepsightLoader` resolves `disableFingerprint` from the same
729
+ * flag. When disabled, the Thumbmark call is skipped and `deviceFingerprint`
730
+ * is `''`.
731
+ */
732
+ async function collectDeviceBehavioralSignals() {
733
+ const browserEnv = new BrowserEnvironmentProvider();
734
+ const [deviceFingerprint, deviceInfo] = await Promise.all([getFingerprintEnabled() ? safeGetFingerprint() : Promise.resolve(""), safeGetDeviceInfo()]);
735
+ const webdriver = Boolean(browserEnv.getNavigatorProperty("webdriver"));
736
+ const emulator = isBrowserSimulation(browserEnv);
737
+ const headlessHints = [];
738
+ if (webdriver) headlessHints.push("navigator.webdriver");
739
+ if (emulator) headlessHints.push("automation-marker");
740
+ const plugins = browserEnv.getNavigatorProperty("plugins");
741
+ const userAgent = browserEnv.getNavigatorProperty("userAgent")?.toLowerCase();
742
+ if (plugins && typeof plugins.length === "number" && plugins.length === 0 && userAgent?.includes("headless")) headlessHints.push("headless-user-agent");
743
+ return {
744
+ deviceFingerprint,
745
+ userAgentClass: formatUserAgentClass(deviceInfo),
746
+ emulator,
747
+ webdriver,
748
+ headlessHints
749
+ };
750
+ }
751
+ function formatUserAgentClass(info) {
752
+ if (!info) return "unknown";
753
+ const parts = [
754
+ info.browser?.name,
755
+ info.browser?.version,
756
+ info.os?.name,
757
+ info.os?.version,
758
+ info.device?.model
759
+ ].filter((part) => typeof part === "string" && part.length > 0);
760
+ return parts.length > 0 ? parts.join(" / ") : "unknown";
761
+ }
762
+ async function safeGetFingerprint() {
763
+ try {
764
+ return await getThumbmarkId();
765
+ } catch {
766
+ return "";
767
+ }
768
+ }
769
+ async function safeGetDeviceInfo() {
770
+ try {
771
+ return await getDeviceFingerprintInfo();
772
+ } catch {
773
+ return;
774
+ }
775
+ }
776
+
777
+ //#endregion
778
+ //#region src/modules/personhood/types.ts
779
+ const PERSONHOOD_ERROR_CODES = {
780
+ CAMERA_DENIED: "CAMERA_DENIED",
781
+ DETECTION_FAILED: "DETECTION_FAILED",
782
+ AUTH_TOKEN_FAILED: "AUTH_TOKEN_FAILED",
783
+ VERIFY_FAILED: "VERIFY_FAILED",
784
+ INJECTION_SUSPECTED: "INJECTION_SUSPECTED",
785
+ EMULATOR_DETECTED: "EMULATOR_DETECTED",
786
+ TIMEOUT: "TIMEOUT",
787
+ UNKNOWN: "UNKNOWN"
788
+ };
789
+
790
+ //#endregion
791
+ //#region src/modules/personhood/personhoodStateMachine.ts
792
+ const _personhoodMachine = setup({
793
+ types: {
794
+ context: {},
795
+ events: {},
796
+ input: {}
797
+ },
798
+ actors: {
799
+ checkPermission: fromPromise(async () => {
800
+ return checkPermission();
801
+ }),
802
+ requestPermission: fromPromise(async () => {
803
+ return requestPermission({ requestMotion: false });
804
+ }),
805
+ initializeCamera: fromPromise(async ({ input }) => {
806
+ return initializePersonhoodCamera({ deepsightService: input.deepsightService });
807
+ }),
808
+ initializeDeepsight: fromPromise(async ({ input }) => {
809
+ return initializePersonhoodDeepsight({ storage: input.dependencies.storage });
810
+ }),
811
+ collectSignals: fromPromise(async () => {
812
+ return collectDeviceBehavioralSignals();
813
+ }),
814
+ analyzeLiveness: fromPromise(async ({ input }) => {
815
+ return analyzeLiveness(input);
816
+ }),
817
+ runDetection: fromCallback(({ input, sendBack }) => {
818
+ let yawMin = Infinity;
819
+ let yawMax = -Infinity;
820
+ let pitchMin = Infinity;
821
+ let pitchMax = -Infinity;
822
+ const { cleanup, reset } = runPersonhoodDetection({
823
+ provider: input.provider,
824
+ capturer: input.frameCapturer,
825
+ autoComplete: input.autoComplete,
826
+ onStatus: (status) => sendBack({
827
+ type: "DETECTION_UPDATE",
828
+ status
829
+ }),
830
+ onPose: (pose) => {
831
+ if (pose.yaw < yawMin) yawMin = pose.yaw;
832
+ if (pose.yaw > yawMax) yawMax = pose.yaw;
833
+ if (pose.pitch < pitchMin) pitchMin = pose.pitch;
834
+ if (pose.pitch > pitchMax) pitchMax = pose.pitch;
835
+ },
836
+ onSuccess: (canvas) => {
837
+ sendBack({
838
+ type: "DETECTION_SUCCESS",
839
+ canvas,
840
+ yawRange: yawMax > yawMin ? yawMax - yawMin : 0,
841
+ pitchRange: pitchMax > pitchMin ? pitchMax - pitchMin : 0
842
+ });
843
+ }
844
+ });
845
+ sendBack({
846
+ type: "DETECTION_RESET_READY",
847
+ reset
848
+ });
849
+ return cleanup;
850
+ }),
851
+ produceLocalVerdict: fromPromise(async ({ input }) => {
852
+ return produceLocalVerdict({
853
+ siteKey: input.config.siteKey,
854
+ threshold: input.config.threshold,
855
+ signals: input.signals,
856
+ detectionOutcome: input.detectionStatus,
857
+ liveness: input.liveness
858
+ });
859
+ }),
860
+ requestServerFallback: fromPromise(async ({ input, signal }) => {
861
+ return requestServerFallbackVerdict({
862
+ siteKey: input.config.siteKey,
863
+ signals: input.signals,
864
+ reason: input.reason,
865
+ mockFallback: input.config.mockVerify,
866
+ signal
867
+ });
868
+ }),
869
+ fetchToken: fromPromise(async ({ input, signal }) => {
870
+ return fetchPersonhoodAuthToken({
871
+ clientId: input.config.clientId,
872
+ clientSecret: input.config.clientSecret,
873
+ authBaseUrl: input.config.authBaseUrl,
874
+ mockVerify: input.config.mockVerify,
875
+ signal
876
+ });
877
+ }),
878
+ verifyOnDevice: fromPromise(async ({ input, signal }) => {
879
+ return verifyPersonhoodOnDevice({
880
+ metadata: input.liveness?.metadata ?? "",
881
+ spoofCheckResults: input.localVerdict.spoofCheckResults,
882
+ fallbackVerdict: input.localVerdict,
883
+ mockVerify: input.config.mockVerify,
884
+ token: input.token,
885
+ signal
886
+ });
887
+ })
888
+ },
889
+ actions: {
890
+ setStreamAndProvider: assign(({ event }) => {
891
+ const output = event.output;
892
+ return {
893
+ stream: output.stream,
894
+ provider: output.provider,
895
+ frameCapturer: new StreamCanvasCapture(output.stream)
896
+ };
897
+ }),
898
+ setDetectionStatus: assign({ detectionStatus: ({ event }) => event.status }),
899
+ setCapturedImageAndRangeFromEvent: assign(({ event }) => {
900
+ const e = event;
901
+ return {
902
+ capturedImage: e.canvas,
903
+ yawRange: e.yawRange,
904
+ pitchRange: e.pitchRange
905
+ };
906
+ }),
907
+ setDeepsightServiceFromEvent: assign({ deepsightService: ({ event }) => event.output }),
908
+ setLivenessOutcomeFromEvent: assign({ livenessOutcome: ({ event }) => event.output }),
909
+ setResetDetection: assign({ resetDetection: ({ event }) => event.reset }),
910
+ setSignalsFromEvent: assign({ signals: ({ event }) => event.output }),
911
+ setTokenFromEvent: assign({ token: ({ event }) => event.output }),
912
+ setLocalVerdictFromEvent: assign({ localVerdict: ({ event }) => event.output }),
913
+ setVerdictFromEvent: assign({ verdict: ({ event }) => event.output }),
914
+ setPermissionResultFromEvent: assign({ permissionResult: ({ event }) => event.output }),
915
+ setPermissionDenied: assign({
916
+ permissionResult: () => "denied",
917
+ error: () => ({ code: PERSONHOOD_ERROR_CODES.CAMERA_DENIED })
918
+ }),
919
+ setDetectionError: assign({ error: () => ({ code: PERSONHOOD_ERROR_CODES.DETECTION_FAILED }) }),
920
+ setFallbackReasonNoCamera: assign({ fallbackReason: () => "no_camera" }),
921
+ setTokenError: assign({ error: ({ event }) => ({
922
+ code: PERSONHOOD_ERROR_CODES.AUTH_TOKEN_FAILED,
923
+ message: String(event.error ?? "auth token fetch failed")
924
+ }) }),
925
+ setVerifyError: assign({ error: ({ event }) => ({
926
+ code: PERSONHOOD_ERROR_CODES.VERIFY_FAILED,
927
+ message: String(event.error ?? "verify failed")
928
+ }) }),
929
+ setLocalVerdictError: assign({ error: ({ event }) => ({
930
+ code: PERSONHOOD_ERROR_CODES.UNKNOWN,
931
+ message: String(event.error ?? "local verdict synthesis failed")
932
+ }) }),
933
+ setVerdictToLocal: assign({ verdict: ({ context }) => context.localVerdict }),
934
+ stopMediaStream: assign(({ context }) => {
935
+ context.frameCapturer?.dispose();
936
+ if (context.stream) stopStream(context.stream);
937
+ context.provider?.dispose();
938
+ context.deepsightService?.cleanup();
939
+ return {
940
+ stream: void 0,
941
+ provider: void 0,
942
+ frameCapturer: void 0
943
+ };
944
+ }),
945
+ resetContext: assign({
946
+ permissionResult: () => void 0,
947
+ stream: () => void 0,
948
+ provider: () => void 0,
949
+ frameCapturer: () => void 0,
950
+ deepsightService: () => void 0,
951
+ detectionStatus: () => "idle",
952
+ yawRange: () => 0,
953
+ pitchRange: () => 0,
954
+ capturedImage: () => void 0,
955
+ livenessOutcome: () => void 0,
956
+ signals: () => void 0,
957
+ fallbackReason: () => void 0,
958
+ token: () => void 0,
959
+ localVerdict: () => void 0,
960
+ verdict: () => void 0,
961
+ error: () => void 0,
962
+ resetDetection: () => void 0
963
+ }),
964
+ emitSignal: ({ context, event }) => {
965
+ const listener = context.config.onSignal;
966
+ if (!listener) return;
967
+ if (event.type === "DETECTION_UPDATE") listener({
968
+ type: "detection",
969
+ payload: event.status
970
+ });
971
+ }
972
+ },
973
+ guards: {
974
+ hasShowTutorial: ({ context }) => context.config.showTutorial === true,
975
+ isPermissionGranted: ({ event }) => {
976
+ if ("output" in event) return event.output === "granted";
977
+ return false;
978
+ },
979
+ isPermissionDenied: ({ event }) => {
980
+ if ("output" in event) return event.output === "denied";
981
+ return false;
982
+ },
983
+ hasTokenError: ({ context }) => context.error?.code === PERSONHOOD_ERROR_CODES.AUTH_TOKEN_FAILED,
984
+ isDetectionError: ({ event }) => event.status === "error"
985
+ }
986
+ }).createMachine({
987
+ id: "personhood",
988
+ initial: "idle",
989
+ context: ({ input }) => ({
990
+ config: input.config,
991
+ dependencies: input.dependencies,
992
+ permissionResult: void 0,
993
+ fallbackReason: void 0,
994
+ stream: void 0,
995
+ provider: void 0,
996
+ frameCapturer: void 0,
997
+ deepsightService: void 0,
998
+ detectionStatus: "idle",
999
+ yawRange: 0,
1000
+ pitchRange: 0,
1001
+ capturedImage: void 0,
1002
+ livenessOutcome: void 0,
1003
+ signals: void 0,
1004
+ token: void 0,
1005
+ localVerdict: void 0,
1006
+ verdict: void 0,
1007
+ error: void 0,
1008
+ resetDetection: void 0
1009
+ }),
1010
+ on: { QUIT: { target: "#personhood.closed" } },
1011
+ states: {
1012
+ idle: { on: { LOAD: [{
1013
+ target: "tutorial",
1014
+ guard: "hasShowTutorial"
1015
+ }, { target: "collectingSignals" }] } },
1016
+ tutorial: { on: { NEXT_STEP: { target: "collectingSignals" } } },
1017
+ collectingSignals: {
1018
+ type: "parallel",
1019
+ states: {
1020
+ signals: {
1021
+ initial: "running",
1022
+ states: {
1023
+ running: { invoke: {
1024
+ id: "collectSignals",
1025
+ src: "collectSignals",
1026
+ onDone: {
1027
+ target: "done",
1028
+ actions: "setSignalsFromEvent"
1029
+ },
1030
+ onError: { target: "done" }
1031
+ } },
1032
+ done: { type: "final" }
1033
+ }
1034
+ },
1035
+ deepsight: {
1036
+ initial: "running",
1037
+ states: {
1038
+ running: { invoke: {
1039
+ id: "initializeDeepsight",
1040
+ src: "initializeDeepsight",
1041
+ input: ({ context }) => ({ dependencies: context.dependencies }),
1042
+ onDone: {
1043
+ target: "done",
1044
+ actions: "setDeepsightServiceFromEvent"
1045
+ },
1046
+ onError: { target: "done" }
1047
+ } },
1048
+ done: { type: "final" }
1049
+ }
1050
+ },
1051
+ token: {
1052
+ initial: "running",
1053
+ states: {
1054
+ running: { invoke: {
1055
+ id: "fetchToken",
1056
+ src: "fetchToken",
1057
+ input: ({ context }) => ({ config: context.config }),
1058
+ onDone: {
1059
+ target: "done",
1060
+ actions: "setTokenFromEvent"
1061
+ },
1062
+ onError: {
1063
+ target: "done",
1064
+ actions: "setTokenError"
1065
+ }
1066
+ } },
1067
+ done: { type: "final" }
1068
+ }
1069
+ }
1070
+ },
1071
+ onDone: [{
1072
+ target: "error",
1073
+ guard: "hasTokenError"
1074
+ }, { target: "checkingPermission" }]
1075
+ },
1076
+ checkingPermission: { invoke: {
1077
+ id: "checkPermission",
1078
+ src: "checkPermission",
1079
+ onDone: [
1080
+ {
1081
+ target: "capture",
1082
+ guard: "isPermissionGranted",
1083
+ actions: "setPermissionResultFromEvent"
1084
+ },
1085
+ {
1086
+ target: "permissions.denied",
1087
+ guard: "isPermissionDenied",
1088
+ actions: "setPermissionResultFromEvent"
1089
+ },
1090
+ {
1091
+ target: "permissions",
1092
+ actions: "setPermissionResultFromEvent"
1093
+ }
1094
+ ]
1095
+ } },
1096
+ permissions: {
1097
+ initial: "idle",
1098
+ states: {
1099
+ idle: { on: {
1100
+ REQUEST_PERMISSION: "requesting",
1101
+ GO_TO_LEARN_MORE: "learnMore"
1102
+ } },
1103
+ learnMore: { on: {
1104
+ BACK: "idle",
1105
+ REQUEST_PERMISSION: "requesting"
1106
+ } },
1107
+ requesting: { invoke: {
1108
+ id: "requestPermission",
1109
+ src: "requestPermission",
1110
+ onDone: [
1111
+ {
1112
+ target: "#personhood.capture",
1113
+ guard: "isPermissionGranted",
1114
+ actions: "setPermissionResultFromEvent"
1115
+ },
1116
+ {
1117
+ target: "denied",
1118
+ guard: "isPermissionDenied",
1119
+ actions: "setPermissionResultFromEvent"
1120
+ },
1121
+ {
1122
+ target: "idle",
1123
+ actions: "setPermissionResultFromEvent"
1124
+ }
1125
+ ],
1126
+ onError: {
1127
+ target: "denied",
1128
+ actions: "setPermissionDenied"
1129
+ }
1130
+ } },
1131
+ denied: {
1132
+ entry: "setPermissionDenied",
1133
+ on: { USE_FALLBACK: { target: "#personhood.serverFallback" } }
1134
+ }
1135
+ },
1136
+ on: { USE_FALLBACK: { target: "#personhood.serverFallback" } }
1137
+ },
1138
+ capture: {
1139
+ initial: "initializing",
1140
+ states: {
1141
+ initializing: { invoke: {
1142
+ id: "initializeCamera",
1143
+ src: "initializeCamera",
1144
+ input: ({ context }) => ({ deepsightService: context.deepsightService }),
1145
+ onDone: {
1146
+ target: "detecting",
1147
+ actions: "setStreamAndProvider"
1148
+ },
1149
+ onError: {
1150
+ target: "#personhood.serverFallback",
1151
+ actions: "setFallbackReasonNoCamera"
1152
+ }
1153
+ } },
1154
+ detecting: {
1155
+ invoke: {
1156
+ id: "runDetection",
1157
+ src: "runDetection",
1158
+ input: ({ context }) => ({
1159
+ provider: context.provider,
1160
+ frameCapturer: context.frameCapturer,
1161
+ autoComplete: context.config.autoComplete
1162
+ }),
1163
+ onError: {
1164
+ target: "#personhood.error",
1165
+ actions: "setDetectionError"
1166
+ }
1167
+ },
1168
+ on: {
1169
+ DETECTION_UPDATE: [{
1170
+ guard: "isDetectionError",
1171
+ target: "#personhood.error",
1172
+ actions: [
1173
+ "setDetectionStatus",
1174
+ "setDetectionError",
1175
+ "emitSignal"
1176
+ ]
1177
+ }, { actions: ["setDetectionStatus", "emitSignal"] }],
1178
+ DETECTION_RESET_READY: { actions: "setResetDetection" },
1179
+ DETECTION_SUCCESS: {
1180
+ target: "#personhood.analyzing",
1181
+ actions: "setCapturedImageAndRangeFromEvent"
1182
+ }
1183
+ }
1184
+ }
1185
+ }
1186
+ },
1187
+ analyzing: {
1188
+ exit: "stopMediaStream",
1189
+ invoke: {
1190
+ id: "analyzeLiveness",
1191
+ src: "analyzeLiveness",
1192
+ input: ({ context }) => ({
1193
+ deepsightService: context.deepsightService,
1194
+ stream: context.stream,
1195
+ capturedImage: context.capturedImage,
1196
+ yawRange: context.yawRange,
1197
+ pitchRange: context.pitchRange,
1198
+ token: context.token
1199
+ }),
1200
+ onDone: {
1201
+ target: "processing",
1202
+ actions: "setLivenessOutcomeFromEvent"
1203
+ },
1204
+ onError: { target: "processing" }
1205
+ }
1206
+ },
1207
+ processing: { invoke: {
1208
+ id: "produceLocalVerdict",
1209
+ src: "produceLocalVerdict",
1210
+ input: ({ context }) => ({
1211
+ config: context.config,
1212
+ signals: context.signals ?? emptySignals(),
1213
+ detectionStatus: context.detectionStatus,
1214
+ liveness: context.livenessOutcome
1215
+ }),
1216
+ onDone: {
1217
+ target: "verifyingOnServer",
1218
+ actions: "setLocalVerdictFromEvent"
1219
+ },
1220
+ onError: {
1221
+ target: "error",
1222
+ actions: "setLocalVerdictError"
1223
+ }
1224
+ } },
1225
+ verifyingOnServer: { invoke: {
1226
+ id: "verifyOnDevice",
1227
+ src: "verifyOnDevice",
1228
+ input: ({ context }) => ({
1229
+ config: context.config,
1230
+ liveness: context.livenessOutcome,
1231
+ localVerdict: context.localVerdict,
1232
+ token: context.token
1233
+ }),
1234
+ onDone: {
1235
+ target: "finished",
1236
+ actions: "setVerdictFromEvent"
1237
+ },
1238
+ onError: {
1239
+ target: "finished",
1240
+ actions: "setVerdictToLocal"
1241
+ }
1242
+ } },
1243
+ serverFallback: { invoke: {
1244
+ id: "requestServerFallback",
1245
+ src: "requestServerFallback",
1246
+ input: ({ context }) => ({
1247
+ config: context.config,
1248
+ signals: context.signals ?? emptySignals(),
1249
+ reason: context.fallbackReason ?? "permission_denied"
1250
+ }),
1251
+ onDone: {
1252
+ target: "finished",
1253
+ actions: "setVerdictFromEvent"
1254
+ },
1255
+ onError: {
1256
+ target: "error",
1257
+ actions: "setVerifyError"
1258
+ }
1259
+ } },
1260
+ finished: { type: "final" },
1261
+ closed: {
1262
+ entry: "stopMediaStream",
1263
+ type: "final"
1264
+ },
1265
+ error: {
1266
+ entry: "stopMediaStream",
1267
+ on: { RESET: {
1268
+ target: "idle",
1269
+ actions: "resetContext"
1270
+ } }
1271
+ }
1272
+ }
1273
+ });
1274
+ /**
1275
+ * Public machine value. Typed as `AnyStateMachine` for declaration file
1276
+ * portability — mirrors the convention used by `selfieMachine` and the
1277
+ * other Core modules. Type safety is enforced by the `setup()` config
1278
+ * above, not by the exported binding.
1279
+ */
1280
+ const personhoodMachine = _personhoodMachine;
1281
+
1282
+ //#endregion
1283
+ //#region src/modules/personhood/personhoodActor.ts
1284
+ /**
1285
+ * Production-default {@link PersonhoodDependencies}. Browser storage +
1286
+ * the singleton WASM util. Single source of truth for what the actor
1287
+ * and the manager wire up when the caller doesn't provide their own;
1288
+ * tests and the extensibility layer pass `dependencies` explicitly.
1289
+ */
1290
+ function getDefaultPersonhoodDependencies() {
1291
+ return {
1292
+ storage: new BrowserStorageProvider(),
1293
+ getWasmUtil: () => WasmUtilProvider.getInstance()
1294
+ };
1295
+ }
1296
+ /**
1297
+ * Creates and starts a Personhood XState actor. Defaults to the production
1298
+ * browser storage + WASM providers; passing `dependencies` lets tests and the
1299
+ * extensibility layer swap them for fakes.
1300
+ */
1301
+ function createPersonhoodActor(options) {
1302
+ const dependencies = options.dependencies ?? getDefaultPersonhoodDependencies();
1303
+ return createActor(personhoodMachine, { input: {
1304
+ config: options.config,
1305
+ dependencies
1306
+ } }).start();
1307
+ }
1308
+
1309
+ //#endregion
1310
+ //#region src/modules/personhood/personhoodManager.ts
1311
+ /**
1312
+ * Personhood deliberately opts out of the SDK's manager-instrumentation
1313
+ * analytics pipeline. The widget runs as a self-contained modal/inline
1314
+ * captcha replacement, not as part of the broader onboarding funnel —
1315
+ * it doesn't share an onboarding session token (`/omni/start`) with
1316
+ * the rest of an integrator's flow, so the per-transition events the
1317
+ * default instrumentation would emit can't authenticate against
1318
+ * `/omni/interview-events`. Wiring them up only produced a cascade of
1319
+ * 403s in integrators' devtools (one preflight + one POST per
1320
+ * `screenOpened` / `elementClicked` / `captureAttemptFinished` /
1321
+ * `errorTriggered` transition), with no usable analytics signal on
1322
+ * the receiving end.
1323
+ *
1324
+ * `createManager()` requires the `instrumentation` option to be
1325
+ * present, so we pass a no-op that satisfies the contract without
1326
+ * firing any of the helpers. If a future use case calls for
1327
+ * personhood analytics (integrator opt-in, internal QA dashboard,
1328
+ * etc.) the right move is to re-enable `createManagerInstrumentation`
1329
+ * here gated on a config flag — not to remove this no-op.
1330
+ */
1331
+ function createNoopInstrumentation() {
1332
+ return {
1333
+ moduleName: eventModuleNames.personhood,
1334
+ onModuleOpened: () => void 0,
1335
+ onModuleClosed: () => void 0,
1336
+ getScreenName: () => void 0,
1337
+ onScreenOpened: () => void 0,
1338
+ onScreenClosed: () => void 0,
1339
+ getErrorName: () => void 0,
1340
+ getErrorPayload: () => void 0,
1341
+ onErrorTriggered: () => void 0,
1342
+ onElementClicked: () => void 0,
1343
+ onCaptureAttemptFinished: () => void 0
1344
+ };
1345
+ }
1346
+ function getPermissionSubState(snapshot) {
1347
+ if (snapshot.matches({ permissions: "learnMore" })) return "learnMore";
1348
+ if (snapshot.matches({ permissions: "requesting" })) return "requesting";
1349
+ if (snapshot.matches({ permissions: "denied" })) return "denied";
1350
+ return "idle";
1351
+ }
1352
+ function mapState(snapshot) {
1353
+ const context = snapshot.context;
1354
+ if (snapshot.matches("idle")) return { status: "idle" };
1355
+ if (snapshot.matches("tutorial")) return { status: "tutorial" };
1356
+ if (snapshot.matches("collectingSignals")) return {
1357
+ status: "loading",
1358
+ phase: "collectingSignals"
1359
+ };
1360
+ if (snapshot.matches("checkingPermission")) return {
1361
+ status: "loading",
1362
+ phase: "checkingPermission"
1363
+ };
1364
+ if (snapshot.matches("permissions")) return {
1365
+ status: "permissions",
1366
+ permissionStatus: getPermissionSubState(snapshot)
1367
+ };
1368
+ if (snapshot.matches({ capture: "initializing" })) return {
1369
+ status: "capture",
1370
+ captureStatus: "initializing",
1371
+ detectionStatus: context.detectionStatus,
1372
+ stream: context.stream
1373
+ };
1374
+ if (snapshot.matches("capture")) return {
1375
+ status: "capture",
1376
+ captureStatus: "detecting",
1377
+ detectionStatus: context.detectionStatus,
1378
+ stream: context.stream
1379
+ };
1380
+ if (snapshot.matches("analyzing")) return {
1381
+ status: "processing",
1382
+ source: "analyzing"
1383
+ };
1384
+ if (snapshot.matches("processing")) return {
1385
+ status: "processing",
1386
+ source: "local"
1387
+ };
1388
+ if (snapshot.matches("serverFallback")) return {
1389
+ status: "processing",
1390
+ source: "fallback"
1391
+ };
1392
+ if (snapshot.matches("verifyingOnServer")) return {
1393
+ status: "processing",
1394
+ source: "local"
1395
+ };
1396
+ if (snapshot.matches("finished")) return {
1397
+ status: "finished",
1398
+ verdict: context.verdict ?? {
1399
+ human: false,
1400
+ confidence: 0,
1401
+ evidenceId: "missing",
1402
+ signals: emptySignals(),
1403
+ spoofCheckResults: []
1404
+ }
1405
+ };
1406
+ if (snapshot.matches("closed")) return { status: "closed" };
1407
+ if (snapshot.matches("error")) return {
1408
+ status: "error",
1409
+ error: context.error ?? { code: "UNKNOWN" }
1410
+ };
1411
+ return { status: "idle" };
1412
+ }
1413
+ function createApi({ actor, trackElementClicked }) {
1414
+ return {
1415
+ load() {
1416
+ actor.send({ type: "LOAD" });
1417
+ },
1418
+ nextStep() {
1419
+ trackElementClicked?.("nextStep");
1420
+ actor.send({ type: "NEXT_STEP" });
1421
+ },
1422
+ requestPermission() {
1423
+ trackElementClicked?.("requestPermission");
1424
+ actor.send({ type: "REQUEST_PERMISSION" });
1425
+ },
1426
+ goToLearnMore() {
1427
+ trackElementClicked?.("goToLearnMore");
1428
+ actor.send({ type: "GO_TO_LEARN_MORE" });
1429
+ },
1430
+ back() {
1431
+ trackElementClicked?.("back");
1432
+ actor.send({ type: "BACK" });
1433
+ },
1434
+ close() {
1435
+ trackElementClicked?.("close");
1436
+ actor.send({ type: "QUIT" });
1437
+ },
1438
+ reset() {
1439
+ actor.send({ type: "RESET" });
1440
+ },
1441
+ useFallback() {
1442
+ trackElementClicked?.("useFallback");
1443
+ actor.send({ type: "USE_FALLBACK" });
1444
+ }
1445
+ };
1446
+ }
1447
+ /**
1448
+ * Wraps a pre-built personhood actor in a manager. Internal helper
1449
+ * shared by {@link createPersonhoodManager} (drop-in widget path) and
1450
+ * {@link createPersonhoodManagerFromActor} (extensibility surface).
1451
+ * Centralizing the `createManager(...)` + instrumentation call avoids
1452
+ * two near-identical wrap blocks drifting apart.
1453
+ */
1454
+ function wrapActor(actor) {
1455
+ return createManager({
1456
+ actor,
1457
+ mapState,
1458
+ createApi,
1459
+ instrumentation: createNoopInstrumentation()
1460
+ });
1461
+ }
1462
+ /**
1463
+ * Manager built from an externally-owned actor (extensibility path).
1464
+ */
1465
+ function createPersonhoodManagerFromActor(actor) {
1466
+ return wrapActor(actor);
1467
+ }
1468
+ /**
1469
+ * Creates a Personhood manager for the drop-in widget.
1470
+ *
1471
+ * The manager exposes:
1472
+ * - `state: PersonhoodState` via `getState()` / `subscribe()`
1473
+ * - Lifecycle controls: `load`, `nextStep`, `requestPermission`,
1474
+ * `goToLearnMore`, `back`, `close`, `reset`, `useFallback`, `stop`
1475
+ *
1476
+ * Head-pose is intentionally **not** exposed as a stream. The SDK
1477
+ * extracts pose internally for the server-side `headMotion` spoof
1478
+ * check; UI consumers that need a frame-rate pose signal (avatar
1479
+ * mirroring, etc.) should run their own face-tracking pipeline
1480
+ * (e.g. MediaPipe FaceLandmarker) against `state.stream` instead.
1481
+ *
1482
+ * @example
1483
+ * ```ts
1484
+ * const manager = createPersonhoodManager({
1485
+ * config: { siteKey: 'demo', mockVerify: true },
1486
+ * });
1487
+ * manager.subscribe((state) => {
1488
+ * if (state.status === 'finished') {
1489
+ * console.log('human?', state.verdict.human);
1490
+ * }
1491
+ * });
1492
+ * manager.load();
1493
+ * ```
1494
+ */
1495
+ function createPersonhoodManager(options) {
1496
+ return wrapActor(createPersonhoodActor(options));
1497
+ }
1498
+
1499
+ //#endregion
1500
+ export { PERSONHOOD_ERROR_CODES, createPersonhoodActor, createPersonhoodManager, createPersonhoodManagerFromActor, personhoodMachine };