@prosopo/provider 4.15.14 → 4.15.16

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 (232) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +106 -106
  2. package/.turbo/turbo-build$colon$tsc.log +24 -24
  3. package/.turbo/turbo-build.log +107 -104
  4. package/CHANGELOG.md +63 -0
  5. package/dist/_virtual/_rolldown/runtime.js +3 -0
  6. package/dist/api/admin/apiAdminRoutesProvider.js +27 -46
  7. package/dist/api/admin/apiClearAllCountersEndpoint.js +62 -57
  8. package/dist/api/admin/apiDnsEventEndpoint.js +79 -92
  9. package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.js +43 -45
  10. package/dist/api/admin/apiGetDecisionMachineEndpoint.js +40 -40
  11. package/dist/api/admin/apiRegisterSiteKeyEndpoint.js +23 -22
  12. package/dist/api/admin/apiRegisterSiteKeysEndpoint.js +26 -30
  13. package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.js +35 -37
  14. package/dist/api/admin/apiRemoveDecisionMachineEndpoint.js +40 -40
  15. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.d.ts.map +1 -1
  16. package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js +29 -31
  17. package/dist/api/admin/apiRemoveSiteKeyEndpoint.js +33 -29
  18. package/dist/api/admin/apiRemoveSiteKeysEndpoint.js +32 -31
  19. package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js +43 -35
  20. package/dist/api/admin/apiUpdateDecisionMachineEndpoint.js +43 -63
  21. package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js +36 -35
  22. package/dist/api/admin/createApiAdminRoutesProvider.js +6 -8
  23. package/dist/api/blacklistRequestInspector.js +285 -377
  24. package/dist/api/block.js +17 -30
  25. package/dist/api/captcha/checkSpamEmail.js +88 -98
  26. package/dist/api/captcha/contextAwareValidation.js +21 -15
  27. package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.js +126 -140
  28. package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.js +11 -12
  29. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js +236 -299
  30. package/dist/api/captcha/getFrictionlessCaptchaChallenge/decryptSimdReadings.js +10 -13
  31. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js +336 -462
  32. package/dist/api/captcha/getFrictionlessCaptchaChallenge/honeypotResponse.js +17 -14
  33. package/dist/api/captcha/getFrictionlessCaptchaChallenge/sessionDedup.js +27 -27
  34. package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js +42 -63
  35. package/dist/api/captcha/getFrictionlessCaptchaChallenge.js +2 -4
  36. package/dist/api/captcha/getImageCaptchaChallenge.js +136 -207
  37. package/dist/api/captcha/getPoWCaptchaChallenge.js +128 -198
  38. package/dist/api/captcha/getPuzzleCaptchaChallenge.js +132 -201
  39. package/dist/api/captcha/maintenanceModeResponses.js +38 -47
  40. package/dist/api/captcha/submitImageCaptchaSolution.js +75 -101
  41. package/dist/api/captcha/submitPoWCaptchaSolution.js +137 -207
  42. package/dist/api/captcha/submitPuzzleCaptchaSolution.js +73 -105
  43. package/dist/api/captcha.js +76 -58
  44. package/dist/api/dnsEventUrl.js +20 -22
  45. package/dist/api/domainMiddleware.js +104 -115
  46. package/dist/api/forwardVerify.js +62 -48
  47. package/dist/api/handshakeTimingMiddleware.js +43 -62
  48. package/dist/api/hardBlockVerdictCache.js +114 -117
  49. package/dist/api/headerCheckMiddleware.js +34 -34
  50. package/dist/api/ignoreMiddleware.js +13 -15
  51. package/dist/api/ipInfoMiddleware.js +17 -19
  52. package/dist/api/ja4.js +149 -188
  53. package/dist/api/ja4Middleware.js +39 -54
  54. package/dist/api/metrics.js +245 -257
  55. package/dist/api/public.js +52 -54
  56. package/dist/api/robotsMiddleware.js +10 -10
  57. package/dist/api/startProviderApi.js +205 -232
  58. package/dist/api/testSiteKey.js +16 -16
  59. package/dist/api/validateAddress.js +23 -21
  60. package/dist/api/verify.js +334 -377
  61. package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
  62. package/dist/cjs/api/admin/apiAdminRoutesProvider.cjs +40 -59
  63. package/dist/cjs/api/admin/apiClearAllCountersEndpoint.cjs +63 -58
  64. package/dist/cjs/api/admin/apiDnsEventEndpoint.cjs +82 -93
  65. package/dist/cjs/api/admin/apiGetAllDecisionMachinesEndpoint.cjs +46 -48
  66. package/dist/cjs/api/admin/apiGetDecisionMachineEndpoint.cjs +41 -41
  67. package/dist/cjs/api/admin/apiRegisterSiteKeyEndpoint.cjs +25 -24
  68. package/dist/cjs/api/admin/apiRegisterSiteKeysEndpoint.cjs +28 -32
  69. package/dist/cjs/api/admin/apiRemoveAllDecisionMachinesEndpoint.cjs +38 -40
  70. package/dist/cjs/api/admin/apiRemoveDecisionMachineEndpoint.cjs +41 -41
  71. package/dist/cjs/api/admin/apiRemoveDetectorKeyEndpoint.cjs +31 -33
  72. package/dist/cjs/api/admin/apiRemoveSiteKeyEndpoint.cjs +35 -31
  73. package/dist/cjs/api/admin/apiRemoveSiteKeysEndpoint.cjs +34 -33
  74. package/dist/cjs/api/admin/apiToggleMaintenanceModeEndpoint.cjs +45 -35
  75. package/dist/cjs/api/admin/apiUpdateDecisionMachineEndpoint.cjs +45 -65
  76. package/dist/cjs/api/admin/apiUpdateDetectorKeyEndpoint.cjs +38 -37
  77. package/dist/cjs/api/admin/createApiAdminRoutesProvider.cjs +7 -8
  78. package/dist/cjs/api/blacklistRequestInspector.cjs +288 -376
  79. package/dist/cjs/api/block.cjs +18 -30
  80. package/dist/cjs/api/captcha/checkSpamEmail.cjs +90 -100
  81. package/dist/cjs/api/captcha/contextAwareValidation.cjs +21 -14
  82. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.cjs +125 -140
  83. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/constants.cjs +10 -10
  84. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.cjs +238 -301
  85. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decryptSimdReadings.cjs +9 -12
  86. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +349 -473
  87. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/honeypotResponse.cjs +18 -14
  88. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/sessionDedup.cjs +26 -26
  89. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.cjs +42 -63
  90. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge.cjs +2 -3
  91. package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +138 -208
  92. package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +131 -200
  93. package/dist/cjs/api/captcha/getPuzzleCaptchaChallenge.cjs +135 -203
  94. package/dist/cjs/api/captcha/maintenanceModeResponses.cjs +38 -44
  95. package/dist/cjs/api/captcha/submitImageCaptchaSolution.cjs +77 -102
  96. package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +140 -209
  97. package/dist/cjs/api/captcha/submitPuzzleCaptchaSolution.cjs +76 -107
  98. package/dist/cjs/api/captcha.cjs +79 -58
  99. package/dist/cjs/api/dnsEventUrl.cjs +20 -21
  100. package/dist/cjs/api/domainMiddleware.cjs +106 -117
  101. package/dist/cjs/api/forwardVerify.cjs +63 -49
  102. package/dist/cjs/api/handshakeTimingMiddleware.cjs +43 -61
  103. package/dist/cjs/api/hardBlockVerdictCache.cjs +114 -114
  104. package/dist/cjs/api/headerCheckMiddleware.cjs +34 -34
  105. package/dist/cjs/api/ignoreMiddleware.cjs +12 -14
  106. package/dist/cjs/api/ipInfoMiddleware.cjs +16 -18
  107. package/dist/cjs/api/ja4.cjs +149 -187
  108. package/dist/cjs/api/ja4Middleware.cjs +40 -53
  109. package/dist/cjs/api/metrics.cjs +229 -228
  110. package/dist/cjs/api/public.cjs +57 -57
  111. package/dist/cjs/api/robotsMiddleware.cjs +9 -9
  112. package/dist/cjs/api/startProviderApi.cjs +219 -237
  113. package/dist/cjs/api/testSiteKey.cjs +15 -14
  114. package/dist/cjs/api/validateAddress.cjs +24 -21
  115. package/dist/cjs/api/verify.cjs +338 -379
  116. package/dist/cjs/compositeIpAddress.cjs +40 -47
  117. package/dist/cjs/index.cjs +65 -71
  118. package/dist/cjs/pairs.cjs +31 -35
  119. package/dist/cjs/rules/lang.cjs +10 -14
  120. package/dist/cjs/schedulers/captchaScheduler.cjs +26 -32
  121. package/dist/cjs/schedulers/getClientList.cjs +35 -33
  122. package/dist/cjs/schedulers/setClientEntropy.cjs +35 -33
  123. package/dist/cjs/schedulers/updateSpamEmailDomains.cjs +39 -43
  124. package/dist/cjs/services/ipComparison.cjs +122 -119
  125. package/dist/cjs/tasks/captchaManager.cjs +407 -486
  126. package/dist/cjs/tasks/client/clientTasks.cjs +347 -470
  127. package/dist/cjs/tasks/dataset/datasetTasks.cjs +25 -29
  128. package/dist/cjs/tasks/dataset/datasetTasksUtils.cjs +16 -32
  129. package/dist/cjs/tasks/decisionMachine/decisionMachineRunner.cjs +220 -307
  130. package/dist/cjs/tasks/detection/decodeBehavior.cjs +408 -317
  131. package/dist/cjs/tasks/detection/decodePayload.cjs +686 -468
  132. package/dist/cjs/tasks/detection/decodeSimd.cjs +462 -304
  133. package/dist/cjs/tasks/detection/getBotScore.cjs +37 -43
  134. package/dist/cjs/tasks/dnsEvent/enrichDnsEvent.cjs +88 -71
  135. package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +348 -486
  136. package/dist/cjs/tasks/frictionless/frictionlessTasksUtils.cjs +13 -30
  137. package/dist/cjs/tasks/frictionless/routingMachine.cjs +71 -55
  138. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +555 -806
  139. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasksUtils.cjs +22 -23
  140. package/dist/cjs/tasks/index.cjs +2 -4
  141. package/dist/cjs/tasks/powCaptcha/powTasks.cjs +491 -687
  142. package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +17 -29
  143. package/dist/cjs/tasks/puzzleCaptcha/puzzleTasks.cjs +422 -591
  144. package/dist/cjs/tasks/puzzleCaptcha/puzzleTasksUtils.cjs +8 -5
  145. package/dist/cjs/tasks/spam/checkSpamEmail.cjs +133 -141
  146. package/dist/cjs/tasks/spam/checkTrafficFilter.cjs +118 -76
  147. package/dist/cjs/tasks/spam/evaluateEmailSpamRules.cjs +75 -84
  148. package/dist/cjs/tasks/spam/updateSpamEmailDomains.cjs +40 -56
  149. package/dist/cjs/tasks/tasks.cjs +107 -158
  150. package/dist/cjs/util/usageCounters.cjs +220 -211
  151. package/dist/cjs/util.cjs +329 -359
  152. package/dist/cjs/utils/devicePlatform.cjs +14 -8
  153. package/dist/cjs/utils/dns.cjs +68 -93
  154. package/dist/cjs/utils/hashUserAgent.cjs +14 -7
  155. package/dist/cjs/utils/hashUserIp.cjs +14 -6
  156. package/dist/cjs/utils/honeypot/encoders.cjs +74 -80
  157. package/dist/cjs/utils/honeypot/phraseBank.cjs +51 -44
  158. package/dist/cjs/utils/normalizeRequestIp.cjs +33 -25
  159. package/dist/compositeIpAddress.js +38 -46
  160. package/dist/index.js +12 -56
  161. package/dist/pairs.js +31 -37
  162. package/dist/rules/lang.js +11 -15
  163. package/dist/schedulers/captchaScheduler.js +25 -31
  164. package/dist/schedulers/getClientList.js +34 -32
  165. package/dist/schedulers/setClientEntropy.js +34 -32
  166. package/dist/schedulers/updateSpamEmailDomains.js +38 -42
  167. package/dist/services/ipComparison.js +122 -119
  168. package/dist/tasks/captchaManager.js +403 -483
  169. package/dist/tasks/client/clientTasks.js +343 -467
  170. package/dist/tasks/dataset/datasetTasks.js +24 -28
  171. package/dist/tasks/dataset/datasetTasksUtils.js +15 -31
  172. package/dist/tasks/decisionMachine/decisionMachineRunner.js +217 -306
  173. package/dist/tasks/detection/getBotScore.js +37 -43
  174. package/dist/tasks/dnsEvent/enrichDnsEvent.d.ts.map +1 -1
  175. package/dist/tasks/dnsEvent/enrichDnsEvent.js +88 -74
  176. package/dist/tasks/dnsEvent/enrichDnsEvent.js.map +1 -1
  177. package/dist/tasks/frictionless/frictionlessTasks.js +342 -479
  178. package/dist/tasks/frictionless/frictionlessTasksUtils.js +14 -32
  179. package/dist/tasks/frictionless/routingMachine.js +72 -56
  180. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +550 -801
  181. package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js +21 -22
  182. package/dist/tasks/index.js +1 -3
  183. package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
  184. package/dist/tasks/powCaptcha/powTasks.js +486 -682
  185. package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
  186. package/dist/tasks/powCaptcha/powTasksUtils.js +15 -28
  187. package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts.map +1 -1
  188. package/dist/tasks/puzzleCaptcha/puzzleTasks.js +417 -586
  189. package/dist/tasks/puzzleCaptcha/puzzleTasks.js.map +1 -1
  190. package/dist/tasks/puzzleCaptcha/puzzleTasksUtils.js +9 -6
  191. package/dist/tasks/spam/checkSpamEmail.js +133 -141
  192. package/dist/tasks/spam/checkTrafficFilter.d.ts +1 -0
  193. package/dist/tasks/spam/checkTrafficFilter.d.ts.map +1 -1
  194. package/dist/tasks/spam/checkTrafficFilter.js +117 -77
  195. package/dist/tasks/spam/checkTrafficFilter.js.map +1 -1
  196. package/dist/tasks/spam/evaluateEmailSpamRules.js +75 -86
  197. package/dist/tasks/spam/updateSpamEmailDomains.js +36 -54
  198. package/dist/tasks/tasks.js +98 -150
  199. package/dist/tests/integration/api/blacklistRequestInspector.integration.test.js +4 -1
  200. package/dist/tests/integration/api/blacklistRequestInspector.integration.test.js.map +1 -1
  201. package/dist/tests/unit/api/block.unit.test.js +8 -4
  202. package/dist/tests/unit/api/block.unit.test.js.map +1 -1
  203. package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js +8 -6
  204. package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js.map +1 -1
  205. package/dist/tests/unit/api/forwardVerify.unit.test.js +3 -1
  206. package/dist/tests/unit/api/forwardVerify.unit.test.js.map +1 -1
  207. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +15 -7
  208. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
  209. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js +24 -18
  210. package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js.map +1 -1
  211. package/dist/tests/unit/schedulers/getClientList.unit.test.js +19 -13
  212. package/dist/tests/unit/schedulers/getClientList.unit.test.js.map +1 -1
  213. package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js +19 -13
  214. package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js.map +1 -1
  215. package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +1 -1
  216. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js +22 -16
  217. package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js.map +1 -1
  218. package/dist/tests/unit/tasks/spam/checkTrafficFilter.unit.test.js +140 -0
  219. package/dist/tests/unit/tasks/spam/checkTrafficFilter.unit.test.js.map +1 -1
  220. package/dist/tests/unit/testUtils/mockProviderEnv.d.ts +7 -7
  221. package/dist/util/usageCounters.js +220 -212
  222. package/dist/util.d.ts.map +1 -1
  223. package/dist/util.js +327 -364
  224. package/dist/util.js.map +1 -1
  225. package/dist/utils/devicePlatform.js +15 -9
  226. package/dist/utils/dns.js +64 -77
  227. package/dist/utils/hashUserAgent.js +14 -7
  228. package/dist/utils/hashUserIp.js +14 -6
  229. package/dist/utils/honeypot/encoders.js +74 -80
  230. package/dist/utils/honeypot/phraseBank.js +49 -44
  231. package/dist/utils/normalizeRequestIp.js +34 -26
  232. package/package.json +24 -24
@@ -1,30 +1,26 @@
1
- import { parseCaptchaDataset } from "@prosopo/datasets";
2
1
  import { providerValidateDataset } from "./datasetTasksUtils.js";
3
- class DatasetManager {
4
- constructor(config, logger, captchaConfig, db) {
5
- this.config = config;
6
- this.logger = logger;
7
- this.captchaConfig = captchaConfig;
8
- this.db = db;
9
- }
10
- /**
11
- * @description Set the provider dataset from a file
12
- *
13
- * @param file JSON of the captcha dataset
14
- */
15
- async providerSetDatasetFromFile(file) {
16
- const datasetRaw = parseCaptchaDataset(file);
17
- return await this.providerSetDataset(datasetRaw);
18
- }
19
- async providerSetDataset(datasetRaw) {
20
- const dataset = await providerValidateDataset(
21
- datasetRaw,
22
- this.captchaConfig.solved.count,
23
- this.captchaConfig.unsolved.count
24
- );
25
- await this.db?.storeDataset(dataset);
26
- }
27
- }
28
- export {
29
- DatasetManager
2
+ import { parseCaptchaDataset } from "@prosopo/datasets";
3
+ //#region src/tasks/dataset/datasetTasks.ts
4
+ var DatasetManager = class {
5
+ constructor(config, logger, captchaConfig, db) {
6
+ this.config = config;
7
+ this.logger = logger;
8
+ this.captchaConfig = captchaConfig;
9
+ this.db = db;
10
+ }
11
+ /**
12
+ * @description Set the provider dataset from a file
13
+ *
14
+ * @param file JSON of the captcha dataset
15
+ */
16
+ async providerSetDatasetFromFile(file) {
17
+ const datasetRaw = parseCaptchaDataset(file);
18
+ return await this.providerSetDataset(datasetRaw);
19
+ }
20
+ async providerSetDataset(datasetRaw) {
21
+ const dataset = await providerValidateDataset(datasetRaw, this.captchaConfig.solved.count, this.captchaConfig.unsolved.count);
22
+ await this.db?.storeDataset(dataset);
23
+ }
30
24
  };
25
+ //#endregion
26
+ export { DatasetManager };
@@ -1,34 +1,18 @@
1
1
  import { ProsopoEnvError } from "@prosopo/common";
2
2
  import { buildDataset } from "@prosopo/datasets";
3
- const providerValidateDataset = async (datasetRaw, minSolvedCaptchas, minUnsolvedCaptchas) => {
4
- if (datasetRaw.captchas.length < minSolvedCaptchas + minUnsolvedCaptchas) {
5
- throw new ProsopoEnvError("DATASET.CAPTCHAS_COUNT_LESS_THAN_CONFIGURED", {
6
- context: { failedFuncName: providerValidateDataset.name }
7
- });
8
- }
9
- const solutions = datasetRaw.captchas.map((captcha) => captcha.solution ? 1 : 0).reduce((partialSum, b) => partialSum + b, 0);
10
- if (solutions < minSolvedCaptchas) {
11
- throw new ProsopoEnvError("DATASET.SOLUTIONS_COUNT_LESS_THAN_CONFIGURED", {
12
- context: { failedFuncName: providerValidateDataset.name }
13
- });
14
- }
15
- if (solutions < minUnsolvedCaptchas) {
16
- throw new ProsopoEnvError("DATASET.SOLUTIONS_COUNT_LESS_THAN_CONFIGURED", {
17
- context: { failedFuncName: providerValidateDataset.name }
18
- });
19
- }
20
- const dataset = await buildDataset(datasetRaw);
21
- if (!dataset.datasetId || !dataset.datasetContentId) {
22
- throw new ProsopoEnvError("DATASET.DATASET_ID_UNDEFINED", {
23
- context: {
24
- failedFuncName: providerValidateDataset.name,
25
- datasetId: dataset.datasetId,
26
- datasetContentId: dataset.datasetContentId
27
- }
28
- });
29
- }
30
- return dataset;
31
- };
32
- export {
33
- providerValidateDataset
3
+ //#region src/tasks/dataset/datasetTasksUtils.ts
4
+ var providerValidateDataset = async (datasetRaw, minSolvedCaptchas, minUnsolvedCaptchas) => {
5
+ if (datasetRaw.captchas.length < minSolvedCaptchas + minUnsolvedCaptchas) throw new ProsopoEnvError("DATASET.CAPTCHAS_COUNT_LESS_THAN_CONFIGURED", { context: { failedFuncName: providerValidateDataset.name } });
6
+ const solutions = datasetRaw.captchas.map((captcha) => captcha.solution ? 1 : 0).reduce((partialSum, b) => partialSum + b, 0);
7
+ if (solutions < minSolvedCaptchas) throw new ProsopoEnvError("DATASET.SOLUTIONS_COUNT_LESS_THAN_CONFIGURED", { context: { failedFuncName: providerValidateDataset.name } });
8
+ if (solutions < minUnsolvedCaptchas) throw new ProsopoEnvError("DATASET.SOLUTIONS_COUNT_LESS_THAN_CONFIGURED", { context: { failedFuncName: providerValidateDataset.name } });
9
+ const dataset = await buildDataset(datasetRaw);
10
+ if (!dataset.datasetId || !dataset.datasetContentId) throw new ProsopoEnvError("DATASET.DATASET_ID_UNDEFINED", { context: {
11
+ failedFuncName: providerValidateDataset.name,
12
+ datasetId: dataset.datasetId,
13
+ datasetContentId: dataset.datasetContentId
14
+ } });
15
+ return dataset;
34
16
  };
17
+ //#endregion
18
+ export { providerValidateDataset };
@@ -1,309 +1,220 @@
1
+ import { CounterSpecSchema, DecisionMachineDecision, DecisionMachineKind, DecisionMachineOutputSchema, DecisionMachineRuntime, DecisionMachineScope, RoutingMachineOutputSchema } from "@prosopo/types";
1
2
  import vm from "node:vm";
2
- import { DecisionMachineDecision, CounterSpecSchema, DecisionMachineKind, DecisionMachineRuntime, DecisionMachineOutputSchema, RoutingMachineOutputSchema, DecisionMachineScope } from "@prosopo/types";
3
3
  import { z } from "zod";
4
- const LOAD_TIMEOUT_MS = Number.parseInt(process.env.DECISION_MACHINE_LOAD_TIMEOUT_MS ?? "", 10) || 1e3;
5
- const EXEC_TIMEOUT_MS = Number.parseInt(process.env.DECISION_MACHINE_EXEC_TIMEOUT_MS ?? "", 10) || 2e3;
6
- const ARTIFACT_CACHE_TTL_MS = Number.parseInt(
7
- process.env.DECISION_MACHINE_ARTIFACT_CACHE_TTL_MS ?? "",
8
- 10
9
- ) || 5 * 60 * 1e3;
10
- const DEFAULT_DECISION = {
11
- decision: DecisionMachineDecision.Allow
12
- };
13
- const RequiredCountersSchema = z.array(CounterSpecSchema);
14
- class DecisionMachineRunner {
15
- constructor(db) {
16
- this.db = db;
17
- this.artifactCache = /* @__PURE__ */ new Map();
18
- }
19
- /** Build a cache key for a given scope + kind + dappAccount tuple. */
20
- static cacheKey(scope, kind, dappAccount) {
21
- return `${scope}:${kind}:${dappAccount ?? ""}`;
22
- }
23
- /** Return a cached artifact if still fresh, or undefined. */
24
- getCachedArtifact(scope, kind, dappAccount) {
25
- const entry = this.artifactCache.get(
26
- DecisionMachineRunner.cacheKey(scope, kind, dappAccount)
27
- );
28
- if (!entry) return null;
29
- if (Date.now() - entry.cachedAt > ARTIFACT_CACHE_TTL_MS) {
30
- this.artifactCache.delete(
31
- DecisionMachineRunner.cacheKey(scope, kind, dappAccount)
32
- );
33
- return null;
34
- }
35
- return entry.artifact;
36
- }
37
- /** Store an artifact (or undefined for negative cache) in the cache. */
38
- setCachedArtifact(scope, kind, dappAccount, artifact) {
39
- this.artifactCache.set(
40
- DecisionMachineRunner.cacheKey(scope, kind, dappAccount),
41
- {
42
- artifact,
43
- cachedAt: Date.now()
44
- }
45
- );
46
- }
47
- /**
48
- * Evaluates a single decision machine artifact and returns a decision.
49
- * Only one decision machine is selected and executed per request based on scope priority.
50
- *
51
- * @param input - The decision machine input containing user, dapp, and behavioral data
52
- * @param logger - Optional logger for warnings and errors
53
- * @returns A decision (allow/deny) with optional metadata
54
- */
55
- async decide(input, logger) {
56
- try {
57
- const artifact = await this.selectArtifact(
58
- input.dappAccount,
59
- DecisionMachineKind.Decision,
60
- input.captchaType
61
- );
62
- if (!artifact) {
63
- return DEFAULT_DECISION;
64
- }
65
- if (artifact.runtime !== DecisionMachineRuntime.Node) {
66
- logger?.warn?.(() => ({
67
- msg: "Unsupported decision machine runtime, defaulting to allow",
68
- data: { runtime: artifact.runtime }
69
- }));
70
- return DEFAULT_DECISION;
71
- }
72
- const decision = await this.runArtifactExport(
73
- artifact,
74
- ["decide", "default"],
75
- { input: { ...input, phase: input.phase ?? "verify" } },
76
- DecisionMachineOutputSchema
77
- );
78
- return decision ?? DEFAULT_DECISION;
79
- } catch (error) {
80
- logger?.error?.(() => ({
81
- msg: "Decision machine failed, defaulting to allow",
82
- err: error,
83
- data: { dappAccount: input.dappAccount }
84
- }));
85
- return DEFAULT_DECISION;
86
- }
87
- }
88
- /**
89
- * Routing phase: ask the configured machine which concrete captcha type to
90
- * serve. Returns undefined when no machine is configured, the machine has
91
- * no route export, the machine throws or times out, or the output fails
92
- * schema validation — caller should fall back to its baseline in any of
93
- * these cases.
94
- */
95
- async route(input, logger) {
96
- try {
97
- const artifact = await this.selectArtifact(
98
- input.dappAccount,
99
- DecisionMachineKind.Routing
100
- );
101
- if (!artifact) return void 0;
102
- if (artifact.runtime !== DecisionMachineRuntime.Node) {
103
- logger?.warn?.(() => ({
104
- msg: "Unsupported routing machine runtime, falling back to baseline",
105
- data: { runtime: artifact.runtime }
106
- }));
107
- return void 0;
108
- }
109
- return await this.runArtifactExport(
110
- artifact,
111
- ["route"],
112
- { input, optional: true },
113
- RoutingMachineOutputSchema
114
- );
115
- } catch (error) {
116
- logger?.error?.(() => ({
117
- msg: "Routing machine failed, falling back to baseline",
118
- err: error,
119
- data: { dappAccount: input.dappAccount }
120
- }));
121
- return void 0;
122
- }
123
- }
124
- /**
125
- * Pre-fetch hook: ask the configured machine which counters it needs read
126
- * into its input before {@link route} is invoked. Returns [] when no machine
127
- * is configured or it doesn't declare any.
128
- */
129
- async getRequiredCounters(input, logger) {
130
- try {
131
- const artifact = await this.selectArtifact(
132
- input.dappAccount,
133
- DecisionMachineKind.Routing
134
- );
135
- if (!artifact) return [];
136
- if (artifact.runtime !== DecisionMachineRuntime.Node) return [];
137
- const specs = await this.runArtifactExport(
138
- artifact,
139
- ["requiredCounters"],
140
- { input, optional: true },
141
- RequiredCountersSchema
142
- );
143
- return specs ?? [];
144
- } catch (error) {
145
- logger?.warn?.(() => ({
146
- msg: "requiredCounters() failed, proceeding with no counters",
147
- err: error,
148
- data: { dappAccount: input.dappAccount }
149
- }));
150
- return [];
151
- }
152
- }
153
- /**
154
- * Selects a single decision machine artifact based on scope priority.
155
- * Currently supports two scopes with the following priority:
156
- * 1. Dapp-specific: Custom decision machine for a specific dapp account
157
- * 2. Global: Default decision machine applied to all dapps
158
- *
159
- * Decision machines can optionally specify a captchaType filter:
160
- * - If artifact has no captchaType: runs on all captcha types
161
- * - If artifact has captchaType: only runs on matching captcha type
162
- *
163
- * @param dappAccount - The dapp account identifier to check for dapp-specific artifacts
164
- * @param captchaType - The captcha type to filter by (optional)
165
- * @returns The single highest-priority artifact, or undefined if none exists
166
- */
167
- async selectArtifact(dappAccount, kind, captchaType) {
168
- const cachedDapp = this.getCachedArtifact(
169
- DecisionMachineScope.Dapp,
170
- kind,
171
- dappAccount
172
- );
173
- const cachedGlobal = this.getCachedArtifact(
174
- DecisionMachineScope.Global,
175
- kind
176
- );
177
- if (cachedDapp !== null && cachedGlobal !== null) {
178
- if (cachedDapp && this.matchesCaptchaType(cachedDapp, captchaType)) {
179
- return cachedDapp;
180
- }
181
- if (cachedGlobal && this.matchesCaptchaType(cachedGlobal, captchaType)) {
182
- return cachedGlobal;
183
- }
184
- return void 0;
185
- }
186
- const [dappArtifact, globalArtifact] = await Promise.all([
187
- cachedDapp !== null ? Promise.resolve(cachedDapp) : this.db.getDecisionMachineArtifact(
188
- DecisionMachineScope.Dapp,
189
- dappAccount,
190
- kind
191
- ).then((a) => {
192
- this.setCachedArtifact(
193
- DecisionMachineScope.Dapp,
194
- kind,
195
- dappAccount,
196
- a ?? void 0
197
- );
198
- return a ?? void 0;
199
- }),
200
- cachedGlobal !== null ? Promise.resolve(cachedGlobal) : this.db.getDecisionMachineArtifact(
201
- DecisionMachineScope.Global,
202
- void 0,
203
- kind
204
- ).then((a) => {
205
- this.setCachedArtifact(
206
- DecisionMachineScope.Global,
207
- kind,
208
- void 0,
209
- a ?? void 0
210
- );
211
- return a ?? void 0;
212
- })
213
- ]);
214
- if (dappArtifact && this.matchesCaptchaType(dappArtifact, captchaType)) {
215
- return dappArtifact;
216
- }
217
- if (globalArtifact && this.matchesCaptchaType(globalArtifact, captchaType)) {
218
- return globalArtifact;
219
- }
220
- return void 0;
221
- }
222
- /**
223
- * Checks if a decision machine artifact matches the requested captcha type.
224
- * - If artifact has no captchaType filter: matches all captcha types
225
- * - If artifact has captchaType filter: only matches if types are equal
226
- *
227
- * @param artifact - The decision machine artifact to check
228
- * @param captchaType - The captcha type to match against (optional)
229
- * @returns True if the artifact should run for this captcha type
230
- */
231
- matchesCaptchaType(artifact, captchaType) {
232
- if (!artifact.captchaType) {
233
- return true;
234
- }
235
- return artifact.captchaType === captchaType;
236
- }
237
- /**
238
- * Load the artifact source into a fresh vm sandbox, locate a callable
239
- * matching one of {exportNames} (or `module.exports` itself if it's a
240
- * function), invoke it with {input}, and validate the result with
241
- * {schema}. Returns undefined when {options.optional} is true and no
242
- * matching export exists. Otherwise throws on missing export, invalid
243
- * output, or sandbox failure.
244
- */
245
- async runArtifactExport(artifact, exportNames, options, schema) {
246
- const sandbox = {
247
- module: { exports: {} },
248
- exports: {}
249
- };
250
- const context = vm.createContext(sandbox);
251
- const script = new vm.Script(artifact.source, {
252
- filename: "decision-machine.js"
253
- });
254
- script.runInContext(context, { timeout: LOAD_TIMEOUT_MS });
255
- const exported = sandbox.module.exports;
256
- const named = this.findExport(exported, exportNames);
257
- if (!named) {
258
- if (options.optional) return void 0;
259
- throw new Error(
260
- `Decision machine must export one of: ${exportNames.join(", ")}`
261
- );
262
- }
263
- const result = await this.withTimeout(
264
- Promise.resolve(named.fn(options.input)),
265
- EXEC_TIMEOUT_MS
266
- );
267
- const parsed = schema.safeParse(result);
268
- if (!parsed.success) {
269
- throw new Error(
270
- `Decision machine '${named.name}' output failed validation`
271
- );
272
- }
273
- return parsed.data;
274
- }
275
- findExport(exported, exportNames) {
276
- if (typeof exported === "function" && (exportNames.includes("default") || exportNames.includes("decide"))) {
277
- return {
278
- name: "default",
279
- fn: exported
280
- };
281
- }
282
- for (const name of exportNames) {
283
- const candidate = exported?.[name];
284
- if (typeof candidate === "function") {
285
- return { name, fn: candidate };
286
- }
287
- }
288
- return void 0;
289
- }
290
- async withTimeout(promise, timeoutMs) {
291
- let timeoutId;
292
- const timeoutPromise = new Promise((_, reject) => {
293
- timeoutId = setTimeout(
294
- () => reject(new Error("Decision machine timeout")),
295
- timeoutMs
296
- );
297
- });
298
- try {
299
- return await Promise.race([promise, timeoutPromise]);
300
- } finally {
301
- if (timeoutId) {
302
- clearTimeout(timeoutId);
303
- }
304
- }
305
- }
306
- }
307
- export {
308
- DecisionMachineRunner
4
+ //#region src/tasks/decisionMachine/decisionMachineRunner.ts
5
+ var LOAD_TIMEOUT_MS = Number.parseInt(process.env.DECISION_MACHINE_LOAD_TIMEOUT_MS ?? "", 10) || 1e3;
6
+ var EXEC_TIMEOUT_MS = Number.parseInt(process.env.DECISION_MACHINE_EXEC_TIMEOUT_MS ?? "", 10) || 2e3;
7
+ /** How long cached artifacts are considered fresh (ms). */
8
+ var ARTIFACT_CACHE_TTL_MS = Number.parseInt(process.env.DECISION_MACHINE_ARTIFACT_CACHE_TTL_MS ?? "", 10) || 300 * 1e3;
9
+ var DEFAULT_DECISION = { decision: DecisionMachineDecision.Allow };
10
+ var RequiredCountersSchema = z.array(CounterSpecSchema);
11
+ var DecisionMachineRunner = class DecisionMachineRunner {
12
+ constructor(db) {
13
+ this.db = db;
14
+ this.artifactCache = /* @__PURE__ */ new Map();
15
+ }
16
+ /** Build a cache key for a given scope + kind + dappAccount tuple. */
17
+ static cacheKey(scope, kind, dappAccount) {
18
+ return `${scope}:${kind}:${dappAccount ?? ""}`;
19
+ }
20
+ /** Return a cached artifact if still fresh, or undefined. */
21
+ getCachedArtifact(scope, kind, dappAccount) {
22
+ const entry = this.artifactCache.get(DecisionMachineRunner.cacheKey(scope, kind, dappAccount));
23
+ if (!entry) return null;
24
+ if (Date.now() - entry.cachedAt > ARTIFACT_CACHE_TTL_MS) {
25
+ this.artifactCache.delete(DecisionMachineRunner.cacheKey(scope, kind, dappAccount));
26
+ return null;
27
+ }
28
+ return entry.artifact;
29
+ }
30
+ /** Store an artifact (or undefined for negative cache) in the cache. */
31
+ setCachedArtifact(scope, kind, dappAccount, artifact) {
32
+ this.artifactCache.set(DecisionMachineRunner.cacheKey(scope, kind, dappAccount), {
33
+ artifact,
34
+ cachedAt: Date.now()
35
+ });
36
+ }
37
+ /**
38
+ * Evaluates a single decision machine artifact and returns a decision.
39
+ * Only one decision machine is selected and executed per request based on scope priority.
40
+ *
41
+ * @param input - The decision machine input containing user, dapp, and behavioral data
42
+ * @param logger - Optional logger for warnings and errors
43
+ * @returns A decision (allow/deny) with optional metadata
44
+ */
45
+ async decide(input, logger) {
46
+ try {
47
+ const artifact = await this.selectArtifact(input.dappAccount, DecisionMachineKind.Decision, input.captchaType);
48
+ if (!artifact) return DEFAULT_DECISION;
49
+ if (artifact.runtime !== DecisionMachineRuntime.Node) {
50
+ logger?.warn?.(() => ({
51
+ msg: "Unsupported decision machine runtime, defaulting to allow",
52
+ data: { runtime: artifact.runtime }
53
+ }));
54
+ return DEFAULT_DECISION;
55
+ }
56
+ return await this.runArtifactExport(artifact, ["decide", "default"], { input: {
57
+ ...input,
58
+ phase: input.phase ?? "verify"
59
+ } }, DecisionMachineOutputSchema) ?? DEFAULT_DECISION;
60
+ } catch (error) {
61
+ logger?.error?.(() => ({
62
+ msg: "Decision machine failed, defaulting to allow",
63
+ err: error,
64
+ data: { dappAccount: input.dappAccount }
65
+ }));
66
+ return DEFAULT_DECISION;
67
+ }
68
+ }
69
+ /**
70
+ * Routing phase: ask the configured machine which concrete captcha type to
71
+ * serve. Returns undefined when no machine is configured, the machine has
72
+ * no route export, the machine throws or times out, or the output fails
73
+ * schema validation — caller should fall back to its baseline in any of
74
+ * these cases.
75
+ */
76
+ async route(input, logger) {
77
+ try {
78
+ const artifact = await this.selectArtifact(input.dappAccount, DecisionMachineKind.Routing);
79
+ if (!artifact) return void 0;
80
+ if (artifact.runtime !== DecisionMachineRuntime.Node) {
81
+ logger?.warn?.(() => ({
82
+ msg: "Unsupported routing machine runtime, falling back to baseline",
83
+ data: { runtime: artifact.runtime }
84
+ }));
85
+ return;
86
+ }
87
+ return await this.runArtifactExport(artifact, ["route"], {
88
+ input,
89
+ optional: true
90
+ }, RoutingMachineOutputSchema);
91
+ } catch (error) {
92
+ logger?.error?.(() => ({
93
+ msg: "Routing machine failed, falling back to baseline",
94
+ err: error,
95
+ data: { dappAccount: input.dappAccount }
96
+ }));
97
+ return;
98
+ }
99
+ }
100
+ /**
101
+ * Pre-fetch hook: ask the configured machine which counters it needs read
102
+ * into its input before {@link route} is invoked. Returns [] when no machine
103
+ * is configured or it doesn't declare any.
104
+ */
105
+ async getRequiredCounters(input, logger) {
106
+ try {
107
+ const artifact = await this.selectArtifact(input.dappAccount, DecisionMachineKind.Routing);
108
+ if (!artifact) return [];
109
+ if (artifact.runtime !== DecisionMachineRuntime.Node) return [];
110
+ return await this.runArtifactExport(artifact, ["requiredCounters"], {
111
+ input,
112
+ optional: true
113
+ }, RequiredCountersSchema) ?? [];
114
+ } catch (error) {
115
+ logger?.warn?.(() => ({
116
+ msg: "requiredCounters() failed, proceeding with no counters",
117
+ err: error,
118
+ data: { dappAccount: input.dappAccount }
119
+ }));
120
+ return [];
121
+ }
122
+ }
123
+ /**
124
+ * Selects a single decision machine artifact based on scope priority.
125
+ * Currently supports two scopes with the following priority:
126
+ * 1. Dapp-specific: Custom decision machine for a specific dapp account
127
+ * 2. Global: Default decision machine applied to all dapps
128
+ *
129
+ * Decision machines can optionally specify a captchaType filter:
130
+ * - If artifact has no captchaType: runs on all captcha types
131
+ * - If artifact has captchaType: only runs on matching captcha type
132
+ *
133
+ * @param dappAccount - The dapp account identifier to check for dapp-specific artifacts
134
+ * @param captchaType - The captcha type to filter by (optional)
135
+ * @returns The single highest-priority artifact, or undefined if none exists
136
+ */
137
+ async selectArtifact(dappAccount, kind, captchaType) {
138
+ const cachedDapp = this.getCachedArtifact(DecisionMachineScope.Dapp, kind, dappAccount);
139
+ const cachedGlobal = this.getCachedArtifact(DecisionMachineScope.Global, kind);
140
+ if (cachedDapp !== null && cachedGlobal !== null) {
141
+ if (cachedDapp && this.matchesCaptchaType(cachedDapp, captchaType)) return cachedDapp;
142
+ if (cachedGlobal && this.matchesCaptchaType(cachedGlobal, captchaType)) return cachedGlobal;
143
+ return;
144
+ }
145
+ const [dappArtifact, globalArtifact] = await Promise.all([cachedDapp !== null ? Promise.resolve(cachedDapp) : this.db.getDecisionMachineArtifact(DecisionMachineScope.Dapp, dappAccount, kind).then((a) => {
146
+ this.setCachedArtifact(DecisionMachineScope.Dapp, kind, dappAccount, a ?? void 0);
147
+ return a ?? void 0;
148
+ }), cachedGlobal !== null ? Promise.resolve(cachedGlobal) : this.db.getDecisionMachineArtifact(DecisionMachineScope.Global, void 0, kind).then((a) => {
149
+ this.setCachedArtifact(DecisionMachineScope.Global, kind, void 0, a ?? void 0);
150
+ return a ?? void 0;
151
+ })]);
152
+ if (dappArtifact && this.matchesCaptchaType(dappArtifact, captchaType)) return dappArtifact;
153
+ if (globalArtifact && this.matchesCaptchaType(globalArtifact, captchaType)) return globalArtifact;
154
+ }
155
+ /**
156
+ * Checks if a decision machine artifact matches the requested captcha type.
157
+ * - If artifact has no captchaType filter: matches all captcha types
158
+ * - If artifact has captchaType filter: only matches if types are equal
159
+ *
160
+ * @param artifact - The decision machine artifact to check
161
+ * @param captchaType - The captcha type to match against (optional)
162
+ * @returns True if the artifact should run for this captcha type
163
+ */
164
+ matchesCaptchaType(artifact, captchaType) {
165
+ if (!artifact.captchaType) return true;
166
+ return artifact.captchaType === captchaType;
167
+ }
168
+ /**
169
+ * Load the artifact source into a fresh vm sandbox, locate a callable
170
+ * matching one of {exportNames} (or `module.exports` itself if it's a
171
+ * function), invoke it with {input}, and validate the result with
172
+ * {schema}. Returns undefined when {options.optional} is true and no
173
+ * matching export exists. Otherwise throws on missing export, invalid
174
+ * output, or sandbox failure.
175
+ */
176
+ async runArtifactExport(artifact, exportNames, options, schema) {
177
+ const sandbox = {
178
+ module: { exports: {} },
179
+ exports: {}
180
+ };
181
+ const context = vm.createContext(sandbox);
182
+ new vm.Script(artifact.source, { filename: "decision-machine.js" }).runInContext(context, { timeout: LOAD_TIMEOUT_MS });
183
+ const exported = sandbox.module.exports;
184
+ const named = this.findExport(exported, exportNames);
185
+ if (!named) {
186
+ if (options.optional) return void 0;
187
+ throw new Error(`Decision machine must export one of: ${exportNames.join(", ")}`);
188
+ }
189
+ const result = await this.withTimeout(Promise.resolve(named.fn(options.input)), EXEC_TIMEOUT_MS);
190
+ const parsed = schema.safeParse(result);
191
+ if (!parsed.success) throw new Error(`Decision machine '${named.name}' output failed validation`);
192
+ return parsed.data;
193
+ }
194
+ findExport(exported, exportNames) {
195
+ if (typeof exported === "function" && (exportNames.includes("default") || exportNames.includes("decide"))) return {
196
+ name: "default",
197
+ fn: exported
198
+ };
199
+ for (const name of exportNames) {
200
+ const candidate = exported?.[name];
201
+ if (typeof candidate === "function") return {
202
+ name,
203
+ fn: candidate
204
+ };
205
+ }
206
+ }
207
+ async withTimeout(promise, timeoutMs) {
208
+ let timeoutId;
209
+ const timeoutPromise = new Promise((_, reject) => {
210
+ timeoutId = setTimeout(() => reject(/* @__PURE__ */ new Error("Decision machine timeout")), timeoutMs);
211
+ });
212
+ try {
213
+ return await Promise.race([promise, timeoutPromise]);
214
+ } finally {
215
+ if (timeoutId) clearTimeout(timeoutId);
216
+ }
217
+ }
309
218
  };
219
+ //#endregion
220
+ export { DecisionMachineRunner };