@prosopo/provider 5.19.3 → 5.20.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 (295) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +45 -40
  2. package/.turbo/turbo-build$colon$tsc.log +28 -28
  3. package/.turbo/turbo-build.log +48 -40
  4. package/CHANGELOG.md +167 -0
  5. package/dist/api/admin/apiClearAllCountersEndpoint.js.map +1 -1
  6. package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.js.map +1 -1
  7. package/dist/api/admin/apiGetDecisionMachineEndpoint.js.map +1 -1
  8. package/dist/api/admin/apiGetSessionEndpoint.js.map +1 -1
  9. package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.js.map +1 -1
  10. package/dist/api/admin/apiRemoveDecisionMachineEndpoint.js.map +1 -1
  11. package/dist/api/admin/apiRemoveSiteKeyEndpoint.js.map +1 -1
  12. package/dist/api/admin/apiRemoveSiteKeysEndpoint.js.map +1 -1
  13. package/dist/api/admin/apiReplaceDetectorPoolEndpoint.js.map +1 -1
  14. package/dist/api/admin/apiUpdateDecisionMachineEndpoint.js.map +1 -1
  15. package/dist/api/blacklistRequestInspector.d.ts.map +1 -1
  16. package/dist/api/blacklistRequestInspector.js +9 -8
  17. package/dist/api/blacklistRequestInspector.js.map +1 -1
  18. package/dist/api/captcha/checkSpamEmail.d.ts.map +1 -1
  19. package/dist/api/captcha/checkSpamEmail.js +19 -26
  20. package/dist/api/captcha/checkSpamEmail.js.map +1 -1
  21. package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.d.ts.map +1 -1
  22. package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.js +11 -2
  23. package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.js.map +1 -1
  24. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.d.ts.map +1 -1
  25. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js +6 -1
  26. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js.map +1 -1
  27. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.d.ts.map +1 -1
  28. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js +30 -27
  29. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js.map +1 -1
  30. package/dist/api/captcha/getImageCaptchaChallenge.d.ts.map +1 -1
  31. package/dist/api/captcha/getImageCaptchaChallenge.js +32 -43
  32. package/dist/api/captcha/getImageCaptchaChallenge.js.map +1 -1
  33. package/dist/api/captcha/getPoWCaptchaChallenge.d.ts.map +1 -1
  34. package/dist/api/captcha/getPoWCaptchaChallenge.js +27 -32
  35. package/dist/api/captcha/getPoWCaptchaChallenge.js.map +1 -1
  36. package/dist/api/captcha/getPuzzleCaptchaChallenge.d.ts +3 -0
  37. package/dist/api/captcha/getPuzzleCaptchaChallenge.d.ts.map +1 -1
  38. package/dist/api/captcha/getPuzzleCaptchaChallenge.js +23 -5
  39. package/dist/api/captcha/getPuzzleCaptchaChallenge.js.map +1 -1
  40. package/dist/api/captcha/interactiveCaptchaChallenge.d.ts.map +1 -1
  41. package/dist/api/captcha/interactiveCaptchaChallenge.js +27 -32
  42. package/dist/api/captcha/interactiveCaptchaChallenge.js.map +1 -1
  43. package/dist/api/captcha/interactiveCaptchaSolution.d.ts.map +1 -1
  44. package/dist/api/captcha/interactiveCaptchaSolution.js +18 -24
  45. package/dist/api/captcha/interactiveCaptchaSolution.js.map +1 -1
  46. package/dist/api/captcha/submitImageCaptchaSolution.d.ts.map +1 -1
  47. package/dist/api/captcha/submitImageCaptchaSolution.js +18 -24
  48. package/dist/api/captcha/submitImageCaptchaSolution.js.map +1 -1
  49. package/dist/api/captcha/submitPoWCaptchaSolution.d.ts.map +1 -1
  50. package/dist/api/captcha/submitPoWCaptchaSolution.js +35 -27
  51. package/dist/api/captcha/submitPoWCaptchaSolution.js.map +1 -1
  52. package/dist/api/domainMiddleware.d.ts.map +1 -1
  53. package/dist/api/domainMiddleware.js +39 -47
  54. package/dist/api/domainMiddleware.js.map +1 -1
  55. package/dist/api/errorCodeForReason.d.ts +3 -0
  56. package/dist/api/errorCodeForReason.d.ts.map +1 -0
  57. package/dist/api/errorCodeForReason.js +22 -0
  58. package/dist/api/errorCodeForReason.js.map +1 -0
  59. package/dist/api/headerCheckMiddleware.d.ts.map +1 -1
  60. package/dist/api/headerCheckMiddleware.js +14 -9
  61. package/dist/api/headerCheckMiddleware.js.map +1 -1
  62. package/dist/api/ipInfoMiddleware.d.ts +1 -1
  63. package/dist/api/ipInfoMiddleware.d.ts.map +1 -1
  64. package/dist/api/ipInfoMiddleware.js +5 -1
  65. package/dist/api/ipInfoMiddleware.js.map +1 -1
  66. package/dist/api/metrics.d.ts.map +1 -1
  67. package/dist/api/metrics.js +9 -1
  68. package/dist/api/metrics.js.map +1 -1
  69. package/dist/api/public.d.ts.map +1 -1
  70. package/dist/api/public.js +6 -2
  71. package/dist/api/public.js.map +1 -1
  72. package/dist/api/rateLimitHandler.d.ts +4 -0
  73. package/dist/api/rateLimitHandler.d.ts.map +1 -0
  74. package/dist/api/rateLimitHandler.js +20 -0
  75. package/dist/api/rateLimitHandler.js.map +1 -0
  76. package/dist/api/startProviderApi.d.ts +1 -0
  77. package/dist/api/startProviderApi.d.ts.map +1 -1
  78. package/dist/api/startProviderApi.js +8 -17
  79. package/dist/api/startProviderApi.js.map +1 -1
  80. package/dist/api/validateAddress.d.ts +3 -4
  81. package/dist/api/validateAddress.d.ts.map +1 -1
  82. package/dist/api/validateAddress.js +13 -19
  83. package/dist/api/validateAddress.js.map +1 -1
  84. package/dist/api/verify.d.ts.map +1 -1
  85. package/dist/api/verify.js +73 -96
  86. package/dist/api/verify.js.map +1 -1
  87. package/dist/cjs/api/blacklistRequestInspector.cjs +9 -8
  88. package/dist/cjs/api/captcha/checkSpamEmail.cjs +18 -25
  89. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.cjs +11 -2
  90. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.cjs +6 -1
  91. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +29 -26
  92. package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +31 -42
  93. package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +26 -31
  94. package/dist/cjs/api/captcha/getPuzzleCaptchaChallenge.cjs +22 -3
  95. package/dist/cjs/api/captcha/interactiveCaptchaChallenge.cjs +26 -31
  96. package/dist/cjs/api/captcha/interactiveCaptchaSolution.cjs +17 -23
  97. package/dist/cjs/api/captcha/submitImageCaptchaSolution.cjs +17 -23
  98. package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +34 -26
  99. package/dist/cjs/api/domainMiddleware.cjs +38 -46
  100. package/dist/cjs/api/errorCodeForReason.cjs +22 -0
  101. package/dist/cjs/api/headerCheckMiddleware.cjs +13 -8
  102. package/dist/cjs/api/ipInfoMiddleware.cjs +5 -1
  103. package/dist/cjs/api/metrics.cjs +9 -1
  104. package/dist/cjs/api/public.cjs +5 -1
  105. package/dist/cjs/api/rateLimitHandler.cjs +20 -0
  106. package/dist/cjs/api/startProviderApi.cjs +8 -16
  107. package/dist/cjs/api/validateAddress.cjs +12 -18
  108. package/dist/cjs/api/verify.cjs +72 -95
  109. package/dist/cjs/index.cjs +1 -0
  110. package/dist/cjs/tasks/captchaManager.cjs +6 -8
  111. package/dist/cjs/tasks/client/clientTasks.cjs +26 -13
  112. package/dist/cjs/tasks/dataset/datasetTasksUtils.cjs +28 -8
  113. package/dist/cjs/tasks/decisionMachine/decisionMachineRunner.cjs +21 -19
  114. package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +1 -1
  115. package/dist/cjs/tasks/frictionless/routingMachine.cjs +13 -4
  116. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +89 -40
  117. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasksUtils.cjs +18 -8
  118. package/dist/cjs/tasks/interactiveCaptcha/interactiveCaptchaManager.cjs +21 -13
  119. package/dist/cjs/tasks/powCaptcha/backgroundWrites.cjs +24 -0
  120. package/dist/cjs/tasks/powCaptcha/powTasks.cjs +44 -19
  121. package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +14 -10
  122. package/dist/cjs/tasks/puzzle/puzzleRenderer.cjs +17 -8
  123. package/dist/cjs/tasks/signatureCheck.cjs +12 -0
  124. package/dist/cjs/tasks/tasks.cjs +6 -1
  125. package/dist/cjs/util/usageCounters.cjs +26 -3
  126. package/dist/cjs/util.cjs +14 -3
  127. package/dist/cjs/utils/devicePlatform.cjs +9 -5
  128. package/dist/cjs/utils/mobileSignals.cjs +69 -0
  129. package/dist/errorSites.d.ts +98 -0
  130. package/dist/errorSites.d.ts.map +1 -0
  131. package/dist/errorSites.js +2 -0
  132. package/dist/errorSites.js.map +1 -0
  133. package/dist/fingerprint/dist/merkle.js +69 -0
  134. package/dist/fingerprint/dist/proof.js +95 -0
  135. package/dist/fingerprint/dist/summary.js +73 -0
  136. package/dist/index.js +2 -2
  137. package/dist/tasks/captchaManager.d.ts +2 -3
  138. package/dist/tasks/captchaManager.d.ts.map +1 -1
  139. package/dist/tasks/captchaManager.js +6 -7
  140. package/dist/tasks/captchaManager.js.map +1 -1
  141. package/dist/tasks/client/clientTasks.d.ts.map +1 -1
  142. package/dist/tasks/client/clientTasks.js +27 -14
  143. package/dist/tasks/client/clientTasks.js.map +1 -1
  144. package/dist/tasks/dataset/datasetTasksUtils.d.ts.map +1 -1
  145. package/dist/tasks/dataset/datasetTasksUtils.js +29 -9
  146. package/dist/tasks/dataset/datasetTasksUtils.js.map +1 -1
  147. package/dist/tasks/decisionMachine/decisionMachineRunner.d.ts +1 -3
  148. package/dist/tasks/decisionMachine/decisionMachineRunner.d.ts.map +1 -1
  149. package/dist/tasks/decisionMachine/decisionMachineRunner.js +21 -19
  150. package/dist/tasks/decisionMachine/decisionMachineRunner.js.map +1 -1
  151. package/dist/tasks/frictionless/frictionlessTasks.d.ts.map +1 -1
  152. package/dist/tasks/frictionless/frictionlessTasks.js +1 -1
  153. package/dist/tasks/frictionless/frictionlessTasks.js.map +1 -1
  154. package/dist/tasks/frictionless/routingMachine.d.ts.map +1 -1
  155. package/dist/tasks/frictionless/routingMachine.js +13 -4
  156. package/dist/tasks/frictionless/routingMachine.js.map +1 -1
  157. package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +1 -1
  158. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +91 -42
  159. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +1 -1
  160. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js +19 -9
  161. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js.map +1 -1
  162. package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.d.ts.map +1 -1
  163. package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.js +22 -14
  164. package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.js.map +1 -1
  165. package/dist/tasks/powCaptcha/backgroundWrites.d.ts +7 -0
  166. package/dist/tasks/powCaptcha/backgroundWrites.d.ts.map +1 -0
  167. package/dist/tasks/powCaptcha/backgroundWrites.js +24 -0
  168. package/dist/tasks/powCaptcha/backgroundWrites.js.map +1 -0
  169. package/dist/tasks/powCaptcha/powTasks.d.ts +3 -3
  170. package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
  171. package/dist/tasks/powCaptcha/powTasks.js +45 -20
  172. package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
  173. package/dist/tasks/powCaptcha/powTasksUtils.d.ts.map +1 -1
  174. package/dist/tasks/powCaptcha/powTasksUtils.js +15 -11
  175. package/dist/tasks/powCaptcha/powTasksUtils.js.map +1 -1
  176. package/dist/tasks/puzzle/puzzleRenderer.d.ts +8 -1
  177. package/dist/tasks/puzzle/puzzleRenderer.d.ts.map +1 -1
  178. package/dist/tasks/puzzle/puzzleRenderer.js +16 -8
  179. package/dist/tasks/puzzle/puzzleRenderer.js.map +1 -1
  180. package/dist/tasks/signatureCheck.d.ts +2 -0
  181. package/dist/tasks/signatureCheck.d.ts.map +1 -0
  182. package/dist/tasks/signatureCheck.js +12 -0
  183. package/dist/tasks/signatureCheck.js.map +1 -0
  184. package/dist/tasks/tasks.d.ts.map +1 -1
  185. package/dist/tasks/tasks.js +7 -2
  186. package/dist/tasks/tasks.js.map +1 -1
  187. package/dist/tests/integration/api/admin/apiRegisterSiteKeyEndpoint.integration.test.js +3 -1
  188. package/dist/tests/integration/api/admin/apiRegisterSiteKeyEndpoint.integration.test.js.map +1 -1
  189. package/dist/tests/integration/api/admin/apiRegisterSiteKeysEndpoint.integration.test.js +6 -2
  190. package/dist/tests/integration/api/admin/apiRegisterSiteKeysEndpoint.integration.test.js.map +1 -1
  191. package/dist/tests/integration/escalationPeekBeforeConsume.integration.test.js +1 -1
  192. package/dist/tests/integration/escalationPeekBeforeConsume.integration.test.js.map +1 -1
  193. package/dist/tests/integration/imgCaptcha.integration.test.js +6 -5
  194. package/dist/tests/integration/imgCaptcha.integration.test.js.map +1 -1
  195. package/dist/tests/integration/ipValidation.integration.test.js +1 -1
  196. package/dist/tests/integration/ipValidation.integration.test.js.map +1 -1
  197. package/dist/tests/integration/powCaptcha.integration.test.js +2 -2
  198. package/dist/tests/integration/powCaptcha.integration.test.js.map +1 -1
  199. package/dist/tests/integration/routingDecisionMachines.integration.test.js.map +1 -1
  200. package/dist/tests/integration/testUtils.d.ts +2 -2
  201. package/dist/tests/integration/testUtils.d.ts.map +1 -1
  202. package/dist/tests/integration/testUtils.js +1 -1
  203. package/dist/tests/integration/testUtils.js.map +1 -1
  204. package/dist/tests/integration/webBotAuthAuthenticated.integration.test.js +3 -1
  205. package/dist/tests/integration/webBotAuthAuthenticated.integration.test.js.map +1 -1
  206. package/dist/tests/unit/api/blacklistRequestInspector.unit.test.js +26 -10
  207. package/dist/tests/unit/api/blacklistRequestInspector.unit.test.js.map +1 -1
  208. package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.js +4 -4
  209. package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.js.map +1 -1
  210. package/dist/tests/unit/api/captcha/puzzleTouchFloors.unit.test.d.ts +2 -0
  211. package/dist/tests/unit/api/captcha/puzzleTouchFloors.unit.test.d.ts.map +1 -0
  212. package/dist/tests/unit/api/captcha/puzzleTouchFloors.unit.test.js +210 -0
  213. package/dist/tests/unit/api/captcha/puzzleTouchFloors.unit.test.js.map +1 -0
  214. package/dist/tests/unit/api/captcha/submitSolutionBadSignature.unit.test.d.ts +2 -0
  215. package/dist/tests/unit/api/captcha/submitSolutionBadSignature.unit.test.d.ts.map +1 -0
  216. package/dist/tests/unit/api/captcha/submitSolutionBadSignature.unit.test.js +153 -0
  217. package/dist/tests/unit/api/captcha/submitSolutionBadSignature.unit.test.js.map +1 -0
  218. package/dist/tests/unit/api/domainMiddlewareErrorBody.unit.test.js +6 -2
  219. package/dist/tests/unit/api/domainMiddlewareErrorBody.unit.test.js.map +1 -1
  220. package/dist/tests/unit/api/errorCodeForReason.unit.test.d.ts +2 -0
  221. package/dist/tests/unit/api/errorCodeForReason.unit.test.d.ts.map +1 -0
  222. package/dist/tests/unit/api/errorCodeForReason.unit.test.js +23 -0
  223. package/dist/tests/unit/api/errorCodeForReason.unit.test.js.map +1 -0
  224. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +6 -1
  225. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
  226. package/dist/tests/unit/api/headerCheckMiddleware.unit.test.js +16 -7
  227. package/dist/tests/unit/api/headerCheckMiddleware.unit.test.js.map +1 -1
  228. package/dist/tests/unit/api/ipInfoMiddleware.unit.test.d.ts +2 -0
  229. package/dist/tests/unit/api/ipInfoMiddleware.unit.test.d.ts.map +1 -0
  230. package/dist/tests/unit/api/ipInfoMiddleware.unit.test.js +46 -0
  231. package/dist/tests/unit/api/ipInfoMiddleware.unit.test.js.map +1 -0
  232. package/dist/tests/unit/api/public.unit.test.js +45 -10
  233. package/dist/tests/unit/api/public.unit.test.js.map +1 -1
  234. package/dist/tests/unit/api/rateLimitHandler.unit.test.d.ts +2 -0
  235. package/dist/tests/unit/api/rateLimitHandler.unit.test.d.ts.map +1 -0
  236. package/dist/tests/unit/api/rateLimitHandler.unit.test.js +39 -0
  237. package/dist/tests/unit/api/rateLimitHandler.unit.test.js.map +1 -0
  238. package/dist/tests/unit/api/validateAddress.unit.test.js +41 -115
  239. package/dist/tests/unit/api/validateAddress.unit.test.js.map +1 -1
  240. package/dist/tests/unit/api/verifyMalformedToken.unit.test.js +3 -3
  241. package/dist/tests/unit/api/verifyMalformedToken.unit.test.js.map +1 -1
  242. package/dist/tests/unit/tasks/captchaManager.unit.test.js +22 -18
  243. package/dist/tests/unit/tasks/captchaManager.unit.test.js.map +1 -1
  244. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js +25 -0
  245. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +1 -1
  246. package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.js +25 -20
  247. package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.js.map +1 -1
  248. package/dist/tests/unit/tasks/decisionMachine/decisionMachineRunner.unit.test.js +31 -0
  249. package/dist/tests/unit/tasks/decisionMachine/decisionMachineRunner.unit.test.js.map +1 -1
  250. package/dist/tests/unit/tasks/frictionless/fingerprintBucketFlow.unit.test.d.ts +2 -0
  251. package/dist/tests/unit/tasks/frictionless/fingerprintBucketFlow.unit.test.d.ts.map +1 -0
  252. package/dist/tests/unit/tasks/frictionless/fingerprintBucketFlow.unit.test.js +80 -0
  253. package/dist/tests/unit/tasks/frictionless/fingerprintBucketFlow.unit.test.js.map +1 -0
  254. package/dist/tests/unit/tasks/frictionless/routingMachine.unit.test.js +48 -0
  255. package/dist/tests/unit/tasks/frictionless/routingMachine.unit.test.js.map +1 -1
  256. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js +20 -28
  257. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js.map +1 -1
  258. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js +2 -2
  259. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js.map +1 -1
  260. package/dist/tests/unit/tasks/powCaptcha/backgroundWrites.unit.test.d.ts +2 -0
  261. package/dist/tests/unit/tasks/powCaptcha/backgroundWrites.unit.test.d.ts.map +1 -0
  262. package/dist/tests/unit/tasks/powCaptcha/backgroundWrites.unit.test.js +44 -0
  263. package/dist/tests/unit/tasks/powCaptcha/backgroundWrites.unit.test.js.map +1 -0
  264. package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js +78 -43
  265. package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js.map +1 -1
  266. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js +7 -6
  267. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js.map +1 -1
  268. package/dist/tests/unit/tasks/puzzleCaptcha/puzzleTasks.unit.test.js +2 -2
  269. package/dist/tests/unit/tasks/puzzleCaptcha/puzzleTasks.unit.test.js.map +1 -1
  270. package/dist/tests/unit/util/usageCounters.unit.test.js +20 -0
  271. package/dist/tests/unit/util/usageCounters.unit.test.js.map +1 -1
  272. package/dist/tests/unit/util.unit.test.js +7 -7
  273. package/dist/tests/unit/util.unit.test.js.map +1 -1
  274. package/dist/tests/unit/utils/devicePlatform.unit.test.js +9 -8
  275. package/dist/tests/unit/utils/devicePlatform.unit.test.js.map +1 -1
  276. package/dist/tests/unit/utils/mobileSignals.unit.test.d.ts +2 -0
  277. package/dist/tests/unit/utils/mobileSignals.unit.test.d.ts.map +1 -0
  278. package/dist/tests/unit/utils/mobileSignals.unit.test.js +161 -0
  279. package/dist/tests/unit/utils/mobileSignals.unit.test.js.map +1 -0
  280. package/dist/util/usageCounters.d.ts +1 -1
  281. package/dist/util/usageCounters.d.ts.map +1 -1
  282. package/dist/util/usageCounters.js +26 -3
  283. package/dist/util/usageCounters.js.map +1 -1
  284. package/dist/util.d.ts.map +1 -1
  285. package/dist/util.js +15 -4
  286. package/dist/util.js.map +1 -1
  287. package/dist/utils/devicePlatform.d.ts +3 -3
  288. package/dist/utils/devicePlatform.d.ts.map +1 -1
  289. package/dist/utils/devicePlatform.js +9 -5
  290. package/dist/utils/devicePlatform.js.map +1 -1
  291. package/dist/utils/mobileSignals.d.ts +32 -0
  292. package/dist/utils/mobileSignals.d.ts.map +1 -0
  293. package/dist/utils/mobileSignals.js +68 -0
  294. package/dist/utils/mobileSignals.js.map +1 -0
  295. package/package.json +44 -43
@@ -8,6 +8,7 @@ const require_enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
8
8
  const require_captchaManager = require("../captchaManager.cjs");
9
9
  const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
10
10
  const require_frictionlessTasksUtils = require("../frictionless/frictionlessTasksUtils.cjs");
11
+ const require_signatureCheck = require("../signatureCheck.cjs");
11
12
  const require_evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
12
13
  const require_lang = require("../../rules/lang.cjs");
13
14
  const require_pairs = require("../../pairs.cjs");
@@ -29,24 +30,38 @@ var ImgCaptchaManager = class extends require_captchaManager.CaptchaManager {
29
30
  }
30
31
  async getCaptchaWithProof(datasetId, solved, size) {
31
32
  const captchaDocs = await this.db.getRandomCaptcha(solved, datasetId, size);
32
- if (!captchaDocs) throw new _prosopo_common.ProsopoEnvError("DATABASE.CAPTCHA_GET_FAILED", { context: {
33
- failedFuncName: this.getCaptchaWithProof.name,
34
- datasetId,
35
- solved,
36
- size
37
- } });
33
+ if (!captchaDocs) throw new _prosopo_common.ProsopoError({
34
+ code: "DB_QUERY_FAILED",
35
+ errorSite: "PROV-59",
36
+ message: "Failed to get captcha",
37
+ context: {
38
+ failedFuncName: this.getCaptchaWithProof.name,
39
+ datasetId,
40
+ solved,
41
+ size
42
+ }
43
+ });
38
44
  return captchaDocs;
39
45
  }
40
46
  async getRandomCaptchasAndRequestHash(datasetId, userAccount, ipAddress, captchaConfig, threshold, sessionId, ipInfo) {
41
47
  const dataset = await this.db.getDatasetDetails(datasetId);
42
- if (!dataset) throw new _prosopo_common.ProsopoEnvError("DATABASE.DATASET_GET_FAILED", { context: {
43
- failedFuncName: this.getRandomCaptchasAndRequestHash.name,
44
- dataset,
45
- datasetId
46
- } });
48
+ if (!dataset) throw new _prosopo_common.ProsopoError({
49
+ code: "DB_QUERY_FAILED",
50
+ errorSite: "PROV-60",
51
+ message: "Failed to get dataset",
52
+ context: {
53
+ failedFuncName: this.getRandomCaptchasAndRequestHash.name,
54
+ dataset,
55
+ datasetId
56
+ }
57
+ });
47
58
  const unsolvedCount = Math.abs(Math.trunc(captchaConfig.unsolved.count));
48
59
  const solvedCount = Math.abs(Math.trunc(captchaConfig.solved.count));
49
- if (!solvedCount) throw new _prosopo_common.ProsopoEnvError("CONFIG.INVALID_CAPTCHA_NUMBER");
60
+ if (!solvedCount) throw new _prosopo_common.ProsopoError({
61
+ code: "CONFIG_INVALID",
62
+ errorSite: "PROV-61",
63
+ message: "Please configure captchas configurations correctly"
64
+ });
50
65
  const solved = await this.getCaptchaWithProof(datasetId, true, solvedCount);
51
66
  let unsolved = [];
52
67
  if (unsolvedCount) unsolved = await this.getCaptchaWithProof(datasetId, false, unsolvedCount);
@@ -81,23 +96,33 @@ var ImgCaptchaManager = class extends require_captchaManager.CaptchaManager {
81
96
  * @return {Promise<DappUserSolutionResult>} result containing the contract event
82
97
  */
83
98
  async dappUserSolution(userAccount, dappAccount, requestHash, captchas, userTimestampSignature, timestamp, providerRequestHashSignature, ipAddress, headers, ja4, behavioralData, ipInfo, simdReadings, clientMetaData) {
84
- if (!(0, _prosopo_util_crypto.signatureVerify)((0, _polkadot_util.stringToHex)(timestamp.toString()), userTimestampSignature, userAccount).isValid) {
85
- const err = new _prosopo_common.ProsopoEnvError("GENERAL.INVALID_SIGNATURE", { context: {
86
- failedFuncName: this.dappUserSolution.name,
87
- userAccount
88
- } });
99
+ if (!require_signatureCheck.isSignatureValid(timestamp.toString(), userTimestampSignature, userAccount)) {
100
+ const err = new _prosopo_common.ProsopoError({
101
+ code: "UNAUTHORIZED",
102
+ errorSite: "PROV-62",
103
+ message: "Invalid signature",
104
+ context: {
105
+ failedFuncName: this.dappUserSolution.name,
106
+ userAccount
107
+ }
108
+ });
89
109
  this.logger.info(() => ({
90
110
  err,
91
111
  msg: "Invalid user timestamp signature"
92
112
  }));
93
113
  throw err;
94
114
  }
95
- if (!(0, _prosopo_util_crypto.signatureVerify)((0, _polkadot_util.stringToHex)(requestHash.toString()), providerRequestHashSignature, this.pair.address).isValid) {
96
- const err = new _prosopo_common.ProsopoEnvError("GENERAL.INVALID_SIGNATURE", { context: {
97
- failedFuncName: this.dappUserSolution.name,
98
- userAccount,
99
- error: "requestHash signature is invalid"
100
- } });
115
+ if (!require_signatureCheck.isSignatureValid(requestHash.toString(), providerRequestHashSignature, this.pair.address)) {
116
+ const err = new _prosopo_common.ProsopoError({
117
+ code: "UNAUTHORIZED",
118
+ errorSite: "PROV-63",
119
+ message: "Invalid signature",
120
+ context: {
121
+ failedFuncName: this.dappUserSolution.name,
122
+ userAccount,
123
+ error: "requestHash signature is invalid"
124
+ }
125
+ });
101
126
  this.logger.info(() => ({
102
127
  err,
103
128
  msg: "Invalid provider requestHash signature"
@@ -130,7 +155,12 @@ var ImgCaptchaManager = class extends require_captchaManager.CaptchaManager {
130
155
  const inputMethodsDeclared = receivedCaptchas.some((c) => c.inputMethods !== void 0);
131
156
  const { tree, commitmentId } = require_imgCaptchaTasksUtils.buildTreeAndGetCommitmentId(receivedCaptchas);
132
157
  const datasetId = (0, _prosopo_util.at)(storedCaptchas, 0).datasetId;
133
- if (!datasetId) throw new _prosopo_common.ProsopoEnvError("CAPTCHA.ID_MISMATCH", { context: { failedFuncName: this.dappUserSolution.name } });
158
+ if (!datasetId) throw new _prosopo_common.ProsopoError({
159
+ code: "INVALID_DATA",
160
+ errorSite: "PROV-64",
161
+ message: "captcha id mismatch",
162
+ context: { failedFuncName: this.dappUserSolution.name }
163
+ });
134
164
  if (!await this.db.updatePendingImageCommitmentStatus(requestHash)) {
135
165
  this.logger.info(() => ({ msg: "Request hash already consumed by a concurrent submission" }));
136
166
  return response;
@@ -198,7 +228,11 @@ var ImgCaptchaManager = class extends require_captchaManager.CaptchaManager {
198
228
  await this.db.storeUserImageCaptchaSolution(receivedCaptchas, commit);
199
229
  const solutionRecords = await Promise.all(storedCaptchas.map(async (captcha) => {
200
230
  const solutionRecord = await this.db.getSolutionByCaptchaId(captcha.captchaId);
201
- if (!solutionRecord) throw new _prosopo_common.ProsopoEnvError("CAPTCHA.SOLUTION_NOT_FOUND", { context: { failedFuncName: this.dappUserSolution.name } });
231
+ if (!solutionRecord) throw new _prosopo_common.ProsopoError({
232
+ code: "SOLUTION_NOT_FOUND",
233
+ errorSite: "PROV-65",
234
+ context: { failedFuncName: this.dappUserSolution.name }
235
+ });
202
236
  return solutionRecord;
203
237
  }));
204
238
  const totalImages = storedCaptchas[0]?.items.length || 0;
@@ -276,14 +310,24 @@ var ImgCaptchaManager = class extends require_captchaManager.CaptchaManager {
276
310
  const receivedCaptchas = (0, _prosopo_datasets.parseAndSortCaptchaSolutions)(captchas);
277
311
  const captchaIds = receivedCaptchas.map((captcha) => captcha.captchaId);
278
312
  const storedCaptchas = await this.db.getCaptchaById(captchaIds);
279
- if (!storedCaptchas || receivedCaptchas.length !== storedCaptchas.length) throw new _prosopo_common.ProsopoEnvError("CAPTCHA.INVALID_CAPTCHA_ID", { context: {
280
- failedFuncName: this.validateReceivedCaptchasAgainstStoredCaptchas.name,
281
- captchas
282
- } });
283
- if (!storedCaptchas.every((captcha) => captcha.datasetId === (0, _prosopo_util.at)(storedCaptchas, 0).datasetId)) throw new _prosopo_common.ProsopoEnvError("CAPTCHA.DIFFERENT_DATASET_IDS", { context: {
284
- failedFuncName: this.validateReceivedCaptchasAgainstStoredCaptchas.name,
285
- captchas
286
- } });
313
+ if (!storedCaptchas || receivedCaptchas.length !== storedCaptchas.length) throw new _prosopo_common.ProsopoError({
314
+ code: "INVALID_DATA",
315
+ errorSite: "PROV-66",
316
+ message: "Invalid captcha id",
317
+ context: {
318
+ failedFuncName: this.validateReceivedCaptchasAgainstStoredCaptchas.name,
319
+ captchas
320
+ }
321
+ });
322
+ if (!storedCaptchas.every((captcha) => captcha.datasetId === (0, _prosopo_util.at)(storedCaptchas, 0).datasetId)) throw new _prosopo_common.ProsopoError({
323
+ code: "INVALID_DATA",
324
+ errorSite: "PROV-67",
325
+ message: "Dataset ids do not match",
326
+ context: {
327
+ failedFuncName: this.validateReceivedCaptchasAgainstStoredCaptchas.name,
328
+ captchas
329
+ }
330
+ });
287
331
  return {
288
332
  storedCaptchas,
289
333
  receivedCaptchas,
@@ -312,10 +356,15 @@ var ImgCaptchaManager = class extends require_captchaManager.CaptchaManager {
312
356
  }
313
357
  async getDappUserCommitmentById(commitmentId) {
314
358
  const dappUserSolution = await this.db.getDappUserCommitmentById(commitmentId);
315
- if (!dappUserSolution) throw new _prosopo_common.ProsopoEnvError("CAPTCHA.DAPP_USER_SOLUTION_NOT_FOUND", { context: {
316
- failedFuncName: this.getDappUserCommitmentById.name,
317
- commitmentId
318
- } });
359
+ if (!dappUserSolution) throw new _prosopo_common.ProsopoError({
360
+ code: "SOLUTION_NOT_FOUND",
361
+ errorSite: "PROV-68",
362
+ message: "Dapp user solution not found",
363
+ context: {
364
+ failedFuncName: this.getDappUserCommitmentById.name,
365
+ commitmentId
366
+ }
367
+ });
319
368
  return dappUserSolution;
320
369
  }
321
370
  async verifyImageCaptchaSolution(user, dapp, commitmentId, env, maxVerifiedTime, ip, disallowWebView, userAccessRulesStorage, email, spamEmailDomainCheckingEnabled = false, spamFilter, trafficFilter, storeMetadata = false, clientSessionId) {
@@ -378,8 +427,9 @@ var ImgCaptchaManager = class extends require_captchaManager.CaptchaManager {
378
427
  };
379
428
  failStatus = _prosopo_types.ResultReason.CLIENT_SESSION_MISMATCH;
380
429
  }
430
+ const sessionRecord = solution.sessionId ? await this.getSessionRecordWithOriginFallback(solution.sessionId) : void 0;
381
431
  if (!failStatus && userAccessRulesStorage) try {
382
- const blockPolicy = await this.checkForHardBlock(userAccessRulesStorage, solution, solution.userAccount, solution.headers, solution.coords, solution.ipInfo?.isValid ? solution.ipInfo.countryCode : void 0, solution.ipInfo?.isValid ? solution.ipInfo.asnNumber : void 0);
432
+ const blockPolicy = await this.checkForHardBlock(userAccessRulesStorage, solution, solution.userAccount, solution.headers, sessionRecord?.decryptedHeadHash, solution.coords, solution.ipInfo?.isValid ? solution.ipInfo.countryCode : void 0, solution.ipInfo?.isValid ? solution.ipInfo.asnNumber : void 0);
383
433
  if (blockPolicy) {
384
434
  logger.info(() => ({
385
435
  msg: "User blocked by access policy in server image verification",
@@ -462,10 +512,9 @@ var ImgCaptchaManager = class extends require_captchaManager.CaptchaManager {
462
512
  }));
463
513
  }
464
514
  }
465
- const sessionRecord = solution.sessionId ? await this.getSessionRecordWithOriginFallback(solution.sessionId) : void 0;
466
515
  const enrichedDnsEvent = await require_enrichDnsEvent.enrichDnsEvent(sessionRecord?.dnsEvent, env.ipInfoService, ip ?? solution.ipInfo?.ip);
467
516
  if (!failStatus) {
468
- const check = await this.resolveTrafficFilterCheck(env, solution.ipInfo, trafficFilter, ip, enrichedDnsEvent);
517
+ const check = await this.resolveTrafficFilterCheck(solution.ipInfo, trafficFilter, ip ? await env.ipInfoService.lookup(ip) : void 0, enrichedDnsEvent);
469
518
  if (check.isBlocked) {
470
519
  logger.info(() => ({
471
520
  msg: "Traffic filter rejected request",
@@ -17,10 +17,15 @@ var nativeMerkle = (() => {
17
17
  * CaptchaMerkleTree so callers can still generate proofs.
18
18
  */
19
19
  var buildTreeAndGetCommitmentId = (captchaSolutions) => {
20
- if (captchaSolutions.length === 0) throw new _prosopo_common.ProsopoEnvError("CONTRACT.CAPTCHA_SOLUTION_COMMITMENT_DOES_NOT_EXIST", { context: {
21
- failedFuncName: buildTreeAndGetCommitmentId.name,
22
- commitmentId: null
23
- } });
20
+ if (captchaSolutions.length === 0) throw new _prosopo_common.ProsopoError({
21
+ code: "RECORD_NOT_FOUND",
22
+ errorSite: "PROV-69",
23
+ message: "Captcha solution commitment does not exist",
24
+ context: {
25
+ failedFuncName: buildTreeAndGetCommitmentId.name,
26
+ commitmentId: null
27
+ }
28
+ });
24
29
  const layers = require_metrics.measureSync("merkle_build", () => {
25
30
  const solutionsHashed = captchaSolutions.map((captcha) => nativeMerkle.computeCaptchaSolutionHash(captcha.captchaId, captcha.captchaContentId, captcha.solution, captcha.salt));
26
31
  return nativeMerkle.buildMerkleLayers(solutionsHashed);
@@ -28,10 +33,15 @@ var buildTreeAndGetCommitmentId = (captchaSolutions) => {
28
33
  const tree = new _prosopo_datasets.CaptchaMerkleTree();
29
34
  tree.hydrateFromLayers(layers);
30
35
  const commitmentId = tree.root?.hash;
31
- if (!commitmentId) throw new _prosopo_common.ProsopoEnvError("CONTRACT.CAPTCHA_SOLUTION_COMMITMENT_DOES_NOT_EXIST", { context: {
32
- failedFuncName: buildTreeAndGetCommitmentId.name,
33
- commitmentId
34
- } });
36
+ if (!commitmentId) throw new _prosopo_common.ProsopoError({
37
+ code: "RECORD_NOT_FOUND",
38
+ errorSite: "PROV-70",
39
+ message: "Captcha solution commitment does not exist",
40
+ context: {
41
+ failedFuncName: buildTreeAndGetCommitmentId.name,
42
+ commitmentId
43
+ }
44
+ });
35
45
  return {
36
46
  tree,
37
47
  commitmentId
@@ -183,18 +183,26 @@ var InteractiveCaptchaManager = class extends require_captchaManager.CaptchaMana
183
183
  return notVerifiedResponse;
184
184
  }
185
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
- } });
186
+ if (challengeRecord.result.status !== _prosopo_types.CaptchaStatus.approved) throw new _prosopo_common.ProsopoError({
187
+ code: "INVALID_SOLUTION",
188
+ errorSite: "PROV-71",
189
+ context: {
190
+ failedFuncName: this.serverVerifyInteractiveCaptchaSolution.name,
191
+ challenge
192
+ }
193
+ });
191
194
  if (challengeRecord.serverChecked) return notVerifiedResponse;
192
195
  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
- } });
196
+ if (dappAccount !== challengeDappAccount) throw new _prosopo_common.ProsopoError({
197
+ code: "SOLUTION_NOT_FOUND",
198
+ errorSite: "PROV-72",
199
+ message: "Dapp user solution not found",
200
+ context: {
201
+ failedFuncName: this.serverVerifyInteractiveCaptchaSolution.name,
202
+ dappAccount,
203
+ challengeDappAccount
204
+ }
205
+ });
198
206
  if (!await this.markRecordChecked(challengeRecord.challenge)) return notVerifiedResponse;
199
207
  const submittedAt = challengeRecord.submittedAtTimestamp;
200
208
  if ((submittedAt instanceof Date ? Date.now() - submittedAt.getTime() : Number.POSITIVE_INFINITY) > timeout) {
@@ -209,8 +217,9 @@ var InteractiveCaptchaManager = class extends require_captchaManager.CaptchaMana
209
217
  await this.disapproveVerification(challengeRecord, _prosopo_types.ResultReason.CLIENT_SESSION_MISMATCH);
210
218
  return notVerifiedResponse;
211
219
  }
220
+ const sessionRecord = challengeRecord.sessionId ? await this.getSessionRecordWithOriginFallback(challengeRecord.sessionId) : void 0;
212
221
  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);
222
+ const blockPolicy = await this.checkForHardBlock(userAccessRulesStorage, challengeRecord, challengeRecord.userAccount, challengeRecord.headers, sessionRecord?.decryptedHeadHash, challengeRecord.coords, challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0, challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.asnNumber : void 0);
214
223
  if (blockPolicy) {
215
224
  logger.info(() => ({
216
225
  msg: `User blocked by access policy in server ${this.logLabel} verification`,
@@ -268,10 +277,9 @@ var InteractiveCaptchaManager = class extends require_captchaManager.CaptchaMana
268
277
  }));
269
278
  }
270
279
  }
271
- const sessionRecord = challengeRecord.sessionId ? await this.getSessionRecordWithOriginFallback(challengeRecord.sessionId) : void 0;
272
280
  const enrichedDnsEvent = await require_enrichDnsEvent.enrichDnsEvent(sessionRecord?.dnsEvent, env.ipInfoService, ip ?? challengeRecord.ipInfo?.ip);
273
281
  {
274
- const check = await this.resolveTrafficFilterCheck(env, challengeRecord.ipInfo, trafficFilter, ip, enrichedDnsEvent);
282
+ const check = await this.resolveTrafficFilterCheck(challengeRecord.ipInfo, trafficFilter, ip ? await env.ipInfoService.lookup(ip) : void 0, enrichedDnsEvent);
275
283
  if (check.isBlocked) {
276
284
  logger.info(() => ({
277
285
  msg: `Traffic filter rejected request in ${this.logLabel} verification`,
@@ -0,0 +1,24 @@
1
+ //#region src/tasks/powCaptcha/backgroundWrites.ts
2
+ /**
3
+ * Lets writes finish after the response, but once `limit` are still pending
4
+ * the caller waits for its own, so a slow database cannot pile them up.
5
+ */
6
+ var BackgroundWrites = class {
7
+ constructor(limit) {
8
+ this.limit = limit;
9
+ this.pending = 0;
10
+ }
11
+ async add(writes, onError) {
12
+ const settled = writes.then(() => void 0, onError);
13
+ if (this.pending >= this.limit) {
14
+ await settled;
15
+ return;
16
+ }
17
+ this.pending++;
18
+ settled.finally(() => {
19
+ this.pending--;
20
+ });
21
+ }
22
+ };
23
+ //#endregion
24
+ exports.BackgroundWrites = BackgroundWrites;
@@ -11,6 +11,7 @@ const require_frictionlessTasksUtils = require("../frictionless/frictionlessTask
11
11
  const require_powTasksUtils = require("./powTasksUtils.cjs");
12
12
  const require_evaluateEmailSpamRules = require("../spam/evaluateEmailSpamRules.cjs");
13
13
  const require_routingMachine = require("../frictionless/routingMachine.cjs");
14
+ const require_backgroundWrites = require("./backgroundWrites.cjs");
14
15
  let _prosopo_common = require("@prosopo/common");
15
16
  let _prosopo_types = require("@prosopo/types");
16
17
  let _polkadot_util = require("@polkadot/util");
@@ -18,6 +19,7 @@ let _prosopo_user_access_policy = require("@prosopo/user-access-policy");
18
19
  let _prosopo_util = require("@prosopo/util");
19
20
  //#region src/tasks/powCaptcha/powTasks.ts
20
21
  var DEFAULT_POW_DIFFICULTY = 4;
22
+ var verifyOutcomeWrites = new require_backgroundWrites.BackgroundWrites(500);
21
23
  var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
22
24
  constructor(db, pair, config, logger, writeQueue, usageCounters) {
23
25
  super(db, pair, config, logger, writeQueue);
@@ -65,7 +67,7 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
65
67
  * @param behavioralData
66
68
  * @param salt
67
69
  */
68
- async verifyPowCaptchaSolution(challenge, providerChallengeSignature, nonce, timeout, userTimestampSignature, ipAddress, headers, behavioralData, salt, simdReadings, clientMetaData) {
70
+ async verifyPowCaptchaSolution(challenge, providerChallengeSignature, nonce, timeout, userTimestampSignature, ipAddress, headers, behavioralData, salt, simdReadings, clientMetaData, fingerprintSummary) {
69
71
  require_powTasksUtils.checkPowSignature(challenge, providerChallengeSignature, this.pair.address, _prosopo_types.ApiParams.challenge);
70
72
  const challengeSplit = challenge.split(this.POW_SEPARATOR);
71
73
  const timestamp = Number.parseInt((0, _prosopo_util.at)(challengeSplit, 0));
@@ -134,7 +136,7 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
134
136
  };
135
137
  if (correct && this.usageCounters) {
136
138
  const dappAccount = (0, _prosopo_util.at)(challengeSplit, 2);
137
- this.usageCounters.incrManyAsync(dappAccount, require_usageCounters.buildAllWindowIncrements("solved", _prosopo_types.CaptchaType.pow, ipAddress.address, userAccount));
139
+ this.usageCounters.incrManyAsync(dappAccount, require_usageCounters.buildAllWindowIncrements("solved", _prosopo_types.CaptchaType.pow, ipAddress.address, userAccount, void 0, fingerprintSummary?.bucketId));
138
140
  }
139
141
  let behavioralUpdates = {};
140
142
  let decryptedBehavioralDataPacked;
@@ -180,6 +182,7 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
180
182
  }));
181
183
  }
182
184
  const recordUpdates = { ...behavioralUpdates };
185
+ if (fingerprintSummary) recordUpdates.fingerprintSummary = fingerprintSummary;
183
186
  const storedClientMetaData = require_clientMetaData.toStoredClientMetaData(clientMetaData);
184
187
  if (storedClientMetaData) recordUpdates.clientMetaData = storedClientMetaData;
185
188
  if (Object.keys(recordUpdates).length > 0) await this.db.updatePowCaptchaRecord(challenge, recordUpdates);
@@ -294,8 +297,10 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
294
297
  * @param clientSessionId - the session id the site rendered the widget
295
298
  * with. When supplied, the solve must carry the same value in its
296
299
  * `clientMetaData` or it is disapproved.
300
+ * @param ipValidationRules - the site's rules for comparing `ip` with the
301
+ * ip the challenge was issued to.
297
302
  */
298
- async serverVerifyPowCaptchaSolution(dappAccount, challenge, timeout, env, ip, userAccessRulesStorage, email, spamEmailDomainCheckingEnabled = false, spamFilter, trafficFilter, storeMetadata = false, clientSessionId) {
303
+ async serverVerifyPowCaptchaSolution(dappAccount, challenge, timeout, env, ip, userAccessRulesStorage, email, spamEmailDomainCheckingEnabled = false, spamFilter, trafficFilter, storeMetadata = false, clientSessionId, ipValidationRules) {
299
304
  const notVerified = (reason, sessionId) => ({
300
305
  verified: false,
301
306
  reason,
@@ -310,18 +315,26 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
310
315
  logger.debug(() => ({ msg: `No record of this challenge: ${challenge}` }));
311
316
  return notVerified("CAPTCHA.DAPP_USER_SOLUTION_NOT_FOUND");
312
317
  }
313
- if (challengeRecord.result.status !== _prosopo_types.CaptchaStatus.approved) throw new _prosopo_common.ProsopoApiError("CAPTCHA.INVALID_SOLUTION", { context: {
314
- code: 400,
315
- failedFuncName: this.serverVerifyPowCaptchaSolution.name,
316
- challenge
317
- } });
318
+ if (challengeRecord.result.status !== _prosopo_types.CaptchaStatus.approved) throw new _prosopo_common.ProsopoError({
319
+ code: "INVALID_SOLUTION",
320
+ errorSite: "PROV-73",
321
+ context: {
322
+ failedFuncName: this.serverVerifyPowCaptchaSolution.name,
323
+ challenge
324
+ }
325
+ });
318
326
  if (challengeRecord.serverChecked) return notVerified("API.USER_ALREADY_VERIFIED", challengeRecord.sessionId);
319
327
  const challengeDappAccount = challengeRecord.dappAccount;
320
- if (dappAccount !== challengeDappAccount) throw new _prosopo_common.ProsopoEnvError("CAPTCHA.DAPP_USER_SOLUTION_NOT_FOUND", { context: {
321
- failedFuncName: this.serverVerifyPowCaptchaSolution.name,
322
- dappAccount,
323
- challengeDappAccount
324
- } });
328
+ if (dappAccount !== challengeDappAccount) throw new _prosopo_common.ProsopoError({
329
+ code: "SOLUTION_NOT_FOUND",
330
+ errorSite: "PROV-74",
331
+ message: "Dapp user solution not found",
332
+ context: {
333
+ failedFuncName: this.serverVerifyPowCaptchaSolution.name,
334
+ dappAccount,
335
+ challengeDappAccount
336
+ }
337
+ });
325
338
  if (await this.db.markDappUserPoWCommitmentsChecked([challengeRecord.challenge]) === 0) return notVerified("API.USER_ALREADY_VERIFIED", challengeRecord.sessionId);
326
339
  const powRecordUpdates = {};
327
340
  let failResult;
@@ -346,8 +359,16 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
346
359
  };
347
360
  failReason = "API.CLIENT_SESSION_MISMATCH";
348
361
  }
362
+ const sessionRecordRead = challengeRecord.sessionId ? this.getSessionRecordWithOriginFallback(challengeRecord.sessionId) : Promise.resolve(void 0);
363
+ const enrichedDnsEventRead = sessionRecordRead.then((sessionRecord) => require_enrichDnsEvent.enrichDnsEvent(sessionRecord?.dnsEvent, env.ipInfoService, ip ?? challengeRecord.ipInfo?.ip));
364
+ const currentIpInfoRead = ip && !failResult ? env.ipInfoService.lookup(ip) : Promise.resolve(void 0);
365
+ for (const read of [
366
+ sessionRecordRead,
367
+ enrichedDnsEventRead,
368
+ currentIpInfoRead
369
+ ]) read.catch(() => void 0);
349
370
  if (!failResult && userAccessRulesStorage) try {
350
- 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);
371
+ const blockPolicy = await this.checkForHardBlock(userAccessRulesStorage, challengeRecord, challengeRecord.userAccount, challengeRecord.headers, (await sessionRecordRead)?.decryptedHeadHash, challengeRecord.coords, challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.countryCode : void 0, challengeRecord.ipInfo?.isValid ? challengeRecord.ipInfo.asnNumber : void 0);
351
372
  if (blockPolicy) {
352
373
  logger.info(() => ({
353
374
  msg: "User blocked by access policy in server PoW verification",
@@ -429,10 +450,10 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
429
450
  }));
430
451
  }
431
452
  }
432
- const sessionRecord = challengeRecord.sessionId ? await this.getSessionRecordWithOriginFallback(challengeRecord.sessionId) : void 0;
433
- const enrichedDnsEvent = await require_enrichDnsEvent.enrichDnsEvent(sessionRecord?.dnsEvent, env.ipInfoService, ip ?? challengeRecord.ipInfo?.ip);
453
+ const sessionRecord = await sessionRecordRead;
454
+ const enrichedDnsEvent = await enrichedDnsEventRead;
434
455
  if (!failResult) {
435
- const check = await this.resolveTrafficFilterCheck(env, challengeRecord.ipInfo, trafficFilter, ip, enrichedDnsEvent);
456
+ const check = await this.resolveTrafficFilterCheck(challengeRecord.ipInfo, trafficFilter, await currentIpInfoRead, enrichedDnsEvent);
436
457
  if (check.isBlocked) {
437
458
  logger.info(() => ({
438
459
  msg: "Traffic filter rejected request in PoW verification",
@@ -459,7 +480,6 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
459
480
  };
460
481
  if (!failResult && ip) {
461
482
  const challengeIpAddress = require_compositeIpAddress.getIpAddressFromComposite(challengeRecord.ipAddress);
462
- const ipValidationRules = (await this.db.getClientRecord(dappAccount))?.settings?.ipValidationRules;
463
483
  powRecordUpdates.providedIp = require_compositeIpAddress.getCompositeIpAddress(ip);
464
484
  if (ipValidationRules?.enabled === true) {
465
485
  const ipValidation = await require_util.deepValidateIpAddress(ip, challengeIpAddress, logger, env.ipInfoService, ipValidationRules, enrichedDnsEvent?.peerIp);
@@ -569,7 +589,12 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
569
589
  ...(0, _prosopo_types.isBlockingCaptchaResult)(_prosopo_types.CaptchaType.pow, finalResult) && { blocked: true },
570
590
  ...matchedRule && { matchedRule }
571
591
  }, true));
572
- if (writePromises.length > 0) await Promise.all(writePromises);
592
+ await verifyOutcomeWrites.add(Promise.all(writePromises), (err) => {
593
+ logger.error(() => ({
594
+ msg: "Failed to record the outcome of a PoW verification",
595
+ err
596
+ }));
597
+ });
573
598
  if (failReason) return notVerified(failReason, challengeRecord.sessionId);
574
599
  return {
575
600
  verified: true,
@@ -1,19 +1,23 @@
1
+ const require_signatureCheck = require("../signatureCheck.cjs");
1
2
  let _prosopo_common = require("@prosopo/common");
2
- let _polkadot_util = require("@polkadot/util");
3
3
  let _prosopo_util = require("@prosopo/util");
4
- let _prosopo_util_crypto = require("@prosopo/util-crypto");
5
4
  let _noble_hashes_sha2_js = require("@noble/hashes/sha2.js");
6
5
  //#region src/tasks/powCaptcha/powTasksUtils.ts
7
6
  var validateSolution = (nonce, challenge, difficulty) => (0, _prosopo_util.hashMeetsDifficulty)((0, _noble_hashes_sha2_js.sha256)(new TextEncoder().encode(nonce + challenge)), difficulty);
8
7
  var checkPowSignature = (message, signature, address, signatureType) => {
9
- if (!(0, _prosopo_util_crypto.signatureVerify)((0, _polkadot_util.stringToHex)(message), signature, address).isValid) throw new _prosopo_common.ProsopoApiError("GENERAL.INVALID_SIGNATURE", { context: {
10
- ERROR: `Signature is invalid for this message: ${signatureType}`,
11
- failedFuncName: checkPowSignature.name,
12
- address,
13
- message,
14
- signature,
15
- signatureType
16
- } });
8
+ if (!require_signatureCheck.isSignatureValid(message, signature, address)) throw new _prosopo_common.ProsopoError({
9
+ code: "UNAUTHORIZED",
10
+ errorSite: "PROV-75",
11
+ message: "Invalid signature",
12
+ context: {
13
+ ERROR: `Signature is invalid for this message: ${signatureType}`,
14
+ failedFuncName: checkPowSignature.name,
15
+ address,
16
+ message,
17
+ signature,
18
+ signatureType
19
+ }
20
+ });
17
21
  };
18
22
  var isCoordsAllZero = (coords) => coords !== void 0 && coords.length > 0 && coords.every((group) => group.length > 0 && group.every(([x, y]) => x === 0 && y === 0));
19
23
  //#endregion
@@ -46,13 +46,9 @@ var resolvePuzzleRenderSettings = (...overrides) => {
46
46
  var pieceSizeSampler = require_stratifiedSampler.createStratifiedSampler();
47
47
  /**
48
48
  * Resolve the effective piece scale range from the same layered
49
- * client-settings / traffic-filter overrides used for render settings, and
50
- * draw a per-challenge piece size in pixels. Stratified so the distribution
51
- * is evenly spread across the range even for short bursts of requests.
52
- * Rounded to an integer because the pixel buffer is allocated as
53
- * `size * size * 4`.
49
+ * client-settings / traffic-filter overrides used for render settings.
54
50
  */
55
- var resolvePuzzlePieceSize = (...overrides) => {
51
+ var resolvePuzzlePieceScaleRange = (...overrides) => {
56
52
  let min = _prosopo_types.puzzlePieceScaleMinDefault;
57
53
  let max = _prosopo_types.puzzlePieceScaleMaxDefault;
58
54
  for (const override of overrides) {
@@ -61,7 +57,19 @@ var resolvePuzzlePieceSize = (...overrides) => {
61
57
  if (override.pieceScale.max !== void 0) max = override.pieceScale.max;
62
58
  }
63
59
  if (min > max) min = max;
64
- const scale = pieceSizeSampler.sample(min, max);
60
+ return {
61
+ min,
62
+ max
63
+ };
64
+ };
65
+ /**
66
+ * Draw a per-challenge piece size in pixels from a scale range. Stratified so
67
+ * the distribution is evenly spread across the range even for short bursts of
68
+ * requests. Rounded to an integer because the pixel buffer is allocated as
69
+ * `size * size * 4`.
70
+ */
71
+ var samplePuzzlePieceSize = (range) => {
72
+ const scale = pieceSizeSampler.sample(range.min, range.max);
65
73
  return Math.max(1, Math.round(_prosopo_puzzle_assets.DEFAULT_GEOMETRY.width * scale));
66
74
  };
67
75
  /**
@@ -94,5 +102,6 @@ var renderPuzzleImages = async (placement, settings = _prosopo_puzzle_assets.DEF
94
102
  //#endregion
95
103
  exports.isPuzzleRenderAvailable = isPuzzleRenderAvailable;
96
104
  exports.renderPuzzleImages = renderPuzzleImages;
97
- exports.resolvePuzzlePieceSize = resolvePuzzlePieceSize;
105
+ exports.resolvePuzzlePieceScaleRange = resolvePuzzlePieceScaleRange;
98
106
  exports.resolvePuzzleRenderSettings = resolvePuzzleRenderSettings;
107
+ exports.samplePuzzlePieceSize = samplePuzzlePieceSize;
@@ -0,0 +1,12 @@
1
+ let _polkadot_util = require("@polkadot/util");
2
+ let _prosopo_util_crypto = require("@prosopo/util-crypto");
3
+ //#region src/tasks/signatureCheck.ts
4
+ var isSignatureValid = (message, signature, address) => {
5
+ try {
6
+ return (0, _prosopo_util_crypto.signatureVerify)((0, _polkadot_util.stringToHex)(message), signature, address).isValid;
7
+ } catch {
8
+ return false;
9
+ }
10
+ };
11
+ //#endregion
12
+ exports.isSignatureValid = isSignatureValid;
@@ -23,7 +23,12 @@ var Tasks = class {
23
23
  this.db = env.getDb();
24
24
  this.captchaConfig = env.config.captchas;
25
25
  this.logger = logger || (0, _prosopo_logger.getLogger)((0, _prosopo_logger.parseLogLevel)(env.config.logLevel), "Tasks");
26
- if (!env.pair) throw new _prosopo_common.ProsopoEnvError("DEVELOPER.MISSING_PROVIDER_PAIR", { context: { failedFuncName: "Tasks.constructor" } });
26
+ if (!env.pair) throw new _prosopo_common.ProsopoError({
27
+ code: "CONFIG_INVALID",
28
+ errorSite: "PROV-76",
29
+ message: "Missing provider pair",
30
+ context: { failedFuncName: "Tasks.constructor" }
31
+ });
27
32
  this.pair = env.pair;
28
33
  if (this.config.mongoCaptchaUri && this.db instanceof _prosopo_database.ProviderDatabase && !this.db.hasCentralDbStreamer()) {
29
34
  const streamer = new _prosopo_database.CentralDbStreamer(this.config.mongoCaptchaUri, this.logger);
@@ -152,10 +152,15 @@ var UsageCounters = class {
152
152
  }
153
153
  };
154
154
  /**
155
- * Helper: produce the standard 24-counter served/solved write set for a given
156
- * captcha challenge. Used by both served (post-session) and solved hooks.
155
+ * Helper: produce the standard served/solved write set for a given captcha
156
+ * challenge. Used by both served (post-session) and solved hooks.
157
+ *
158
+ * `deviceBucket` is only written when the caller knows one, which for now is
159
+ * the PoW solve path with a verified proof of fingerprint. Omitting it leaves
160
+ * the key absent rather than at zero, so a bucket's count is over the requests
161
+ * that actually proved it.
157
162
  */
158
- var buildAllWindowIncrements = (kind, captchaType, ip, userAccount, peerIp) => {
163
+ var buildAllWindowIncrements = (kind, captchaType, ip, userAccount, peerIp, deviceBucket) => {
159
164
  const out = [];
160
165
  for (const window of [
161
166
  "1m",
@@ -191,6 +196,15 @@ var buildAllWindowIncrements = (kind, captchaType, ip, userAccount, peerIp) => {
191
196
  },
192
197
  value: peerIp
193
198
  });
199
+ if (deviceBucket) out.push({
200
+ spec: {
201
+ kind,
202
+ captchaType,
203
+ dimension: "deviceBucket",
204
+ window
205
+ },
206
+ value: deviceBucket
207
+ });
194
208
  if (captchaType !== "any") {
195
209
  out.push({
196
210
  spec: {
@@ -218,6 +232,15 @@ var buildAllWindowIncrements = (kind, captchaType, ip, userAccount, peerIp) => {
218
232
  },
219
233
  value: peerIp
220
234
  });
235
+ if (deviceBucket) out.push({
236
+ spec: {
237
+ kind,
238
+ captchaType: "any",
239
+ dimension: "deviceBucket",
240
+ window
241
+ },
242
+ value: deviceBucket
243
+ });
221
244
  }
222
245
  }
223
246
  return out;