@prosopo/provider 5.19.4 → 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 (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 +135 -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
@@ -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
@@ -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;
package/dist/cjs/util.cjs CHANGED
@@ -11,7 +11,12 @@ function encodeStringAddress(address) {
11
11
  try {
12
12
  return (0, _prosopo_util_crypto.encodeAddress)((0, _polkadot_util_is.isHex)(address) ? (0, _polkadot_util_hex.hexToU8a)(address) : (0, _prosopo_util_crypto.decodeAddress)(address));
13
13
  } catch (err) {
14
- throw new _prosopo_common.ProsopoContractError("CONTRACT.INVALID_ADDRESS", { context: { address } });
14
+ throw new _prosopo_common.ProsopoError({
15
+ code: "INVALID_DATA",
16
+ errorSite: "PROV-77",
17
+ message: "Failed to encode invalid address",
18
+ context: { address }
19
+ });
15
20
  }
16
21
  }
17
22
  function shuffleArray(array) {
@@ -43,7 +48,10 @@ var getIPAddress = (ipAddressString) => {
43
48
  return new ip_address.Address6(ipAddressString);
44
49
  }
45
50
  } catch (e) {
46
- throw new _prosopo_common.ProsopoEnvError("API.INVALID_IP");
51
+ throw new _prosopo_common.ProsopoError({
52
+ code: "INVALID_IP",
53
+ errorSite: "PROV-78"
54
+ });
47
55
  }
48
56
  };
49
57
  var getIPAddressFromBigInt = (ipAddressBigInt) => {
@@ -51,7 +59,10 @@ var getIPAddressFromBigInt = (ipAddressBigInt) => {
51
59
  if (ipAddressBigInt > 4228250626n) return ip_address.Address6.fromBigInt(BigInt(ipAddressBigInt));
52
60
  return ip_address.Address4.fromBigInt(BigInt(ipAddressBigInt));
53
61
  } catch (e) {
54
- throw new _prosopo_common.ProsopoEnvError("API.INVALID_IP");
62
+ throw new _prosopo_common.ProsopoError({
63
+ code: "INVALID_IP",
64
+ errorSite: "PROV-79"
65
+ });
55
66
  }
56
67
  };
57
68
  /**
@@ -0,0 +1,98 @@
1
+ declare module "@prosopo/common" {
2
+ interface ErrorSites {
3
+ "PROV-1": true;
4
+ "PROV-2": true;
5
+ "PROV-3": true;
6
+ "PROV-4": true;
7
+ "PROV-5": true;
8
+ "PROV-6": true;
9
+ "PROV-7": true;
10
+ "PROV-8": true;
11
+ "PROV-9": true;
12
+ "PROV-10": true;
13
+ "PROV-11": true;
14
+ "PROV-12": true;
15
+ "PROV-13": true;
16
+ "PROV-14": true;
17
+ "PROV-15": true;
18
+ "PROV-16": true;
19
+ "PROV-17": true;
20
+ "PROV-18": true;
21
+ "PROV-19": true;
22
+ "PROV-20": true;
23
+ "PROV-21": true;
24
+ "PROV-22": true;
25
+ "PROV-23": true;
26
+ "PROV-24": true;
27
+ "PROV-25": true;
28
+ "PROV-26": true;
29
+ "PROV-27": true;
30
+ "PROV-28": true;
31
+ "PROV-29": true;
32
+ "PROV-30": true;
33
+ "PROV-31": true;
34
+ "PROV-32": true;
35
+ "PROV-33": true;
36
+ "PROV-34": true;
37
+ "PROV-35": true;
38
+ "PROV-37": true;
39
+ "PROV-38": true;
40
+ "PROV-39": true;
41
+ "PROV-40": true;
42
+ "PROV-41": true;
43
+ "PROV-42": true;
44
+ "PROV-43": true;
45
+ "PROV-44": true;
46
+ "PROV-45": true;
47
+ "PROV-46": true;
48
+ "PROV-47": true;
49
+ "PROV-48": true;
50
+ "PROV-49": true;
51
+ "PROV-50": true;
52
+ "PROV-51": true;
53
+ "PROV-52": true;
54
+ "PROV-53": true;
55
+ "PROV-54": true;
56
+ "PROV-55": true;
57
+ "PROV-56": true;
58
+ "PROV-57": true;
59
+ "PROV-58": true;
60
+ "PROV-59": true;
61
+ "PROV-60": true;
62
+ "PROV-61": true;
63
+ "PROV-62": true;
64
+ "PROV-63": true;
65
+ "PROV-64": true;
66
+ "PROV-65": true;
67
+ "PROV-66": true;
68
+ "PROV-67": true;
69
+ "PROV-68": true;
70
+ "PROV-69": true;
71
+ "PROV-70": true;
72
+ "PROV-71": true;
73
+ "PROV-72": true;
74
+ "PROV-73": true;
75
+ "PROV-74": true;
76
+ "PROV-75": true;
77
+ "PROV-76": true;
78
+ "PROV-77": true;
79
+ "PROV-78": true;
80
+ "PROV-79": true;
81
+ "PROV-80": true;
82
+ "PROV-81": true;
83
+ "PROV-82": true;
84
+ "PROV-83": true;
85
+ "PROV-84": true;
86
+ "PROV-85": true;
87
+ "PROV-86": true;
88
+ "PROV-87": true;
89
+ "PROV-88": true;
90
+ "PROV-89": true;
91
+ "PROV-90": true;
92
+ "PROV-91": true;
93
+ "PROV-92": true;
94
+ "PROV-93": true;
95
+ }
96
+ }
97
+ export {};
98
+ //# sourceMappingURL=errorSites.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorSites.d.ts","sourceRoot":"","sources":["../src/errorSites.ts"],"names":[],"mappings":"AAcA,OAAO,QAAQ,iBAAiB,CAAC;IAChC,UAAU,UAAU;QACnB,QAAQ,EAAE,IAAI,CAAC;QACf,QAAQ,EAAE,IAAI,CAAC;QACf,QAAQ,EAAE,IAAI,CAAC;QACf,QAAQ,EAAE,IAAI,CAAC;QACf,QAAQ,EAAE,IAAI,CAAC;QACf,QAAQ,EAAE,IAAI,CAAC;QACf,QAAQ,EAAE,IAAI,CAAC;QACf,QAAQ,EAAE,IAAI,CAAC;QACf,QAAQ,EAAE,IAAI,CAAC;QACf,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;QAChB,SAAS,EAAE,IAAI,CAAC;KAChB;CACD;AAED,OAAO,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=errorSites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorSites.js","sourceRoot":"","sources":["../src/errorSites.ts"],"names":[],"mappings":""}
@@ -0,0 +1,69 @@
1
+ import { hexHashArray } from "@prosopo/util-crypto";
2
+ //#region ../fingerprint/dist/merkle.js
3
+ var at = (arr, index) => {
4
+ const value = arr[index];
5
+ if (value === void 0) throw new Error(`merkle: index ${index} out of range (length ${arr.length})`);
6
+ return value;
7
+ };
8
+ /** Hash a pair of child hashes into their parent. */
9
+ var hashMerklePair = (left, right) => hexHashArray([left, right]);
10
+ /**
11
+ * Build every layer of the Merkle tree, bottom-up. Layer 0 is the leaf hashes,
12
+ * the final layer is `[root]`. An odd node at the end of a layer is paired with
13
+ * itself.
14
+ */
15
+ var buildMerkleLayers = (leafHashes) => {
16
+ if (leafHashes.length === 0) throw new Error("merkle: cannot build a tree with no leaves");
17
+ const layers = [[...leafHashes]];
18
+ let current = leafHashes;
19
+ while (current.length > 1) {
20
+ const next = [];
21
+ for (let i = 0; i < current.length; i += 2) {
22
+ const left = at(current, i);
23
+ const right = i + 1 < current.length ? at(current, i + 1) : left;
24
+ next.push(hashMerklePair(left, right));
25
+ }
26
+ layers.push(next);
27
+ current = next;
28
+ }
29
+ return layers;
30
+ };
31
+ var merkleRootFromLayers = (layers) => at(at(layers, layers.length - 1), 0);
32
+ /** Produce the sibling path proving `leafHash` belongs to the tree. */
33
+ var merkleProofFromLayers = (layers, leafHash) => {
34
+ const proof = [];
35
+ let hash = leafHash;
36
+ for (let layerNum = 0; layerNum < layers.length - 1; layerNum++) {
37
+ const layer = at(layers, layerNum);
38
+ const index = layer.indexOf(hash);
39
+ if (index === -1) throw new Error("merkle: leaf hash not present in layer");
40
+ let partnerIndex = index % 2 === 1 ? index - 1 : index + 1;
41
+ if (partnerIndex > layer.length - 1) partnerIndex = index;
42
+ const partner = at(layer, partnerIndex);
43
+ const pair = partnerIndex > index ? [hash, partner] : [partner, hash];
44
+ proof.push(pair);
45
+ hash = hashMerklePair(pair[0], pair[1]);
46
+ }
47
+ return [...proof, [merkleRootFromLayers(layers)]];
48
+ };
49
+ /** Verify a leaf + sibling path recomputes to the proof's embedded root. */
50
+ var verifyMerkleProof = (leafHash, proof) => {
51
+ try {
52
+ const firstLayer = proof[0];
53
+ if (firstLayer === void 0 || firstLayer.indexOf(leafHash) === -1) return false;
54
+ if (proof.length === 1) return at(firstLayer, 0) === leafHash;
55
+ const root = at(at(proof, proof.length - 1), 0);
56
+ let hash = leafHash;
57
+ for (let i = 0; i < proof.length - 1; i++) {
58
+ const layer = at(proof, i);
59
+ if (layer.indexOf(hash) === -1) return false;
60
+ hash = hashMerklePair(at(layer, 0), at(layer, 1));
61
+ if (at(proof, i + 1).indexOf(hash) === -1) return false;
62
+ }
63
+ return hash === root;
64
+ } catch {
65
+ return false;
66
+ }
67
+ };
68
+ //#endregion
69
+ export { buildMerkleLayers, hashMerklePair, merkleProofFromLayers, merkleRootFromLayers, verifyMerkleProof };
@@ -0,0 +1,95 @@
1
+ import { buildMerkleLayers, merkleProofFromLayers, merkleRootFromLayers, verifyMerkleProof } from "./merkle.js";
2
+ import { hexHash } from "@prosopo/util-crypto";
3
+ /**
4
+ * The fixed set of components the client discloses in a proof of fingerprint.
5
+ * Disclosing every component (the previous default) made the proof enormous —
6
+ * each disclosure carries a full Merkle path and its raw value, and components
7
+ * like webgl/audio/fonts have very large values. Selective disclosure keeps the
8
+ * commitment (`root`) over the whole component set while only these cheap,
9
+ * stable scalar components carry a path + value, shrinking the payload ~10x.
10
+ *
11
+ * The provider-side validator's bounds MUST be a subset of these keys: a bounded
12
+ * key that isn't disclosed would always fail validation as `missing:<key>`.
13
+ */
14
+ var FINGERPRINT_DISCLOSURE_KEYS = [
15
+ "colorDepth",
16
+ "cookiesEnabled",
17
+ "sessionStorage",
18
+ "localStorage",
19
+ "timezone",
20
+ "hardwareConcurrency",
21
+ "languages",
22
+ "architecture",
23
+ "deviceBucket"
24
+ ];
25
+ var escapeKey = (key) => key.replace(/([:|\\])/g, "\\$1");
26
+ var componentLeafContent = (key, component) => {
27
+ const serialized = "error" in component ? "error" : JSON.stringify(component.value);
28
+ return `${escapeKey(key)}:${serialized}`;
29
+ };
30
+ var disclosureLeafContent = (disclosure) => {
31
+ const serialized = disclosure.error ? "error" : JSON.stringify(disclosure.value);
32
+ return `${escapeKey(disclosure.key)}:${serialized}`;
33
+ };
34
+ var leafHashForContent = (content) => hexHash(content);
35
+ /**
36
+ * Build a {@link FingerprintProof} from an already-resolved FingerprintJS
37
+ * components map. The commitment always covers every component (in sorted key
38
+ * order); `discloseKeys` selects which components are revealed (defaulting to
39
+ * all). Keys that are not present in the fingerprint are skipped — a validator
40
+ * should treat an expected-but-absent disclosure as a failure.
41
+ */
42
+ var buildFingerprintProofFromComponents = (components, discloseKeys) => {
43
+ const keys = Object.keys(components).sort();
44
+ if (keys.length === 0) throw new Error("fingerprint proof: no components to commit to");
45
+ const leafHashes = keys.map((key) => {
46
+ const component = components[key];
47
+ if (component === void 0) throw new Error(`fingerprint proof: missing component ${key}`);
48
+ return leafHashForContent(componentLeafContent(key, component));
49
+ });
50
+ const layers = buildMerkleLayers(leafHashes);
51
+ const root = merkleRootFromLayers(layers);
52
+ const disclose = discloseKeys ?? keys;
53
+ const disclosures = [];
54
+ for (const key of disclose) {
55
+ const index = keys.indexOf(key);
56
+ if (index === -1) continue;
57
+ const component = components[key];
58
+ const leafHash = leafHashes[index];
59
+ if (component === void 0 || leafHash === void 0) continue;
60
+ const proof = merkleProofFromLayers(layers, leafHash);
61
+ disclosures.push("error" in component ? {
62
+ key,
63
+ error: true,
64
+ proof
65
+ } : {
66
+ key,
67
+ value: component.value,
68
+ proof
69
+ });
70
+ }
71
+ return {
72
+ v: 1,
73
+ root,
74
+ disclosures
75
+ };
76
+ };
77
+ /**
78
+ * Structural verification of a proof: every disclosed `(key, value)` re-hashes
79
+ * to a leaf that is proven to belong to the single committed `root`. This is
80
+ * the non-secret half of validation — the value-bounding rules live in the
81
+ * provider-side (closed-source) validator and are layered on top of this.
82
+ */
83
+ var verifyFingerprintProofStructure = (proof) => {
84
+ if (proof.v !== 1) return false;
85
+ if (typeof proof.root !== "string" || proof.disclosures.length === 0) return false;
86
+ for (const disclosure of proof.disclosures) {
87
+ if (!verifyMerkleProof(leafHashForContent(disclosureLeafContent(disclosure)), disclosure.proof)) return false;
88
+ const rootLayer = disclosure.proof[disclosure.proof.length - 1];
89
+ if (rootLayer === void 0 || rootLayer[0] !== proof.root) return false;
90
+ }
91
+ return true;
92
+ };
93
+ var encodeFingerprintProof = (proof) => JSON.stringify(proof);
94
+ //#endregion
95
+ export { FINGERPRINT_DISCLOSURE_KEYS, buildFingerprintProofFromComponents, encodeFingerprintProof, leafHashForContent, verifyFingerprintProofStructure };
@@ -0,0 +1,73 @@
1
+ import { verifyFingerprintProofStructure } from "./proof.js";
2
+ import { hexHash } from "@prosopo/util-crypto";
3
+ //#region ../fingerprint/dist/summary.js
4
+ /**
5
+ * The disclosed keys that are fixed by the installation and the host. A hash
6
+ * over them names a cohort of devices.
7
+ *
8
+ * `colorDepth` and `hardwareConcurrency` are disclosed too but kept out of the
9
+ * hash and stored beside it, so that the values can be read per cohort rather
10
+ * than only folded into it.
11
+ */
12
+ var GROUP_KEYS = [
13
+ "cookiesEnabled",
14
+ "sessionStorage",
15
+ "localStorage",
16
+ "timezone",
17
+ "languages",
18
+ "architecture"
19
+ ];
20
+ var asNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
21
+ /**
22
+ * Reduce an encoded proof to the fields worth storing, or `undefined` when it
23
+ * is absent, unparseable, or fails structural verification.
24
+ *
25
+ * Structural verification is not optional here: an unverified disclosure is a
26
+ * client-asserted value with a decorative Merkle path beside it, and storing
27
+ * one would put a forgeable field into an aggregation that reads as
28
+ * tamper-evident. Whether the values are *plausible* is a separate concern and
29
+ * stays in the routing machine's validator; this only refuses what does not
30
+ * hash together.
31
+ */
32
+ var summariseFingerprintProof = (encoded) => {
33
+ if (!encoded) return void 0;
34
+ let proof;
35
+ try {
36
+ proof = JSON.parse(encoded);
37
+ } catch {
38
+ return;
39
+ }
40
+ if (typeof proof !== "object" || proof === null || typeof proof.root !== "string" || !Array.isArray(proof.disclosures)) return;
41
+ if (!verifyFingerprintProofStructure(proof)) return void 0;
42
+ const byKey = /* @__PURE__ */ new Map();
43
+ for (const disclosure of proof.disclosures) if (!disclosure.error) byKey.set(disclosure.key, disclosure.value);
44
+ const groupInput = GROUP_KEYS.map((key) => `${key}:${JSON.stringify(byKey.get(key) ?? null)}`).join("|");
45
+ const disclosed = {};
46
+ const timezone = byKey.get("timezone");
47
+ if (typeof timezone === "string") disclosed.timezone = timezone;
48
+ const languages = byKey.get("languages");
49
+ if (languages !== void 0) disclosed.languages = JSON.stringify(languages);
50
+ const architecture = asNumber(byKey.get("architecture"));
51
+ if (architecture !== void 0) disclosed.architecture = architecture;
52
+ for (const key of [
53
+ "cookiesEnabled",
54
+ "sessionStorage",
55
+ "localStorage"
56
+ ]) {
57
+ const value = byKey.get(key);
58
+ if (typeof value === "boolean") disclosed[key] = value;
59
+ }
60
+ const bucketId = byKey.get("deviceBucket");
61
+ const colorDepth = asNumber(byKey.get("colorDepth"));
62
+ const hardwareConcurrency = asNumber(byKey.get("hardwareConcurrency"));
63
+ return {
64
+ root: proof.root,
65
+ groupHash: hexHash(groupInput),
66
+ ...typeof bucketId === "string" && bucketId !== "" && { bucketId },
67
+ ...colorDepth !== void 0 && { colorDepth },
68
+ ...hardwareConcurrency !== void 0 && { hardwareConcurrency },
69
+ ...Object.keys(disclosed).length > 0 && { disclosed }
70
+ };
71
+ };
72
+ //#endregion
73
+ export { summariseFingerprintProof };
package/dist/index.js CHANGED
@@ -17,9 +17,9 @@ import { createApiAdminRoutesProvider } from "./api/admin/createApiAdminRoutesPr
17
17
  import { headerCheckMiddleware } from "./api/headerCheckMiddleware.js";
18
18
  import { ignoreMiddleware } from "./api/ignoreMiddleware.js";
19
19
  import { robotsMiddleware } from "./api/robotsMiddleware.js";
20
- import { getClientApiPathsExpectingProsopoHeaders, getUserFromJWT, isTlsAvailable, providerCorsOptions, startProviderApi } from "./api/startProviderApi.js";
20
+ import { getClientApiPathsExpectingProsopoHeaders, getServerVerifyPaths, getUserFromJWT, isTlsAvailable, providerCorsOptions, startProviderApi } from "./api/startProviderApi.js";
21
21
  import { migrateFrictionlessLadder, runFrictionlessLadderMigration } from "./migrations/frictionlessLadder.js";
22
22
  import { storeCaptchasExternally } from "./schedulers/captchaScheduler.js";
23
23
  import { getClientList } from "./schedulers/getClientList.js";
24
24
  import { updateSpamEmailDomainsScheduler } from "./schedulers/updateSpamEmailDomains.js";
25
- export { BlacklistRequestInspector, DEFAULT_JA4, FrictionlessReason, Tasks, asyncHandler, blockMiddleware, checkIfTaskIsRunning, compareIPs, createApiAdminRoutesProvider, deepValidateIpAddress, domainMiddleware, encodeStringAddress, evaluateIpValidationRules, getClientApiPathsExpectingProsopoHeaders, getClientList, getCompositeIpAddress, getHandshakeTiming, getIPAddress, getIPAddressFromBigInt, getIpAddressFromComposite, getJA4, getPrioritisedAccessRule, getRequestUserScope, getUserFromJWT, getVerdictCache, handshakeTimingMiddleware, headerCheckMiddleware, ignoreMiddleware, isSameIpOrigin, isTlsAvailable, ja4Middleware, migrateFrictionlessLadder, normalizeHeadersForMatching, prosopoRouter, prosopoVerifyRouter, providerCorsOptions, publicRouter, rankCandidateRules, robotsMiddleware, runFrictionlessLadderMigration, shuffleArray, startProviderApi, storeCaptchasExternally, updateSpamEmailDomains, updateSpamEmailDomainsScheduler, validateIpAddress };
25
+ export { BlacklistRequestInspector, DEFAULT_JA4, FrictionlessReason, Tasks, asyncHandler, blockMiddleware, checkIfTaskIsRunning, compareIPs, createApiAdminRoutesProvider, deepValidateIpAddress, domainMiddleware, encodeStringAddress, evaluateIpValidationRules, getClientApiPathsExpectingProsopoHeaders, getClientList, getCompositeIpAddress, getHandshakeTiming, getIPAddress, getIPAddressFromBigInt, getIpAddressFromComposite, getJA4, getPrioritisedAccessRule, getRequestUserScope, getServerVerifyPaths, getUserFromJWT, getVerdictCache, handshakeTimingMiddleware, headerCheckMiddleware, ignoreMiddleware, isSameIpOrigin, isTlsAvailable, ja4Middleware, migrateFrictionlessLadder, normalizeHeadersForMatching, prosopoRouter, prosopoVerifyRouter, providerCorsOptions, publicRouter, rankCandidateRules, robotsMiddleware, runFrictionlessLadderMigration, shuffleArray, startProviderApi, storeCaptchasExternally, updateSpamEmailDomains, updateSpamEmailDomainsScheduler, validateIpAddress };