@prosopo/provider 5.19.4 → 5.20.1

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 (261) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +40 -36
  2. package/.turbo/turbo-build$colon$tsc.log +28 -28
  3. package/.turbo/turbo-build.log +43 -36
  4. package/CHANGELOG.md +155 -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 +20 -25
  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/interactiveCaptchaChallenge.d.ts.map +1 -1
  37. package/dist/api/captcha/interactiveCaptchaChallenge.js +27 -32
  38. package/dist/api/captcha/interactiveCaptchaChallenge.js.map +1 -1
  39. package/dist/api/captcha/interactiveCaptchaSolution.d.ts.map +1 -1
  40. package/dist/api/captcha/interactiveCaptchaSolution.js +18 -24
  41. package/dist/api/captcha/interactiveCaptchaSolution.js.map +1 -1
  42. package/dist/api/captcha/submitImageCaptchaSolution.d.ts.map +1 -1
  43. package/dist/api/captcha/submitImageCaptchaSolution.js +18 -24
  44. package/dist/api/captcha/submitImageCaptchaSolution.js.map +1 -1
  45. package/dist/api/captcha/submitPoWCaptchaSolution.d.ts.map +1 -1
  46. package/dist/api/captcha/submitPoWCaptchaSolution.js +23 -25
  47. package/dist/api/captcha/submitPoWCaptchaSolution.js.map +1 -1
  48. package/dist/api/domainMiddleware.d.ts.map +1 -1
  49. package/dist/api/domainMiddleware.js +39 -47
  50. package/dist/api/domainMiddleware.js.map +1 -1
  51. package/dist/api/errorCodeForReason.d.ts +3 -0
  52. package/dist/api/errorCodeForReason.d.ts.map +1 -0
  53. package/dist/api/errorCodeForReason.js +22 -0
  54. package/dist/api/errorCodeForReason.js.map +1 -0
  55. package/dist/api/headerCheckMiddleware.d.ts.map +1 -1
  56. package/dist/api/headerCheckMiddleware.js +14 -9
  57. package/dist/api/headerCheckMiddleware.js.map +1 -1
  58. package/dist/api/ipInfoMiddleware.d.ts +1 -1
  59. package/dist/api/ipInfoMiddleware.d.ts.map +1 -1
  60. package/dist/api/ipInfoMiddleware.js +5 -1
  61. package/dist/api/ipInfoMiddleware.js.map +1 -1
  62. package/dist/api/metrics.d.ts.map +1 -1
  63. package/dist/api/metrics.js +9 -1
  64. package/dist/api/metrics.js.map +1 -1
  65. package/dist/api/public.d.ts.map +1 -1
  66. package/dist/api/public.js +6 -2
  67. package/dist/api/public.js.map +1 -1
  68. package/dist/api/rateLimitHandler.d.ts +4 -0
  69. package/dist/api/rateLimitHandler.d.ts.map +1 -0
  70. package/dist/api/rateLimitHandler.js +20 -0
  71. package/dist/api/rateLimitHandler.js.map +1 -0
  72. package/dist/api/startProviderApi.d.ts +1 -0
  73. package/dist/api/startProviderApi.d.ts.map +1 -1
  74. package/dist/api/startProviderApi.js +8 -17
  75. package/dist/api/startProviderApi.js.map +1 -1
  76. package/dist/api/validateAddress.d.ts +3 -4
  77. package/dist/api/validateAddress.d.ts.map +1 -1
  78. package/dist/api/validateAddress.js +13 -19
  79. package/dist/api/validateAddress.js.map +1 -1
  80. package/dist/api/verify.d.ts.map +1 -1
  81. package/dist/api/verify.js +73 -96
  82. package/dist/api/verify.js.map +1 -1
  83. package/dist/cjs/api/blacklistRequestInspector.cjs +9 -8
  84. package/dist/cjs/api/captcha/checkSpamEmail.cjs +18 -25
  85. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.cjs +11 -2
  86. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.cjs +6 -1
  87. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +19 -24
  88. package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +31 -42
  89. package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +26 -31
  90. package/dist/cjs/api/captcha/interactiveCaptchaChallenge.cjs +26 -31
  91. package/dist/cjs/api/captcha/interactiveCaptchaSolution.cjs +17 -23
  92. package/dist/cjs/api/captcha/submitImageCaptchaSolution.cjs +17 -23
  93. package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +22 -24
  94. package/dist/cjs/api/domainMiddleware.cjs +38 -46
  95. package/dist/cjs/api/errorCodeForReason.cjs +22 -0
  96. package/dist/cjs/api/headerCheckMiddleware.cjs +13 -8
  97. package/dist/cjs/api/ipInfoMiddleware.cjs +5 -1
  98. package/dist/cjs/api/metrics.cjs +9 -1
  99. package/dist/cjs/api/public.cjs +5 -1
  100. package/dist/cjs/api/rateLimitHandler.cjs +20 -0
  101. package/dist/cjs/api/startProviderApi.cjs +8 -16
  102. package/dist/cjs/api/validateAddress.cjs +12 -18
  103. package/dist/cjs/api/verify.cjs +72 -95
  104. package/dist/cjs/index.cjs +1 -0
  105. package/dist/cjs/tasks/captchaManager.cjs +6 -8
  106. package/dist/cjs/tasks/client/clientTasks.cjs +26 -13
  107. package/dist/cjs/tasks/dataset/datasetTasksUtils.cjs +28 -8
  108. package/dist/cjs/tasks/decisionMachine/decisionMachineRunner.cjs +21 -19
  109. package/dist/cjs/tasks/frictionless/routingMachine.cjs +13 -4
  110. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +89 -40
  111. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasksUtils.cjs +18 -8
  112. package/dist/cjs/tasks/interactiveCaptcha/interactiveCaptchaManager.cjs +21 -13
  113. package/dist/cjs/tasks/powCaptcha/backgroundWrites.cjs +24 -0
  114. package/dist/cjs/tasks/powCaptcha/powTasks.cjs +44 -19
  115. package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +14 -10
  116. package/dist/cjs/tasks/signatureCheck.cjs +12 -0
  117. package/dist/cjs/tasks/tasks.cjs +6 -1
  118. package/dist/cjs/util/usageCounters.cjs +26 -3
  119. package/dist/cjs/util.cjs +14 -3
  120. package/dist/errorSites.d.ts +98 -0
  121. package/dist/errorSites.d.ts.map +1 -0
  122. package/dist/errorSites.js +2 -0
  123. package/dist/errorSites.js.map +1 -0
  124. package/dist/fingerprint/dist/merkle.js +69 -0
  125. package/dist/fingerprint/dist/proof.js +95 -0
  126. package/dist/fingerprint/dist/summary.js +73 -0
  127. package/dist/index.js +2 -2
  128. package/dist/tasks/captchaManager.d.ts +2 -3
  129. package/dist/tasks/captchaManager.d.ts.map +1 -1
  130. package/dist/tasks/captchaManager.js +6 -7
  131. package/dist/tasks/captchaManager.js.map +1 -1
  132. package/dist/tasks/client/clientTasks.d.ts.map +1 -1
  133. package/dist/tasks/client/clientTasks.js +27 -14
  134. package/dist/tasks/client/clientTasks.js.map +1 -1
  135. package/dist/tasks/dataset/datasetTasksUtils.d.ts.map +1 -1
  136. package/dist/tasks/dataset/datasetTasksUtils.js +29 -9
  137. package/dist/tasks/dataset/datasetTasksUtils.js.map +1 -1
  138. package/dist/tasks/decisionMachine/decisionMachineRunner.d.ts +1 -3
  139. package/dist/tasks/decisionMachine/decisionMachineRunner.d.ts.map +1 -1
  140. package/dist/tasks/decisionMachine/decisionMachineRunner.js +21 -19
  141. package/dist/tasks/decisionMachine/decisionMachineRunner.js.map +1 -1
  142. package/dist/tasks/frictionless/routingMachine.d.ts.map +1 -1
  143. package/dist/tasks/frictionless/routingMachine.js +13 -4
  144. package/dist/tasks/frictionless/routingMachine.js.map +1 -1
  145. package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +1 -1
  146. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +91 -42
  147. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +1 -1
  148. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js +19 -9
  149. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js.map +1 -1
  150. package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.d.ts.map +1 -1
  151. package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.js +22 -14
  152. package/dist/tasks/interactiveCaptcha/interactiveCaptchaManager.js.map +1 -1
  153. package/dist/tasks/powCaptcha/backgroundWrites.d.ts +7 -0
  154. package/dist/tasks/powCaptcha/backgroundWrites.d.ts.map +1 -0
  155. package/dist/tasks/powCaptcha/backgroundWrites.js +24 -0
  156. package/dist/tasks/powCaptcha/backgroundWrites.js.map +1 -0
  157. package/dist/tasks/powCaptcha/powTasks.d.ts +3 -3
  158. package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
  159. package/dist/tasks/powCaptcha/powTasks.js +45 -20
  160. package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
  161. package/dist/tasks/powCaptcha/powTasksUtils.d.ts.map +1 -1
  162. package/dist/tasks/powCaptcha/powTasksUtils.js +15 -11
  163. package/dist/tasks/powCaptcha/powTasksUtils.js.map +1 -1
  164. package/dist/tasks/signatureCheck.d.ts +2 -0
  165. package/dist/tasks/signatureCheck.d.ts.map +1 -0
  166. package/dist/tasks/signatureCheck.js +12 -0
  167. package/dist/tasks/signatureCheck.js.map +1 -0
  168. package/dist/tasks/tasks.d.ts.map +1 -1
  169. package/dist/tasks/tasks.js +7 -2
  170. package/dist/tasks/tasks.js.map +1 -1
  171. package/dist/tests/integration/api/admin/apiRegisterSiteKeyEndpoint.integration.test.js +3 -1
  172. package/dist/tests/integration/api/admin/apiRegisterSiteKeyEndpoint.integration.test.js.map +1 -1
  173. package/dist/tests/integration/api/admin/apiRegisterSiteKeysEndpoint.integration.test.js +6 -2
  174. package/dist/tests/integration/api/admin/apiRegisterSiteKeysEndpoint.integration.test.js.map +1 -1
  175. package/dist/tests/integration/escalationPeekBeforeConsume.integration.test.js +1 -1
  176. package/dist/tests/integration/escalationPeekBeforeConsume.integration.test.js.map +1 -1
  177. package/dist/tests/integration/imgCaptcha.integration.test.js +6 -5
  178. package/dist/tests/integration/imgCaptcha.integration.test.js.map +1 -1
  179. package/dist/tests/integration/ipValidation.integration.test.js +1 -1
  180. package/dist/tests/integration/ipValidation.integration.test.js.map +1 -1
  181. package/dist/tests/integration/powCaptcha.integration.test.js +2 -2
  182. package/dist/tests/integration/powCaptcha.integration.test.js.map +1 -1
  183. package/dist/tests/integration/routingDecisionMachines.integration.test.js.map +1 -1
  184. package/dist/tests/integration/testUtils.d.ts +2 -2
  185. package/dist/tests/integration/testUtils.d.ts.map +1 -1
  186. package/dist/tests/integration/testUtils.js +1 -1
  187. package/dist/tests/integration/testUtils.js.map +1 -1
  188. package/dist/tests/integration/webBotAuthAuthenticated.integration.test.js +3 -1
  189. package/dist/tests/integration/webBotAuthAuthenticated.integration.test.js.map +1 -1
  190. package/dist/tests/unit/api/blacklistRequestInspector.unit.test.js +26 -10
  191. package/dist/tests/unit/api/blacklistRequestInspector.unit.test.js.map +1 -1
  192. package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.js +4 -4
  193. package/dist/tests/unit/api/captcha/checkSpamEmail.unit.test.js.map +1 -1
  194. package/dist/tests/unit/api/captcha/submitSolutionBadSignature.unit.test.d.ts +2 -0
  195. package/dist/tests/unit/api/captcha/submitSolutionBadSignature.unit.test.d.ts.map +1 -0
  196. package/dist/tests/unit/api/captcha/submitSolutionBadSignature.unit.test.js +153 -0
  197. package/dist/tests/unit/api/captcha/submitSolutionBadSignature.unit.test.js.map +1 -0
  198. package/dist/tests/unit/api/domainMiddlewareErrorBody.unit.test.js +6 -2
  199. package/dist/tests/unit/api/domainMiddlewareErrorBody.unit.test.js.map +1 -1
  200. package/dist/tests/unit/api/errorCodeForReason.unit.test.d.ts +2 -0
  201. package/dist/tests/unit/api/errorCodeForReason.unit.test.d.ts.map +1 -0
  202. package/dist/tests/unit/api/errorCodeForReason.unit.test.js +23 -0
  203. package/dist/tests/unit/api/errorCodeForReason.unit.test.js.map +1 -0
  204. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +6 -1
  205. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
  206. package/dist/tests/unit/api/headerCheckMiddleware.unit.test.js +16 -7
  207. package/dist/tests/unit/api/headerCheckMiddleware.unit.test.js.map +1 -1
  208. package/dist/tests/unit/api/ipInfoMiddleware.unit.test.d.ts +2 -0
  209. package/dist/tests/unit/api/ipInfoMiddleware.unit.test.d.ts.map +1 -0
  210. package/dist/tests/unit/api/ipInfoMiddleware.unit.test.js +46 -0
  211. package/dist/tests/unit/api/ipInfoMiddleware.unit.test.js.map +1 -0
  212. package/dist/tests/unit/api/public.unit.test.js +45 -10
  213. package/dist/tests/unit/api/public.unit.test.js.map +1 -1
  214. package/dist/tests/unit/api/rateLimitHandler.unit.test.d.ts +2 -0
  215. package/dist/tests/unit/api/rateLimitHandler.unit.test.d.ts.map +1 -0
  216. package/dist/tests/unit/api/rateLimitHandler.unit.test.js +39 -0
  217. package/dist/tests/unit/api/rateLimitHandler.unit.test.js.map +1 -0
  218. package/dist/tests/unit/api/validateAddress.unit.test.js +41 -115
  219. package/dist/tests/unit/api/validateAddress.unit.test.js.map +1 -1
  220. package/dist/tests/unit/api/verifyMalformedToken.unit.test.js +3 -3
  221. package/dist/tests/unit/api/verifyMalformedToken.unit.test.js.map +1 -1
  222. package/dist/tests/unit/tasks/captchaManager.unit.test.js +22 -18
  223. package/dist/tests/unit/tasks/captchaManager.unit.test.js.map +1 -1
  224. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js +25 -0
  225. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +1 -1
  226. package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.js +25 -20
  227. package/dist/tests/unit/tasks/dataset/datasetTasksUtils.unit.test.js.map +1 -1
  228. package/dist/tests/unit/tasks/decisionMachine/decisionMachineRunner.unit.test.js +31 -0
  229. package/dist/tests/unit/tasks/decisionMachine/decisionMachineRunner.unit.test.js.map +1 -1
  230. package/dist/tests/unit/tasks/frictionless/fingerprintBucketFlow.unit.test.d.ts +2 -0
  231. package/dist/tests/unit/tasks/frictionless/fingerprintBucketFlow.unit.test.d.ts.map +1 -0
  232. package/dist/tests/unit/tasks/frictionless/fingerprintBucketFlow.unit.test.js +80 -0
  233. package/dist/tests/unit/tasks/frictionless/fingerprintBucketFlow.unit.test.js.map +1 -0
  234. package/dist/tests/unit/tasks/frictionless/routingMachine.unit.test.js +48 -0
  235. package/dist/tests/unit/tasks/frictionless/routingMachine.unit.test.js.map +1 -1
  236. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js +20 -28
  237. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasks.unit.test.js.map +1 -1
  238. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js +2 -2
  239. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js.map +1 -1
  240. package/dist/tests/unit/tasks/powCaptcha/backgroundWrites.unit.test.d.ts +2 -0
  241. package/dist/tests/unit/tasks/powCaptcha/backgroundWrites.unit.test.d.ts.map +1 -0
  242. package/dist/tests/unit/tasks/powCaptcha/backgroundWrites.unit.test.js +44 -0
  243. package/dist/tests/unit/tasks/powCaptcha/backgroundWrites.unit.test.js.map +1 -0
  244. package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js +78 -43
  245. package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js.map +1 -1
  246. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js +7 -6
  247. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js.map +1 -1
  248. package/dist/tests/unit/tasks/puzzleCaptcha/puzzleTasks.unit.test.js +2 -2
  249. package/dist/tests/unit/tasks/puzzleCaptcha/puzzleTasks.unit.test.js.map +1 -1
  250. package/dist/tests/unit/util/usageCounters.unit.test.js +20 -0
  251. package/dist/tests/unit/util/usageCounters.unit.test.js.map +1 -1
  252. package/dist/tests/unit/util.unit.test.js +7 -7
  253. package/dist/tests/unit/util.unit.test.js.map +1 -1
  254. package/dist/util/usageCounters.d.ts +1 -1
  255. package/dist/util/usageCounters.d.ts.map +1 -1
  256. package/dist/util/usageCounters.js +26 -3
  257. package/dist/util/usageCounters.js.map +1 -1
  258. package/dist/util.d.ts.map +1 -1
  259. package/dist/util.js +15 -4
  260. package/dist/util.js.map +1 -1
  261. package/package.json +44 -43
@@ -45,6 +45,7 @@ exports.getIpAddressFromComposite = require_compositeIpAddress.getIpAddressFromC
45
45
  exports.getJA4 = require_ja4Middleware.getJA4;
46
46
  exports.getPrioritisedAccessRule = require_blacklistRequestInspector.getPrioritisedAccessRule;
47
47
  exports.getRequestUserScope = require_blacklistRequestInspector.getRequestUserScope;
48
+ exports.getServerVerifyPaths = require_startProviderApi.getServerVerifyPaths;
48
49
  exports.getUserFromJWT = require_startProviderApi.getUserFromJWT;
49
50
  exports.getVerdictCache = require_blacklistRequestInspector.getVerdictCache;
50
51
  exports.handshakeTimingMiddleware = require_handshakeTimingMiddleware.handshakeTimingMiddleware;
@@ -552,9 +552,7 @@ var CaptchaManager = class CaptchaManager {
552
552
  *
553
553
  * @returns The blocking policy if user should be blocked, undefined otherwise
554
554
  */
555
- async checkForHardBlock(userAccessRulesStorage, challengeRecord, userAccount, headers, coords, countryCode, asn) {
556
- let headHash;
557
- if (challengeRecord.sessionId) headHash = (await this.db.getSessionRecordBySessionId(challengeRecord.sessionId))?.decryptedHeadHash;
555
+ async checkForHardBlock(userAccessRulesStorage, challengeRecord, userAccount, headers, headHash, coords, countryCode, asn) {
558
556
  const coordsString = coords ? JSON.stringify(coords) : void 0;
559
557
  const ipAddressRecord = require_compositeIpAddress.getIpAddressFromComposite(challengeRecord.ipAddress);
560
558
  const userScope = require_blacklistRequestInspector.getRequestUserScope(headers, challengeRecord.ja4, ipAddressRecord.address, userAccount, headHash, coordsString, countryCode, asn);
@@ -581,8 +579,9 @@ var CaptchaManager = class CaptchaManager {
581
579
  * time (ipInfoMiddleware → storeXxxRecord), so by default we reuse it
582
580
  * instead of hitting the sidecar again.
583
581
  * - If the dapp's server passed up the end user's current IP via the
584
- * verify call, look that up fresh — it's the "now" IP for filtering
585
- * and may differ from the IP that originally requested the captcha.
582
+ * verify call, the caller looks that up fresh and passes the result as
583
+ * `currentIpInfo` — it's the "now" IP for filtering and may differ from
584
+ * the IP that originally requested the captcha.
586
585
  * - When the session carries a `dnsEvent`, its `peerIp` and `resolverIp`
587
586
  * are enriched and passed alongside the primary IP.
588
587
  * - The abuser category defaults to `{action:"block"}` so abusive
@@ -595,7 +594,7 @@ var CaptchaManager = class CaptchaManager {
595
594
  * updates record / session state differently); this helper just returns
596
595
  * the verdict.
597
596
  */
598
- async resolveTrafficFilterCheck(env, recordIpInfo, trafficFilter, currentIp, enrichedDnsEvent) {
597
+ async resolveTrafficFilterCheck(recordIpInfo, trafficFilter, currentIpInfo, enrichedDnsEvent) {
599
598
  const effective = {
600
599
  abuser: { action: _prosopo_types.TrafficFilterAction.Block },
601
600
  ...trafficFilter
@@ -604,8 +603,7 @@ var CaptchaManager = class CaptchaManager {
604
603
  isBlocked: false,
605
604
  matches: []
606
605
  };
607
- const ipInfo = currentIp ? await env.ipInfoService.lookup(currentIp) : recordIpInfo;
608
- return require_checkTrafficFilter.checkTrafficFilter(ipInfo, effective, require_enrichDnsEvent.extraIpInfosFromEnrichedDnsEvent(enrichedDnsEvent), enrichedDnsEvent?.pathValid);
606
+ return require_checkTrafficFilter.checkTrafficFilter(currentIpInfo ?? recordIpInfo, effective, require_enrichDnsEvent.extraIpInfosFromEnrichedDnsEvent(enrichedDnsEvent), enrichedDnsEvent?.pathValid);
609
607
  }
610
608
  /**
611
609
  * Does this client's tier entitle it to the bot score, and is there one?
@@ -126,9 +126,11 @@ var ClientTaskManager = class {
126
126
  if (newClientRecords) await this.providerDB.updateClientRecords(newClientRecords);
127
127
  await this.providerDB.updateScheduledTaskStatus(taskID, _prosopo_types.ScheduledTaskStatus.Completed, { data: { clientRecords: newClientRecords.length } });
128
128
  } catch (e) {
129
- const getClientListError = new _prosopo_common.ProsopoApiError("DATABASE.UNKNOWN", {
130
- context: { error: e },
131
- logger: this.logger
129
+ const getClientListError = new _prosopo_common.ProsopoError({
130
+ code: "DB_QUERY_FAILED",
131
+ errorSite: "PROV-51",
132
+ message: "Unknown database error",
133
+ cause: e
132
134
  });
133
135
  this.logger.error(() => ({
134
136
  err: getClientListError,
@@ -170,12 +172,14 @@ var ClientTaskManager = class {
170
172
  await this.providerDB.removeClientRecords(accounts);
171
173
  }
172
174
  async updateDecisionMachine(scope, runtime, source, dappAccount, language, name, version, captchaType, kind) {
173
- if (scope === _prosopo_types.DecisionMachineScope.Dapp && !dappAccount) throw new _prosopo_common.ProsopoApiError("API.BAD_REQUEST", {
175
+ if (scope === _prosopo_types.DecisionMachineScope.Dapp && !dappAccount) throw new _prosopo_common.ProsopoError({
176
+ code: "INVALID_REQUEST",
177
+ errorSite: "PROV-52",
178
+ message: "BadRequest",
174
179
  context: {
175
180
  scope,
176
181
  dappAccount
177
- },
178
- logger: this.logger
182
+ }
179
183
  });
180
184
  const now = /* @__PURE__ */ new Date();
181
185
  await this.providerDB.upsertDecisionMachineArtifact({
@@ -218,9 +222,11 @@ var ClientTaskManager = class {
218
222
  }
219
223
  async getDecisionMachine(id) {
220
224
  const artifact = await this.providerDB.getDecisionMachineArtifactById(id);
221
- if (!artifact) throw new _prosopo_common.ProsopoApiError("API.BAD_REQUEST", {
222
- context: { id },
223
- logger: this.logger
225
+ if (!artifact) throw new _prosopo_common.ProsopoError({
226
+ code: "INVALID_REQUEST",
227
+ errorSite: "PROV-53",
228
+ message: "BadRequest",
229
+ context: { id }
224
230
  });
225
231
  return {
226
232
  _id: artifact._id.toString(),
@@ -239,22 +245,29 @@ var ClientTaskManager = class {
239
245
  }
240
246
  async removeDecisionMachine(id) {
241
247
  const success = await this.providerDB.removeDecisionMachineArtifact(id);
242
- if (!success) throw new _prosopo_common.ProsopoApiError("API.BAD_REQUEST", {
248
+ if (!success) throw new _prosopo_common.ProsopoError({
249
+ code: "INVALID_REQUEST",
250
+ errorSite: "PROV-54",
251
+ message: "BadRequest",
243
252
  context: {
244
253
  id,
245
254
  message: "Decision machine not found"
246
- },
247
- logger: this.logger
255
+ }
248
256
  });
257
+ require_decisionMachineRunner.invalidateAllDecisionMachineArtifactCaches();
258
+ require_decisionMachineRunner.invalidateDecisionMachineScriptCache();
249
259
  return {
250
260
  success,
251
261
  deletedId: id
252
262
  };
253
263
  }
254
264
  async removeAllDecisionMachines() {
265
+ const deletedCount = await this.providerDB.removeAllDecisionMachineArtifacts();
266
+ require_decisionMachineRunner.invalidateAllDecisionMachineArtifactCaches();
267
+ require_decisionMachineRunner.invalidateDecisionMachineScriptCache();
255
268
  return {
256
269
  success: true,
257
- deletedCount: await this.providerDB.removeAllDecisionMachineArtifacts()
270
+ deletedCount
258
271
  };
259
272
  }
260
273
  /**
@@ -2,16 +2,36 @@ let _prosopo_common = require("@prosopo/common");
2
2
  let _prosopo_datasets = require("@prosopo/datasets");
3
3
  //#region src/tasks/dataset/datasetTasksUtils.ts
4
4
  var providerValidateDataset = async (datasetRaw, minSolvedCaptchas, minUnsolvedCaptchas) => {
5
- if (datasetRaw.captchas.length < minSolvedCaptchas + minUnsolvedCaptchas) throw new _prosopo_common.ProsopoEnvError("DATASET.CAPTCHAS_COUNT_LESS_THAN_CONFIGURED", { context: { failedFuncName: providerValidateDataset.name } });
5
+ if (datasetRaw.captchas.length < minSolvedCaptchas + minUnsolvedCaptchas) throw new _prosopo_common.ProsopoError({
6
+ code: "DATASET_INVALID",
7
+ errorSite: "PROV-55",
8
+ message: "Number of captchas in dataset is less than configured number of captchas",
9
+ context: { failedFuncName: providerValidateDataset.name }
10
+ });
6
11
  const solutions = datasetRaw.captchas.map((captcha) => captcha.solution ? 1 : 0).reduce((partialSum, b) => partialSum + b, 0);
7
- if (solutions < minSolvedCaptchas) throw new _prosopo_common.ProsopoEnvError("DATASET.SOLUTIONS_COUNT_LESS_THAN_CONFIGURED", { context: { failedFuncName: providerValidateDataset.name } });
8
- if (datasetRaw.captchas.length - solutions < minUnsolvedCaptchas) throw new _prosopo_common.ProsopoEnvError("DATASET.CAPTCHAS_COUNT_LESS_THAN_CONFIGURED", { context: { failedFuncName: providerValidateDataset.name } });
12
+ if (solutions < minSolvedCaptchas) throw new _prosopo_common.ProsopoError({
13
+ code: "DATASET_INVALID",
14
+ errorSite: "PROV-56",
15
+ message: "Number of solutions in dataset is less than configured number of solutions",
16
+ context: { failedFuncName: providerValidateDataset.name }
17
+ });
18
+ if (datasetRaw.captchas.length - solutions < minUnsolvedCaptchas) throw new _prosopo_common.ProsopoError({
19
+ code: "DATASET_INVALID",
20
+ errorSite: "PROV-57",
21
+ message: "Number of captchas in dataset is less than configured number of captchas",
22
+ context: { failedFuncName: providerValidateDataset.name }
23
+ });
9
24
  const dataset = await (0, _prosopo_datasets.buildDataset)(datasetRaw);
10
- if (!dataset.datasetId || !dataset.datasetContentId) throw new _prosopo_common.ProsopoEnvError("DATASET.DATASET_ID_UNDEFINED", { context: {
11
- failedFuncName: providerValidateDataset.name,
12
- datasetId: dataset.datasetId,
13
- datasetContentId: dataset.datasetContentId
14
- } });
25
+ if (!dataset.datasetId || !dataset.datasetContentId) throw new _prosopo_common.ProsopoError({
26
+ code: "DATASET_INVALID",
27
+ errorSite: "PROV-58",
28
+ message: "Dataset id undefined",
29
+ context: {
30
+ failedFuncName: providerValidateDataset.name,
31
+ datasetId: dataset.datasetId,
32
+ datasetContentId: dataset.datasetContentId
33
+ }
34
+ });
15
35
  return dataset;
16
36
  };
17
37
  //#endregion
@@ -44,18 +44,20 @@ var ARTIFACT_CACHE_TTL_MS = Number.parseInt(process.env.DECISION_MACHINE_ARTIFAC
44
44
  var DEFAULT_DECISION = { decision: _prosopo_types.DecisionMachineDecision.Allow };
45
45
  var RequiredCountersSchema = zod.z.array(_prosopo_types.CounterSpecSchema);
46
46
  /**
47
- * Bumped by {@link invalidateAllDecisionMachineArtifactCaches}. A runner
48
- * caches the value it last saw and drops its artifact cache whenever the two
49
- * diverge, which flushes every runner — including ones built after the
50
- * invalidation — without holding a reference to any of them.
51
- *
52
- * This replaces a registry of live runners, which assumed runners were built
53
- * once per process. They are built per request, so the registry grew without
54
- * bound and construction eventually began to fail. `WeakRef` did not bound
55
- * it: the set held the wrapper, which outlives its referent.
47
+ * Bumped by {@link invalidateAllDecisionMachineArtifactCaches}. Each cache
48
+ * records the generation it was filled under and is discarded once the two
49
+ * diverge, which flushes every cache without holding a reference to any of
50
+ * them.
56
51
  */
57
52
  var artifactCacheGeneration = 0;
58
53
  /**
54
+ * Runners are built per request, so a cache owned by the runner never served
55
+ * a second lookup and every decision paid two Mongo reads. The cache lives
56
+ * with the database the runner reads from instead: one per process in
57
+ * production, and still isolated between test doubles.
58
+ */
59
+ var artifactCaches = /* @__PURE__ */ new WeakMap();
60
+ /**
59
61
  * Flush every runner's in-memory artifact cache. Companion to
60
62
  * {@link invalidateDecisionMachineScriptCache}. Call both after any
61
63
  * `upsertDecisionMachineArtifact` upload.
@@ -66,19 +68,20 @@ var invalidateAllDecisionMachineArtifactCaches = () => {
66
68
  var DecisionMachineRunner = class DecisionMachineRunner {
67
69
  constructor(db) {
68
70
  this.db = db;
69
- this.artifactCache = /* @__PURE__ */ new Map();
70
- this.seenArtifactCacheGeneration = artifactCacheGeneration;
71
71
  }
72
- /** Drop every entry in this runner's artifact cache. */
72
+ /** Drop every cached artifact read from this runner's database. */
73
73
  invalidateArtifactCache() {
74
74
  this.artifactCache.clear();
75
75
  }
76
- /** Drop the cache if an invalidation happened since it was last consulted. */
77
- dropArtifactCacheIfStale() {
78
- if (this.seenArtifactCacheGeneration !== artifactCacheGeneration) {
79
- this.seenArtifactCacheGeneration = artifactCacheGeneration;
80
- this.artifactCache.clear();
81
- }
76
+ get artifactCache() {
77
+ const cache = artifactCaches.get(this.db);
78
+ if (cache && cache.generation === artifactCacheGeneration) return cache.entries;
79
+ const fresh = {
80
+ generation: artifactCacheGeneration,
81
+ entries: /* @__PURE__ */ new Map()
82
+ };
83
+ artifactCaches.set(this.db, fresh);
84
+ return fresh.entries;
82
85
  }
83
86
  /** Build a cache key for a given scope + kind + dappAccount tuple. */
84
87
  static cacheKey(scope, kind, dappAccount) {
@@ -86,7 +89,6 @@ var DecisionMachineRunner = class DecisionMachineRunner {
86
89
  }
87
90
  /** Return a cached artifact if still fresh, or undefined. */
88
91
  getCachedArtifact(scope, kind, dappAccount) {
89
- this.dropArtifactCacheIfStale();
90
92
  const entry = this.artifactCache.get(DecisionMachineRunner.cacheKey(scope, kind, dappAccount));
91
93
  if (!entry) return null;
92
94
  if (Date.now() - entry.cachedAt > ARTIFACT_CACHE_TTL_MS) {
@@ -56,14 +56,15 @@ var applyRouter = async (runner, counters, baseline, ctx, logger, phase = "route
56
56
  };
57
57
  /**
58
58
  * Map machine-declared CounterSpecs onto the values that the provider knows
59
- * how to read (IP and userAccount). Specs whose dimension we cannot resolve
60
- * are silently skipped.
59
+ * how to read. Specs whose dimension we cannot resolve are silently skipped,
60
+ * so a rule naming `deviceBucket` on a request that disclosed no proof of
61
+ * fingerprint simply does not get that key.
61
62
  */
62
63
  var specsToReads = (specs, ctx) => {
63
64
  const out = [];
64
65
  for (const spec of specs) {
65
- const value = spec.dimension === "ip" ? ctx.ip : spec.dimension === "userAccount" ? ctx.userAccount : void 0;
66
- if (value === void 0) continue;
66
+ const value = resolveDimension(spec.dimension, ctx);
67
+ if (value === void 0 || value === "") continue;
67
68
  out.push({
68
69
  spec,
69
70
  value
@@ -71,5 +72,13 @@ var specsToReads = (specs, ctx) => {
71
72
  }
72
73
  return out;
73
74
  };
75
+ var resolveDimension = (dimension, ctx) => {
76
+ switch (dimension) {
77
+ case "ip": return ctx.ip;
78
+ case "userAccount": return ctx.userAccount;
79
+ case "deviceBucket": return ctx.raw.fingerprintSummary?.bucketId;
80
+ case "peerIp": return;
81
+ }
82
+ };
74
83
  //#endregion
75
84
  exports.applyRouter = applyRouter;
@@ -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;