@prosopo/provider 5.14.0 → 5.16.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.
Files changed (303) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +62 -46
  2. package/.turbo/turbo-build$colon$tsc.log +37 -34
  3. package/.turbo/turbo-build.log +63 -50
  4. package/CHANGELOG.md +193 -0
  5. package/LICENSE +201 -0
  6. package/dist/api/admin/apiToggleMaintenanceModeEndpoint.d.ts +4 -0
  7. package/dist/api/admin/apiToggleMaintenanceModeEndpoint.d.ts.map +1 -1
  8. package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js +63 -3
  9. package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js.map +1 -1
  10. package/dist/api/blacklistRequestInspector.js +2 -2
  11. package/dist/api/captcha/getAudioCaptchaChallenge.d.ts +5 -0
  12. package/dist/api/captcha/getAudioCaptchaChallenge.d.ts.map +1 -0
  13. package/dist/api/captcha/getAudioCaptchaChallenge.js +37 -0
  14. package/dist/api/captcha/getAudioCaptchaChallenge.js.map +1 -0
  15. package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.d.ts +2 -1
  16. package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.d.ts.map +1 -1
  17. package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.js +11 -2
  18. package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.js.map +1 -1
  19. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js +1 -1
  20. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.d.ts.map +1 -1
  21. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js +26 -15
  22. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js.map +1 -1
  23. package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.d.ts +5 -0
  24. package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.d.ts.map +1 -0
  25. package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.js +20 -0
  26. package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.js.map +1 -0
  27. package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.d.ts.map +1 -1
  28. package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js +1 -0
  29. package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js.map +1 -1
  30. package/dist/api/captcha/getIconOrderCaptchaChallenge.d.ts +5 -0
  31. package/dist/api/captcha/getIconOrderCaptchaChallenge.d.ts.map +1 -0
  32. package/dist/api/captcha/getIconOrderCaptchaChallenge.js +37 -0
  33. package/dist/api/captcha/getIconOrderCaptchaChallenge.js.map +1 -0
  34. package/dist/api/captcha/getImageCaptchaChallenge.js +2 -2
  35. package/dist/api/captcha/getPoWCaptchaChallenge.js +4 -4
  36. package/dist/api/captcha/getPuzzleCaptchaChallenge.d.ts +1 -3
  37. package/dist/api/captcha/getPuzzleCaptchaChallenge.d.ts.map +1 -1
  38. package/dist/api/captcha/getPuzzleCaptchaChallenge.js +53 -146
  39. package/dist/api/captcha/getPuzzleCaptchaChallenge.js.map +1 -1
  40. package/dist/api/captcha/interactiveCaptchaChallenge.d.ts +42 -0
  41. package/dist/api/captcha/interactiveCaptchaChallenge.d.ts.map +1 -0
  42. package/dist/api/captcha/interactiveCaptchaChallenge.js +154 -0
  43. package/dist/api/captcha/interactiveCaptchaChallenge.js.map +1 -0
  44. package/dist/api/captcha/interactiveCaptchaSolution.d.ts +14 -0
  45. package/dist/api/captcha/interactiveCaptchaSolution.d.ts.map +1 -0
  46. package/dist/api/captcha/interactiveCaptchaSolution.js +77 -0
  47. package/dist/api/captcha/interactiveCaptchaSolution.js.map +1 -0
  48. package/dist/api/captcha/maintenanceModeResponses.d.ts +4 -2
  49. package/dist/api/captcha/maintenanceModeResponses.d.ts.map +1 -1
  50. package/dist/api/captcha/maintenanceModeResponses.js +28 -1
  51. package/dist/api/captcha/maintenanceModeResponses.js.map +1 -1
  52. package/dist/api/captcha/submitAudioCaptchaSolution.d.ts +4 -0
  53. package/dist/api/captcha/submitAudioCaptchaSolution.d.ts.map +1 -0
  54. package/dist/api/captcha/submitAudioCaptchaSolution.js +11 -0
  55. package/dist/api/captcha/submitAudioCaptchaSolution.js.map +1 -0
  56. package/dist/api/captcha/submitIconOrderCaptchaSolution.d.ts +4 -0
  57. package/dist/api/captcha/submitIconOrderCaptchaSolution.d.ts.map +1 -0
  58. package/dist/api/captcha/submitIconOrderCaptchaSolution.js +11 -0
  59. package/dist/api/captcha/submitIconOrderCaptchaSolution.js.map +1 -0
  60. package/dist/api/captcha/submitPoWCaptchaSolution.d.ts +4 -11
  61. package/dist/api/captcha/submitPoWCaptchaSolution.d.ts.map +1 -1
  62. package/dist/api/captcha/submitPoWCaptchaSolution.js +13 -18
  63. package/dist/api/captcha/submitPoWCaptchaSolution.js.map +1 -1
  64. package/dist/api/captcha/submitPuzzleCaptchaSolution.d.ts +1 -3
  65. package/dist/api/captcha/submitPuzzleCaptchaSolution.d.ts.map +1 -1
  66. package/dist/api/captcha/submitPuzzleCaptchaSolution.js +6 -73
  67. package/dist/api/captcha/submitPuzzleCaptchaSolution.js.map +1 -1
  68. package/dist/api/captcha/trafficFilterRequestTime.d.ts +4 -1
  69. package/dist/api/captcha/trafficFilterRequestTime.d.ts.map +1 -1
  70. package/dist/api/captcha/trafficFilterRequestTime.js +3 -0
  71. package/dist/api/captcha/trafficFilterRequestTime.js.map +1 -1
  72. package/dist/api/captcha.d.ts.map +1 -1
  73. package/dist/api/captcha.js +8 -0
  74. package/dist/api/captcha.js.map +1 -1
  75. package/dist/api/domainMiddleware.js +1 -1
  76. package/dist/api/ja4Middleware.js +1 -1
  77. package/dist/api/rawTlsSignalsMiddleware.d.ts +14 -1
  78. package/dist/api/rawTlsSignalsMiddleware.d.ts.map +1 -1
  79. package/dist/api/rawTlsSignalsMiddleware.js +111 -23
  80. package/dist/api/rawTlsSignalsMiddleware.js.map +1 -1
  81. package/dist/api/startProviderApi.js +2 -2
  82. package/dist/api/verify.d.ts.map +1 -1
  83. package/dist/api/verify.js +153 -96
  84. package/dist/api/verify.js.map +1 -1
  85. package/dist/cjs/api/admin/apiToggleMaintenanceModeEndpoint.cjs +65 -2
  86. package/dist/cjs/api/blacklistRequestInspector.cjs +2 -2
  87. package/dist/cjs/api/captcha/getAudioCaptchaChallenge.cjs +37 -0
  88. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/constants.cjs +10 -0
  89. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.cjs +1 -1
  90. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +25 -14
  91. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.cjs +20 -0
  92. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.cjs +1 -0
  93. package/dist/cjs/api/captcha/getIconOrderCaptchaChallenge.cjs +37 -0
  94. package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +2 -2
  95. package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +4 -4
  96. package/dist/cjs/api/captcha/getPuzzleCaptchaChallenge.cjs +52 -145
  97. package/dist/cjs/api/captcha/interactiveCaptchaChallenge.cjs +154 -0
  98. package/dist/cjs/api/captcha/interactiveCaptchaSolution.cjs +77 -0
  99. package/dist/cjs/api/captcha/maintenanceModeResponses.cjs +29 -0
  100. package/dist/cjs/api/captcha/submitAudioCaptchaSolution.cjs +11 -0
  101. package/dist/cjs/api/captcha/submitIconOrderCaptchaSolution.cjs +11 -0
  102. package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +11 -16
  103. package/dist/cjs/api/captcha/submitPuzzleCaptchaSolution.cjs +6 -73
  104. package/dist/cjs/api/captcha/trafficFilterRequestTime.cjs +3 -0
  105. package/dist/cjs/api/captcha.cjs +8 -0
  106. package/dist/cjs/api/domainMiddleware.cjs +1 -1
  107. package/dist/cjs/api/ja4Middleware.cjs +1 -1
  108. package/dist/cjs/api/rawTlsSignalsMiddleware.cjs +111 -22
  109. package/dist/cjs/api/startProviderApi.cjs +2 -2
  110. package/dist/cjs/api/verify.cjs +152 -95
  111. package/dist/cjs/compositeIpAddress.cjs +21 -7
  112. package/dist/cjs/index.cjs +1 -1
  113. package/dist/cjs/tasks/audio/audioBuffer.cjs +72 -0
  114. package/dist/cjs/tasks/audio/audioRenderer.cjs +32 -0
  115. package/dist/cjs/tasks/audioAlternative.cjs +23 -0
  116. package/dist/cjs/tasks/audioCaptcha/audioTasks.cjs +65 -0
  117. package/dist/cjs/tasks/audioCaptcha/audioTasksUtils.cjs +19 -0
  118. package/dist/cjs/tasks/captchaManager.cjs +28 -1
  119. package/dist/cjs/tasks/captchaTypeSelection.cjs +31 -3
  120. package/dist/cjs/tasks/client/clientTasks.cjs +2 -2
  121. package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +49 -26
  122. package/dist/cjs/tasks/iconOrder/iconOrderRenderer.cjs +42 -0
  123. package/dist/cjs/tasks/iconOrderCaptcha/iconOrderTasks.cjs +69 -0
  124. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +10 -17
  125. package/dist/cjs/tasks/interactiveCaptcha/interactiveCaptchaManager.cjs +423 -0
  126. package/dist/cjs/tasks/powCaptcha/powTasks.cjs +15 -19
  127. package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +3 -1
  128. package/dist/cjs/tasks/puzzle/backgroundBuffer.cjs +3 -3
  129. package/dist/cjs/tasks/puzzle/nativeBackground.cjs +12 -5
  130. package/dist/cjs/tasks/puzzle/puzzleRenderer.cjs +4 -3
  131. package/dist/cjs/tasks/puzzleCaptcha/puzzleTasks.cjs +40 -493
  132. package/dist/cjs/tasks/spam/checkTrafficFilter.cjs +18 -1
  133. package/dist/cjs/tasks/tasks.cjs +6 -0
  134. package/dist/cjs/util.cjs +1 -1
  135. package/dist/compositeIpAddress.d.ts.map +1 -1
  136. package/dist/compositeIpAddress.js +21 -7
  137. package/dist/compositeIpAddress.js.map +1 -1
  138. package/dist/index.js +2 -2
  139. package/dist/tasks/audio/audioBuffer.d.ts +23 -0
  140. package/dist/tasks/audio/audioBuffer.d.ts.map +1 -0
  141. package/dist/tasks/audio/audioBuffer.js +70 -0
  142. package/dist/tasks/audio/audioBuffer.js.map +1 -0
  143. package/dist/tasks/audio/audioRenderer.d.ts +11 -0
  144. package/dist/tasks/audio/audioRenderer.d.ts.map +1 -0
  145. package/dist/tasks/audio/audioRenderer.js +31 -0
  146. package/dist/tasks/audio/audioRenderer.js.map +1 -0
  147. package/dist/tasks/audioAlternative.d.ts +8 -0
  148. package/dist/tasks/audioAlternative.d.ts.map +1 -0
  149. package/dist/tasks/audioAlternative.js +20 -0
  150. package/dist/tasks/audioAlternative.js.map +1 -0
  151. package/dist/tasks/audioCaptcha/audioTasks.d.ts +19 -0
  152. package/dist/tasks/audioCaptcha/audioTasks.d.ts.map +1 -0
  153. package/dist/tasks/audioCaptcha/audioTasks.js +65 -0
  154. package/dist/tasks/audioCaptcha/audioTasks.js.map +1 -0
  155. package/dist/tasks/audioCaptcha/audioTasksUtils.d.ts +3 -0
  156. package/dist/tasks/audioCaptcha/audioTasksUtils.d.ts.map +1 -0
  157. package/dist/tasks/audioCaptcha/audioTasksUtils.js +18 -0
  158. package/dist/tasks/audioCaptcha/audioTasksUtils.js.map +1 -0
  159. package/dist/tasks/captchaManager.d.ts +9 -3
  160. package/dist/tasks/captchaManager.d.ts.map +1 -1
  161. package/dist/tasks/captchaManager.js +29 -2
  162. package/dist/tasks/captchaManager.js.map +1 -1
  163. package/dist/tasks/captchaTypeSelection.d.ts +4 -2
  164. package/dist/tasks/captchaTypeSelection.d.ts.map +1 -1
  165. package/dist/tasks/captchaTypeSelection.js +32 -5
  166. package/dist/tasks/captchaTypeSelection.js.map +1 -1
  167. package/dist/tasks/client/clientTasks.js +2 -2
  168. package/dist/tasks/frictionless/frictionlessTasks.d.ts +6 -1
  169. package/dist/tasks/frictionless/frictionlessTasks.d.ts.map +1 -1
  170. package/dist/tasks/frictionless/frictionlessTasks.js +51 -28
  171. package/dist/tasks/frictionless/frictionlessTasks.js.map +1 -1
  172. package/dist/tasks/frictionless/routingMachine.d.ts +1 -2
  173. package/dist/tasks/frictionless/routingMachine.d.ts.map +1 -1
  174. package/dist/tasks/frictionless/routingMachine.js.map +1 -1
  175. package/dist/tasks/iconOrder/iconOrderRenderer.d.ts +12 -0
  176. package/dist/tasks/iconOrder/iconOrderRenderer.d.ts.map +1 -0
  177. package/dist/tasks/iconOrder/iconOrderRenderer.js +40 -0
  178. package/dist/tasks/iconOrder/iconOrderRenderer.js.map +1 -0
  179. package/dist/tasks/iconOrderCaptcha/iconOrderTasks.d.ts +22 -0
  180. package/dist/tasks/iconOrderCaptcha/iconOrderTasks.d.ts.map +1 -0
  181. package/dist/tasks/iconOrderCaptcha/iconOrderTasks.js +69 -0
  182. package/dist/tasks/iconOrderCaptcha/iconOrderTasks.js.map +1 -0
  183. package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +1 -1
  184. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +10 -17
  185. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +1 -1
  186. package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.d.ts +52 -0
  187. package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.d.ts.map +1 -0
  188. package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.js +423 -0
  189. package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.js.map +1 -0
  190. package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
  191. package/dist/tasks/powCaptcha/powTasks.js +15 -19
  192. package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
  193. package/dist/tasks/powCaptcha/powTasksUtils.d.ts +1 -0
  194. package/dist/tasks/powCaptcha/powTasksUtils.d.ts.map +1 -1
  195. package/dist/tasks/powCaptcha/powTasksUtils.js +3 -2
  196. package/dist/tasks/powCaptcha/powTasksUtils.js.map +1 -1
  197. package/dist/tasks/puzzle/backgroundBuffer.d.ts +3 -2
  198. package/dist/tasks/puzzle/backgroundBuffer.d.ts.map +1 -1
  199. package/dist/tasks/puzzle/backgroundBuffer.js +3 -3
  200. package/dist/tasks/puzzle/backgroundBuffer.js.map +1 -1
  201. package/dist/tasks/puzzle/nativeBackground.d.ts +5 -1
  202. package/dist/tasks/puzzle/nativeBackground.d.ts.map +1 -1
  203. package/dist/tasks/puzzle/nativeBackground.js +12 -5
  204. package/dist/tasks/puzzle/nativeBackground.js.map +1 -1
  205. package/dist/tasks/puzzle/puzzleRenderer.d.ts +2 -0
  206. package/dist/tasks/puzzle/puzzleRenderer.d.ts.map +1 -1
  207. package/dist/tasks/puzzle/puzzleRenderer.js +4 -3
  208. package/dist/tasks/puzzle/puzzleRenderer.js.map +1 -1
  209. package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts +14 -16
  210. package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts.map +1 -1
  211. package/dist/tasks/puzzleCaptcha/puzzleTasks.js +41 -494
  212. package/dist/tasks/puzzleCaptcha/puzzleTasks.js.map +1 -1
  213. package/dist/tasks/spam/checkTrafficFilter.d.ts +4 -1
  214. package/dist/tasks/spam/checkTrafficFilter.d.ts.map +1 -1
  215. package/dist/tasks/spam/checkTrafficFilter.js +18 -1
  216. package/dist/tasks/spam/checkTrafficFilter.js.map +1 -1
  217. package/dist/tasks/tasks.d.ts +4 -0
  218. package/dist/tasks/tasks.d.ts.map +1 -1
  219. package/dist/tasks/tasks.js +6 -0
  220. package/dist/tasks/tasks.js.map +1 -1
  221. package/dist/tests/integration/api/admin/apiRegisterSiteKeyEndpoint.integration.test.js +7 -3
  222. package/dist/tests/integration/api/admin/apiRegisterSiteKeyEndpoint.integration.test.js.map +1 -1
  223. package/dist/tests/integration/clientSettingsPersistence.integration.test.js +44 -2
  224. package/dist/tests/integration/clientSettingsPersistence.integration.test.js.map +1 -1
  225. package/dist/tests/unit/api/admin/apiRegisterSiteKeyEndpoint.unit.test.js +4 -2
  226. package/dist/tests/unit/api/admin/apiRegisterSiteKeyEndpoint.unit.test.js.map +1 -1
  227. package/dist/tests/unit/api/admin/apiToggleMaintenanceModeEndpoint.unit.test.js +76 -1
  228. package/dist/tests/unit/api/admin/apiToggleMaintenanceModeEndpoint.unit.test.js.map +1 -1
  229. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/constants.unit.test.js +54 -2
  230. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/constants.unit.test.js.map +1 -1
  231. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.d.ts +2 -0
  232. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.d.ts.map +1 -0
  233. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.js +45 -0
  234. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.js.map +1 -0
  235. package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js +20 -0
  236. package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js.map +1 -1
  237. package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.js +15 -1
  238. package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.js.map +1 -1
  239. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +174 -0
  240. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
  241. package/dist/tests/unit/api/rawTlsSignalsMiddleware.unit.test.js +96 -1
  242. package/dist/tests/unit/api/rawTlsSignalsMiddleware.unit.test.js.map +1 -1
  243. package/dist/tests/unit/compositeIpAddress.unit.test.js +12 -3
  244. package/dist/tests/unit/compositeIpAddress.unit.test.js.map +1 -1
  245. package/dist/tests/unit/tasks/audio/audioBuffer.unit.test.d.ts +2 -0
  246. package/dist/tests/unit/tasks/audio/audioBuffer.unit.test.d.ts.map +1 -0
  247. package/dist/tests/unit/tasks/audio/audioBuffer.unit.test.js +105 -0
  248. package/dist/tests/unit/tasks/audio/audioBuffer.unit.test.js.map +1 -0
  249. package/dist/tests/unit/tasks/audioAlternative.unit.test.d.ts +2 -0
  250. package/dist/tests/unit/tasks/audioAlternative.unit.test.d.ts.map +1 -0
  251. package/dist/tests/unit/tasks/audioAlternative.unit.test.js +76 -0
  252. package/dist/tests/unit/tasks/audioAlternative.unit.test.js.map +1 -0
  253. package/dist/tests/unit/tasks/audioCaptcha/audioTasks.unit.test.d.ts +2 -0
  254. package/dist/tests/unit/tasks/audioCaptcha/audioTasks.unit.test.d.ts.map +1 -0
  255. package/dist/tests/unit/tasks/audioCaptcha/audioTasks.unit.test.js +259 -0
  256. package/dist/tests/unit/tasks/audioCaptcha/audioTasks.unit.test.js.map +1 -0
  257. package/dist/tests/unit/tasks/audioCaptcha/audioTasksUtils.unit.test.d.ts +2 -0
  258. package/dist/tests/unit/tasks/audioCaptcha/audioTasksUtils.unit.test.d.ts.map +1 -0
  259. package/dist/tests/unit/tasks/audioCaptcha/audioTasksUtils.unit.test.js +52 -0
  260. package/dist/tests/unit/tasks/audioCaptcha/audioTasksUtils.unit.test.js.map +1 -0
  261. package/dist/tests/unit/tasks/captchaManager.unit.test.js +171 -2
  262. package/dist/tests/unit/tasks/captchaManager.unit.test.js.map +1 -1
  263. package/dist/tests/unit/tasks/captchaTypeSelection.unit.test.js +68 -6
  264. package/dist/tests/unit/tasks/captchaTypeSelection.unit.test.js.map +1 -1
  265. package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.d.ts +2 -0
  266. package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.d.ts.map +1 -0
  267. package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.js +123 -0
  268. package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.js.map +1 -0
  269. package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.js +31 -0
  270. package/dist/tests/unit/tasks/frictionless/frictionlessTasks.unit.test.js.map +1 -1
  271. package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.d.ts +2 -0
  272. package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.d.ts.map +1 -0
  273. package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.js +103 -0
  274. package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.js.map +1 -0
  275. package/dist/tests/unit/tasks/frictionless/routerPuzzleOverrides.unit.test.js +28 -0
  276. package/dist/tests/unit/tasks/frictionless/routerPuzzleOverrides.unit.test.js.map +1 -1
  277. package/dist/tests/unit/tasks/iconOrder/iconOrderRenderer.unit.test.d.ts +2 -0
  278. package/dist/tests/unit/tasks/iconOrder/iconOrderRenderer.unit.test.d.ts.map +1 -0
  279. package/dist/tests/unit/tasks/iconOrder/iconOrderRenderer.unit.test.js +60 -0
  280. package/dist/tests/unit/tasks/iconOrder/iconOrderRenderer.unit.test.js.map +1 -0
  281. package/dist/tests/unit/tasks/iconOrderCaptcha/iconOrderTasks.unit.test.d.ts +2 -0
  282. package/dist/tests/unit/tasks/iconOrderCaptcha/iconOrderTasks.unit.test.d.ts.map +1 -0
  283. package/dist/tests/unit/tasks/iconOrderCaptcha/iconOrderTasks.unit.test.js +225 -0
  284. package/dist/tests/unit/tasks/iconOrderCaptcha/iconOrderTasks.unit.test.js.map +1 -0
  285. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js +23 -1
  286. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js.map +1 -1
  287. package/dist/tests/unit/tasks/puzzle/backgroundBuffer.unit.test.js +1 -4
  288. package/dist/tests/unit/tasks/puzzle/backgroundBuffer.unit.test.js.map +1 -1
  289. package/dist/tests/unit/tasks/puzzle/nativeBackground.unit.test.js +10 -3
  290. package/dist/tests/unit/tasks/puzzle/nativeBackground.unit.test.js.map +1 -1
  291. package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.d.ts +2 -0
  292. package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.d.ts.map +1 -0
  293. package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.js +35 -0
  294. package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.js.map +1 -0
  295. package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.d.ts +2 -0
  296. package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.d.ts.map +1 -0
  297. package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.js +49 -0
  298. package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.js.map +1 -0
  299. package/dist/tests/unit/testUtils/mockProviderEnv.d.ts +17 -14
  300. package/dist/tests/unit/testUtils/mockProviderEnv.d.ts.map +1 -1
  301. package/dist/tests/unit/testUtils/mockProviderEnv.js.map +1 -1
  302. package/dist/util.js +1 -1
  303. package/package.json +107 -103
@@ -0,0 +1,423 @@
1
+ const require_usageCounters = require("../../util/usageCounters.cjs");
2
+ const require_rawTlsSignalsMiddleware = require("../../api/rawTlsSignalsMiddleware.cjs");
3
+ const require_compositeIpAddress = require("../../compositeIpAddress.cjs");
4
+ const require_util = require("../../util.cjs");
5
+ const require_clientMetaData = require("../../utils/clientMetaData.cjs");
6
+ const require_devicePlatform = require("../../utils/devicePlatform.cjs");
7
+ const require_enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
8
+ const require_captchaManager = require("../captchaManager.cjs");
9
+ const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
10
+ const require_frictionlessTasksUtils = require("../frictionless/frictionlessTasksUtils.cjs");
11
+ const require_powTasksUtils = require("../powCaptcha/powTasksUtils.cjs");
12
+ const require_evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
13
+ let _prosopo_common = require("@prosopo/common");
14
+ let _prosopo_types = require("@prosopo/types");
15
+ let _polkadot_util = require("@polkadot/util");
16
+ let _prosopo_user_access_policy = require("@prosopo/user-access-policy");
17
+ let _prosopo_util = require("@prosopo/util");
18
+ //#region src/tasks/interactiveCaptcha/interactiveCaptchaManager.ts
19
+ /**
20
+ * Shared pipeline for the captcha types a human solves on screen (puzzle,
21
+ * icon-order). Subclasses supply the record accessors and grading; minting,
22
+ * submission bookkeeping and server verification live here.
23
+ */
24
+ var InteractiveCaptchaManager = class extends require_captchaManager.CaptchaManager {
25
+ constructor(db, pair, config, logger, usageCounters) {
26
+ super(db, pair, config, logger);
27
+ this.POW_SEPARATOR = _prosopo_types.POW_SEPARATOR;
28
+ this.decisionMachineRunner = new require_decisionMachineRunner.DecisionMachineRunner(db);
29
+ this.usageCounters = usageCounters ?? null;
30
+ }
31
+ mintChallenge(userAccount, dappAccount) {
32
+ const requestedAtTimestamp = Date.now();
33
+ const challenge = `${requestedAtTimestamp}___${userAccount}___${dappAccount}___${Math.floor(Math.random() * 1e6)}`;
34
+ return {
35
+ challenge,
36
+ providerSignature: (0, _polkadot_util.u8aToHex)(this.pair.sign((0, _polkadot_util.stringToHex)(challenge))),
37
+ requestedAtTimestamp
38
+ };
39
+ }
40
+ /**
41
+ * Grades a user's submission and records the outcome on the captcha and
42
+ * session records. Returns whether the solution was correct.
43
+ */
44
+ async submitInteractiveCaptchaSolution(submission) {
45
+ const { challenge, userTimestampSignature, behavioralData, simdReadings } = submission;
46
+ require_powTasksUtils.checkPowSignature(challenge, submission.providerChallengeSignature, this.pair.address, _prosopo_types.ApiParams.challenge);
47
+ const challengeSplit = challenge.split(this.POW_SEPARATOR);
48
+ const timestamp = Number.parseInt((0, _prosopo_util.at)(challengeSplit, 0));
49
+ const userAccount = (0, _prosopo_util.at)(challengeSplit, 1);
50
+ require_powTasksUtils.checkPowSignature(timestamp.toString(), userTimestampSignature, userAccount, _prosopo_types.ApiParams.timestamp);
51
+ const challengeRecord = await this.getRecordByChallenge(challenge);
52
+ if (!challengeRecord) {
53
+ this.logger.debug(() => ({ msg: `No record of this challenge: ${challenge}` }));
54
+ return false;
55
+ }
56
+ const { coords, saltDecodeError } = this.decodeSaltCoords(submission.salt);
57
+ if (!await this.claimSubmission(challengeRecord)) {
58
+ this.logger.debug(() => ({ msg: `Challenge already submitted: ${challenge}` }));
59
+ return false;
60
+ }
61
+ if (saltDecodeError) {
62
+ await this.recordSubmissionResult(challengeRecord, {
63
+ status: _prosopo_types.CaptchaStatus.disapproved,
64
+ reason: _prosopo_types.ResultReason.CAPTCHA_INVALID_SALT
65
+ }, userTimestampSignature, void 0);
66
+ return false;
67
+ }
68
+ if (!(0, _prosopo_util.verifyRecency)(challenge, submission.timeout)) {
69
+ await this.recordSubmissionResult(challengeRecord, {
70
+ status: _prosopo_types.CaptchaStatus.disapproved,
71
+ reason: _prosopo_types.ResultReason.CAPTCHA_INVALID_TIMESTAMP
72
+ }, userTimestampSignature, coords);
73
+ return false;
74
+ }
75
+ const correct = submission.isCorrect(challengeRecord);
76
+ const result = correct ? { status: _prosopo_types.CaptchaStatus.approved } : {
77
+ status: _prosopo_types.CaptchaStatus.disapproved,
78
+ reason: _prosopo_types.ResultReason.CAPTCHA_INVALID_SOLUTION
79
+ };
80
+ if (correct && this.usageCounters) this.usageCounters.incrManyAsync((0, _prosopo_util.at)(challengeSplit, 2), require_usageCounters.buildAllWindowIncrements("solved", this.captchaType, submission.ipAddress.address, userAccount));
81
+ await submission.persistInteraction();
82
+ const decodedPayloads = await this.decodeSubmissionPayloads(challengeRecord.sessionId, {
83
+ behavioural: behavioralData,
84
+ simd: simdReadings
85
+ });
86
+ if (behavioralData) try {
87
+ const decryptedData = decodedPayloads.behavioural;
88
+ if (decryptedData) {
89
+ this.logger?.info(() => ({
90
+ msg: "Behavioral analysis completed",
91
+ data: {
92
+ userAccount,
93
+ dappAccount: (0, _prosopo_util.at)(challengeSplit, 2),
94
+ challenge,
95
+ mouseEventsCount: decryptedData.collector1?.length || 0,
96
+ touchEventsCount: decryptedData.collector2?.length || 0,
97
+ clickEventsCount: decryptedData.collector3?.length || 0,
98
+ scrollEventsCount: decryptedData.collector4?.length || 0,
99
+ deviceCapability: decryptedData.deviceCapability,
100
+ captchaResult: correct ? "passed" : "failed"
101
+ }
102
+ }));
103
+ const packedData = {
104
+ c1: decryptedData.collector1 || [],
105
+ c2: decryptedData.collector2 || [],
106
+ c3: decryptedData.collector3 || [],
107
+ c4: decryptedData.collector4 || [],
108
+ d: decryptedData.deviceCapability
109
+ };
110
+ await this.updateRecord(challenge, {
111
+ behavioralDataPacked: packedData,
112
+ deviceCapability: decryptedData.deviceCapability
113
+ });
114
+ }
115
+ } catch (error) {
116
+ this.logger?.error(() => ({
117
+ msg: "Failed to process behavioral data",
118
+ err: error
119
+ }));
120
+ }
121
+ const storedClientMetaData = require_clientMetaData.toStoredClientMetaData(submission.clientMetaData);
122
+ if (storedClientMetaData) await this.updateRecord(challenge, { clientMetaData: storedClientMetaData });
123
+ await this.recordSubmissionResult(challengeRecord, result, userTimestampSignature, coords, storedClientMetaData);
124
+ if (challengeRecord.sessionId && decodedPayloads.simd) await this.recordSessionSimdReadingsIfAbsentWithCache(challengeRecord.sessionId, decodedPayloads.simd, _prosopo_types.SimdReadingsStage.submit);
125
+ return correct;
126
+ }
127
+ /** Invalid salt disapproves the submission rather than being ignored. */
128
+ decodeSaltCoords(salt) {
129
+ if (!salt) return {};
130
+ try {
131
+ const extractedData = (0, _prosopo_util.extractData)(salt);
132
+ if (extractedData.length < 2) return {};
133
+ const coords = [[[extractedData[0], extractedData[1]]]];
134
+ (0, _prosopo_util.assertCoordsSafe)(coords, "coords");
135
+ return { coords };
136
+ } catch (error) {
137
+ this.logger.warn(() => ({
138
+ msg: "Failed to extract coordinates from salt",
139
+ error,
140
+ salt
141
+ }));
142
+ return { saltDecodeError: error };
143
+ }
144
+ }
145
+ async recordSubmissionResult(challengeRecord, result, userSignature, coords, clientMetaData) {
146
+ await this.updateSubmissionResult(challengeRecord.challenge, result, userSignature, coords);
147
+ if (challengeRecord.sessionId) await this.updateSessionRecordWithCache(challengeRecord.sessionId, {
148
+ userSubmitted: true,
149
+ result,
150
+ ...(0, _prosopo_types.isBlockingCaptchaResult)(this.captchaType, result) && { blocked: true },
151
+ ...clientMetaData && { clientMetaData }
152
+ });
153
+ }
154
+ /**
155
+ * The post-solve gate the site's server calls: decides whether the token
156
+ * the widget was given is honoured.
157
+ *
158
+ * @param dappAccount - the dapp that is requesting the captcha
159
+ * @param challenge - the challenge string
160
+ * @param timeout - milliseconds allowed between submit and verify
161
+ * @param env - provider environment
162
+ * @param ip - optional IP address for validation
163
+ * @param userAccessRulesStorage - storage for querying user access policies
164
+ * @param email
165
+ * @param spamEmailDomainCheckingEnabled
166
+ * @param spamFilter
167
+ * @param trafficFilter
168
+ * @param storeMetadata - when true, persists the dapp-server-provided
169
+ * `email` on the captcha record for spam-rate analysis.
170
+ * @param clientSessionId - the session id the site rendered the widget
171
+ * with. When supplied, the solve must carry the same value in its
172
+ * `clientMetaData` or it is disapproved.
173
+ */
174
+ async serverVerifyInteractiveCaptchaSolution(dappAccount, challenge, timeout, env, ip, userAccessRulesStorage, email, spamEmailDomainCheckingEnabled = false, spamFilter, trafficFilter, storeMetadata = false, clientSessionId) {
175
+ const notVerifiedResponse = { verified: false };
176
+ const logger = this.logger.with({
177
+ challenge,
178
+ dappAccount
179
+ });
180
+ const challengeRecord = await this.getRecordByChallenge(challenge);
181
+ if (!challengeRecord) {
182
+ logger.debug(() => ({ msg: `No record of this challenge: ${challenge}` }));
183
+ return notVerifiedResponse;
184
+ }
185
+ notVerifiedResponse.sessionId = challengeRecord.sessionId;
186
+ if (challengeRecord.result.status !== _prosopo_types.CaptchaStatus.approved) throw new _prosopo_common.ProsopoApiError("CAPTCHA.INVALID_SOLUTION", { context: {
187
+ code: 400,
188
+ failedFuncName: this.serverVerifyInteractiveCaptchaSolution.name,
189
+ challenge
190
+ } });
191
+ if (challengeRecord.serverChecked) return notVerifiedResponse;
192
+ const challengeDappAccount = challengeRecord.dappAccount;
193
+ if (dappAccount !== challengeDappAccount) throw new _prosopo_common.ProsopoEnvError("CAPTCHA.DAPP_USER_SOLUTION_NOT_FOUND", { context: {
194
+ failedFuncName: this.serverVerifyInteractiveCaptchaSolution.name,
195
+ dappAccount,
196
+ challengeDappAccount
197
+ } });
198
+ if (!await this.markRecordChecked(challengeRecord.challenge)) return notVerifiedResponse;
199
+ const submittedAt = challengeRecord.submittedAtTimestamp;
200
+ if ((submittedAt instanceof Date ? Date.now() - submittedAt.getTime() : Number.POSITIVE_INFINITY) > timeout) {
201
+ await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.TIMESTAMP_TOO_OLD);
202
+ return notVerifiedResponse;
203
+ }
204
+ if (require_clientMetaData.isClientSessionMismatch(clientSessionId, challengeRecord.clientMetaData?.clientSessionId)) {
205
+ logger.info(() => ({
206
+ msg: `Client session mismatch in server ${this.logLabel} verification`,
207
+ data: { hasRecordedClientSessionId: Boolean(challengeRecord.clientMetaData?.clientSessionId) }
208
+ }));
209
+ await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.CLIENT_SESSION_MISMATCH);
210
+ return notVerifiedResponse;
211
+ }
212
+ if (userAccessRulesStorage) try {
213
+ const blockPolicy = await this.checkForHardBlock(userAccessRulesStorage, challengeRecord, challengeRecord.userAccount, challengeRecord.headers, challengeRecord.coords, challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0, challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.asnNumber : void 0);
214
+ if (blockPolicy) {
215
+ logger.info(() => ({
216
+ msg: `User blocked by access policy in server ${this.logLabel} verification`,
217
+ data: {
218
+ userAccount: challengeRecord.userAccount,
219
+ policy: blockPolicy
220
+ }
221
+ }));
222
+ await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.ACCESS_POLICY_BLOCK, { matchedRule: (0, _prosopo_user_access_policy.describeMatchedRule)(blockPolicy) });
223
+ return notVerifiedResponse;
224
+ }
225
+ } catch (error) {
226
+ logger.warn(() => ({
227
+ msg: `Failed to check user access policies in server ${this.logLabel} verification`,
228
+ error
229
+ }));
230
+ }
231
+ if (email && spamEmailDomainCheckingEnabled) try {
232
+ if (await this.checkSpamEmail(email)) {
233
+ const emailDomain = email.split("@")[1] || "unknown";
234
+ logger.info(() => ({
235
+ msg: `Spam email domain detected in server ${this.logLabel} verification`,
236
+ data: { emailDomain }
237
+ }));
238
+ await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.SPAM_EMAIL_DOMAIN, null);
239
+ return notVerifiedResponse;
240
+ }
241
+ } catch (error) {
242
+ logger.warn(() => ({
243
+ msg: `Failed to check spam email domain in server ${this.logLabel} verification`,
244
+ error
245
+ }));
246
+ }
247
+ const maxEmailSubmissionCount = spamFilter?.enabled && spamFilter.emailRules?.enabled ? spamFilter.emailRules.maxEmailSubmissionCount : void 0;
248
+ let emailNormalised;
249
+ if (maxEmailSubmissionCount !== void 0 && email && storeMetadata) {
250
+ emailNormalised = require_evaluateEmailSpamRules.normaliseEmailForMatching(email);
251
+ if (emailNormalised) try {
252
+ const priorCount = await this.db.countCommitmentsByNormalisedEmail(dappAccount, emailNormalised);
253
+ if (priorCount >= maxEmailSubmissionCount) {
254
+ logger.info(() => ({
255
+ msg: `Email submission count exceeded in server ${this.logLabel} verification`,
256
+ data: {
257
+ priorCount,
258
+ maxEmailSubmissionCount
259
+ }
260
+ }));
261
+ await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.SPAM_EMAIL_COUNT_EXCEEDED, null);
262
+ return notVerifiedResponse;
263
+ }
264
+ } catch (error) {
265
+ logger.warn(() => ({
266
+ msg: `Failed to check email submission count in server ${this.logLabel} verification`,
267
+ error
268
+ }));
269
+ }
270
+ }
271
+ const sessionRecord = challengeRecord.sessionId ? await this.getSessionRecordWithOriginFallback(challengeRecord.sessionId) : void 0;
272
+ const enrichedDnsEvent = await require_enrichDnsEvent.enrichDnsEvent(sessionRecord?.dnsEvent, env.ipInfoService, ip ?? challengeRecord.ipInfo?.ip);
273
+ {
274
+ const check = await this.resolveTrafficFilterCheck(env, challengeRecord.ipInfo, trafficFilter, ip, enrichedDnsEvent);
275
+ if (check.isBlocked) {
276
+ logger.info(() => ({
277
+ msg: `Traffic filter rejected request in ${this.logLabel} verification`,
278
+ data: {
279
+ ip,
280
+ reason: check.reason,
281
+ dnsPeerIp: enrichedDnsEvent?.peerIp,
282
+ dnsResolverIp: enrichedDnsEvent?.resolverIp,
283
+ dnsPeerAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
284
+ dnsResolverAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo),
285
+ dnsPathValid: enrichedDnsEvent?.pathValid
286
+ }
287
+ }));
288
+ await this.disapproveVerification(challengeRecord, check.reason);
289
+ return notVerifiedResponse;
290
+ }
291
+ }
292
+ if (storeMetadata && email) await this.updateRecord(challengeRecord.challenge, { metadata: {
293
+ email,
294
+ emailNormalised: emailNormalised ?? require_evaluateEmailSpamRules.normaliseEmailForMatching(email)
295
+ } });
296
+ if (ip) {
297
+ const challengeIpAddress = require_compositeIpAddress.getIpAddressFromComposite(challengeRecord.ipAddress);
298
+ const ipValidationRules = (await this.db.getClientRecord(dappAccount))?.settings?.ipValidationRules;
299
+ await this.updateRecord(challengeRecord.challenge, { providedIp: require_compositeIpAddress.getCompositeIpAddress(ip) });
300
+ if (ipValidationRules?.enabled === true) {
301
+ const ipValidation = await require_util.deepValidateIpAddress(ip, challengeIpAddress, logger, env.ipInfoService, ipValidationRules, enrichedDnsEvent?.peerIp);
302
+ if (!ipValidation.isValid) {
303
+ logger.error(() => ({
304
+ msg: `IP validation failed for ${this.logLabel} captcha`,
305
+ data: {
306
+ ip,
307
+ challengeIp: challengeIpAddress.address,
308
+ error: ipValidation.errorMessage,
309
+ distanceKm: ipValidation.distanceKm
310
+ }
311
+ }));
312
+ await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.FAILED_IP_VALIDATION);
313
+ return notVerifiedResponse;
314
+ }
315
+ }
316
+ }
317
+ let score;
318
+ if (sessionRecord) {
319
+ const dnsAsymmetry = require_enrichDnsEvent.computeDnsAsymmetry(enrichedDnsEvent, challengeRecord.ipInfo, trafficFilter);
320
+ if (dnsAsymmetry > 0) sessionRecord.scoreComponents = {
321
+ ...sessionRecord.scoreComponents,
322
+ dnsAsymmetry
323
+ };
324
+ score = require_frictionlessTasksUtils.computeFrictionlessScore(sessionRecord?.scoreComponents);
325
+ logger.info(() => ({ data: {
326
+ scoreComponents: { ...sessionRecord?.scoreComponents || {} },
327
+ score,
328
+ dnsPeerAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.peerIpInfo),
329
+ dnsResolverAsn: require_enrichDnsEvent.getIpInfoAsn(enrichedDnsEvent?.resolverIpInfo)
330
+ } }));
331
+ }
332
+ try {
333
+ const decisionInput = {
334
+ userAccount: challengeRecord.userAccount,
335
+ dappAccount: challengeRecord.dappAccount,
336
+ captchaResult: "passed",
337
+ headers: challengeRecord.headers,
338
+ captchaType: this.captchaType,
339
+ behavioralDataPacked: challengeRecord.behavioralDataPacked,
340
+ deviceCapability: challengeRecord.deviceCapability,
341
+ countryCode: challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0,
342
+ ipInfo: challengeRecord.ipInfo,
343
+ dnsEvent: enrichedDnsEvent,
344
+ score,
345
+ threshold: sessionRecord?.threshold,
346
+ scoreComponents: sessionRecord?.scoreComponents,
347
+ decryptedHeadHash: sessionRecord?.decryptedHeadHash,
348
+ userSitekeyIpHash: sessionRecord?.userSitekeyIpHash,
349
+ simdReadings: sessionRecord?.simdReadings,
350
+ d: sessionRecord?.d,
351
+ frictionlessReason: sessionRecord?.reason,
352
+ ruleType: sessionRecord?.ruleType,
353
+ webView: sessionRecord?.webView,
354
+ iFrame: sessionRecord?.iFrame,
355
+ currentUrl: sessionRecord?.currentUrl,
356
+ iframeUrl: sessionRecord?.iframeUrl,
357
+ coords: challengeRecord.coords,
358
+ ...this.decisionMachineEventFields(challengeRecord),
359
+ ...require_rawTlsSignalsMiddleware.rawTlsSignalsFromRecord(sessionRecord),
360
+ trafficPolicies: require_devicePlatform.deriveTrafficPolicies(trafficFilter)
361
+ };
362
+ const decision = await this.decisionMachineRunner.decide(decisionInput, logger);
363
+ if (decision.decision === _prosopo_types.DecisionMachineDecision.Deny) {
364
+ logger.info(() => ({
365
+ msg: `Decision machine denied ${this.logLabel} captcha in server verification`,
366
+ data: {
367
+ userAccount: challengeRecord.userAccount,
368
+ reason: decision.reason,
369
+ score: decision.score,
370
+ tags: decision.tags
371
+ }
372
+ }));
373
+ await this.disapproveVerification(challengeRecord, decision.reason || _prosopo_types.ResultReason.CAPTCHA_DECISION_MACHINE_DENIED);
374
+ return notVerifiedResponse;
375
+ }
376
+ logger.debug(() => ({
377
+ msg: `Decision machine allowed ${this.logLabel} captcha`,
378
+ data: {
379
+ reason: decision.reason,
380
+ score: decision.score,
381
+ tags: decision.tags
382
+ }
383
+ }));
384
+ } catch (error) {
385
+ logger.error(() => ({
386
+ msg: `Failed to run decision machine in server ${this.logLabel} verification`,
387
+ err: error
388
+ }));
389
+ }
390
+ if (challengeRecord.sessionId) await this.updateSessionRecordWithCache(challengeRecord.sessionId, {
391
+ serverChecked: true,
392
+ result: { status: _prosopo_types.CaptchaStatus.approved }
393
+ });
394
+ return {
395
+ verified: true,
396
+ ...score ? { score } : {},
397
+ ...challengeRecord.sessionId && { sessionId: challengeRecord.sessionId }
398
+ };
399
+ }
400
+ /**
401
+ * Records a server-verification rejection on the captcha record and, unless
402
+ * `session` is null, on the linked session.
403
+ */
404
+ async disapproveVerification(challengeRecord, reason, session = {}) {
405
+ const result = {
406
+ status: _prosopo_types.CaptchaStatus.disapproved,
407
+ reason
408
+ };
409
+ const isBlocked = (0, _prosopo_types.isBlockingCaptchaResult)(this.captchaType, result);
410
+ await this.updateRecord(challengeRecord.challenge, {
411
+ result,
412
+ ...isBlocked && { blocked: true }
413
+ });
414
+ if (session && challengeRecord.sessionId) await this.updateSessionRecordWithCache(challengeRecord.sessionId, {
415
+ serverChecked: true,
416
+ result,
417
+ ...isBlocked && { blocked: true },
418
+ ...session
419
+ });
420
+ }
421
+ };
422
+ //#endregion
423
+ exports.InteractiveCaptchaManager = InteractiveCaptchaManager;
@@ -1,20 +1,21 @@
1
1
  const require_usageCounters = require("../../util/usageCounters.cjs");
2
- const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
3
- const require_clientMetaData = require("../../utils/clientMetaData.cjs");
2
+ const require_rawTlsSignalsMiddleware = require("../../api/rawTlsSignalsMiddleware.cjs");
4
3
  const require_compositeIpAddress = require("../../compositeIpAddress.cjs");
5
- const require_enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
6
- const require_captchaManager = require("../captchaManager.cjs");
7
- const require_routingMachine = require("../frictionless/routingMachine.cjs");
8
4
  const require_util = require("../../util.cjs");
5
+ const require_clientMetaData = require("../../utils/clientMetaData.cjs");
9
6
  const require_devicePlatform = require("../../utils/devicePlatform.cjs");
7
+ const require_enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
8
+ const require_captchaManager = require("../captchaManager.cjs");
9
+ const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
10
10
  const require_frictionlessTasksUtils = require("../frictionless/frictionlessTasksUtils.cjs");
11
- const require_evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
12
11
  const require_powTasksUtils = require("./powTasksUtils.cjs");
12
+ const require_evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
13
+ const require_routingMachine = require("../frictionless/routingMachine.cjs");
13
14
  let _prosopo_common = require("@prosopo/common");
14
15
  let _prosopo_types = require("@prosopo/types");
15
- let _prosopo_util = require("@prosopo/util");
16
- let _prosopo_user_access_policy = require("@prosopo/user-access-policy");
17
16
  let _polkadot_util = require("@polkadot/util");
17
+ let _prosopo_user_access_policy = require("@prosopo/user-access-policy");
18
+ let _prosopo_util = require("@prosopo/util");
18
19
  //#region src/tasks/powCaptcha/powTasks.ts
19
20
  var DEFAULT_POW_DIFFICULTY = 4;
20
21
  var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
@@ -209,7 +210,8 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
209
210
  let routingOutput = this.postPowContext ? await this.runPostPowRouting({
210
211
  challengeRecord,
211
212
  challengeSplit,
212
- behavioralDataPacked: decryptedBehavioralDataPacked
213
+ behavioralDataPacked: decryptedBehavioralDataPacked,
214
+ coords
213
215
  }) : void 0;
214
216
  if ((escalateForMissingCoords || escalateForIpChange) && routingOutput?.captchaType !== _prosopo_types.CaptchaType.image && routingOutput?.captchaType !== _prosopo_types.CaptchaType.puzzle) routingOutput = {
215
217
  captchaType: _prosopo_types.CaptchaType.image,
@@ -228,7 +230,7 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
228
230
  */
229
231
  async runPostPowRouting(args) {
230
232
  if (!this.postPowContext) return void 0;
231
- const { challengeRecord, challengeSplit, behavioralDataPacked } = args;
233
+ const { challengeRecord, challengeSplit, behavioralDataPacked, coords } = args;
232
234
  if (!challengeRecord.sessionId) {
233
235
  this.logger.debug(() => ({ msg: "Skipping post-pow routing: PoW record has no linked session" }));
234
236
  return;
@@ -259,6 +261,8 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
259
261
  raw: {
260
262
  ...this.postPowContext.raw,
261
263
  ...behavioralDataPacked && { behavioralDataPacked },
264
+ ...sessionRecord.mode && { mode: sessionRecord.mode },
265
+ coordsAllZero: require_powTasksUtils.isCoordsAllZero(coords),
262
266
  ...sessionRecord.simdReadings && { simd: sessionRecord.simdReadings },
263
267
  ...sessionRecord.currentUrl && { currentUrl: sessionRecord.currentUrl },
264
268
  ...sessionRecord.iframeUrl && { iframeUrl: sessionRecord.iframeUrl }
@@ -518,15 +522,7 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
518
522
  currentUrl: sessionRecord?.currentUrl,
519
523
  iframeUrl: sessionRecord?.iframeUrl,
520
524
  coords: challengeRecord.coords,
521
- synNs: sessionRecord?.synNs,
522
- synackNs: sessionRecord?.synackNs,
523
- ackNs: sessionRecord?.ackNs,
524
- observedTtl: sessionRecord?.observedTtl,
525
- tcpMss: sessionRecord?.tcpMss,
526
- tcpWscale: sessionRecord?.tcpWscale,
527
- tcpOptsFlags: sessionRecord?.tcpOptsFlags,
528
- tcpOptsOrder: sessionRecord?.tcpOptsOrder,
529
- tcpWindow: sessionRecord?.tcpWindow,
525
+ ...require_rawTlsSignalsMiddleware.rawTlsSignalsFromRecord(sessionRecord),
530
526
  trafficPolicies: require_devicePlatform.deriveTrafficPolicies(trafficFilter)
531
527
  };
532
528
  const decision = await this.decisionMachineRunner.decide(decisionInput, logger);
@@ -1,7 +1,7 @@
1
1
  let _prosopo_common = require("@prosopo/common");
2
+ let _polkadot_util = require("@polkadot/util");
2
3
  let _prosopo_util = require("@prosopo/util");
3
4
  let _prosopo_util_crypto = require("@prosopo/util-crypto");
4
- let _polkadot_util = require("@polkadot/util");
5
5
  let _noble_hashes_sha2_js = require("@noble/hashes/sha2.js");
6
6
  //#region src/tasks/powCaptcha/powTasksUtils.ts
7
7
  var validateSolution = (nonce, challenge, difficulty) => (0, _prosopo_util.hashMeetsDifficulty)((0, _noble_hashes_sha2_js.sha256)(new TextEncoder().encode(nonce + challenge)), difficulty);
@@ -15,6 +15,8 @@ var checkPowSignature = (message, signature, address, signatureType) => {
15
15
  signatureType
16
16
  } });
17
17
  };
18
+ var isCoordsAllZero = (coords) => coords !== void 0 && coords.length > 0 && coords.every((group) => group.length > 0 && group.every(([x, y]) => x === 0 && y === 0));
18
19
  //#endregion
19
20
  exports.checkPowSignature = checkPowSignature;
21
+ exports.isCoordsAllZero = isCoordsAllZero;
20
22
  exports.validateSolution = validateSolution;
@@ -15,12 +15,12 @@ var createPuzzleBackgroundBuffer = (options = {}) => {
15
15
  timer.unref?.();
16
16
  return {
17
17
  take() {
18
- const image = ready.pop();
19
- if (!image) {
18
+ const background = ready.pop();
19
+ if (!background) {
20
20
  starved++;
21
21
  return require_nativeBackground.createBackgroundNative(geometry);
22
22
  }
23
- return image;
23
+ return background;
24
24
  },
25
25
  depth: () => ready.length,
26
26
  starvations: () => starved,
@@ -15,15 +15,22 @@ var nativePuzzle = (() => {
15
15
  * Byte-identical to `createBackground` from @prosopo/puzzle-assets given the
16
16
  * same seed — the JS remains the reference implementation and the contract
17
17
  * the differential test pins. Single-use is unchanged and still the caller's
18
- * responsibility: this mints a fresh CSPRNG seed per call and the seed never
19
- * leaves the process.
18
+ * responsibility.
19
+ *
20
+ * The seed is returned so the challenge record can keep it and the portal can
21
+ * regenerate this background later. See the secrecy note in prng.ts for where
22
+ * it may and may not go.
20
23
  */
21
24
  var createBackgroundNative = (geometry = _prosopo_puzzle_assets.DEFAULT_GEOMETRY) => {
22
25
  const { width, height } = geometry;
26
+ const seed = (0, _prosopo_puzzle_assets.createSeed)();
23
27
  return {
24
- data: require_metrics.measureSync("puzzle_background", () => nativePuzzle.generateBackground((0, _prosopo_puzzle_assets.createSeed)(), width, height)),
25
- width,
26
- height
28
+ image: {
29
+ data: require_metrics.measureSync("puzzle_background", () => nativePuzzle.generateBackground(seed, width, height)),
30
+ width,
31
+ height
32
+ },
33
+ seed
27
34
  };
28
35
  };
29
36
  //#endregion
@@ -79,15 +79,16 @@ var isPuzzleRenderAvailable = () => {
79
79
  };
80
80
  var renderPuzzleImages = async (placement, settings = _prosopo_puzzle_assets.DEFAULT_RENDER_SETTINGS, pieceSize) => {
81
81
  const background = (require_backgroundBuffer.getPuzzleBackgroundBuffer() ?? require_backgroundBuffer.initPuzzleBackgroundBuffer()).take();
82
- if (!background) throw new Error("puzzle renderer: no background available");
83
- const rendered = await require_metrics.measureSync("puzzle_render", () => (0, _prosopo_puzzle_assets.renderPuzzle)(background, placement, pieceSize !== void 0 ? {
82
+ const rendered = await require_metrics.measureSync("puzzle_render", () => (0, _prosopo_puzzle_assets.renderPuzzle)(background.image, placement, pieceSize !== void 0 ? {
84
83
  ..._prosopo_puzzle_assets.DEFAULT_GEOMETRY,
85
84
  pieceSize
86
85
  } : _prosopo_puzzle_assets.DEFAULT_GEOMETRY, settings));
87
86
  return {
88
87
  background: (0, _prosopo_puzzle_assets.toDataUri)(rendered.background),
89
88
  piece: (0, _prosopo_puzzle_assets.toDataUri)(rendered.piece),
90
- pieceSize: rendered.pieceSize
89
+ pieceSize: rendered.pieceSize,
90
+ backgroundSeed: background.seed.toString("hex"),
91
+ renderSeed: rendered.seed.toString("hex")
91
92
  };
92
93
  };
93
94
  //#endregion