@prosopo/provider 5.14.0 → 5.15.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 (134) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +20 -22
  2. package/.turbo/turbo-build$colon$tsc.log +27 -30
  3. package/.turbo/turbo-build.log +21 -26
  4. package/CHANGELOG.md +128 -0
  5. package/LICENSE +201 -0
  6. package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.d.ts +2 -1
  7. package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.d.ts.map +1 -1
  8. package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.js +11 -2
  9. package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.js.map +1 -1
  10. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.d.ts.map +1 -1
  11. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js +15 -8
  12. package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js.map +1 -1
  13. package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.d.ts +5 -0
  14. package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.d.ts.map +1 -0
  15. package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.js +20 -0
  16. package/dist/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.js.map +1 -0
  17. package/dist/api/captcha/getPuzzleCaptchaChallenge.d.ts.map +1 -1
  18. package/dist/api/captcha/getPuzzleCaptchaChallenge.js +24 -0
  19. package/dist/api/captcha/getPuzzleCaptchaChallenge.js.map +1 -1
  20. package/dist/api/captcha/submitPoWCaptchaSolution.d.ts +4 -11
  21. package/dist/api/captcha/submitPoWCaptchaSolution.d.ts.map +1 -1
  22. package/dist/api/captcha/submitPoWCaptchaSolution.js +12 -17
  23. package/dist/api/captcha/submitPoWCaptchaSolution.js.map +1 -1
  24. package/dist/api/rawTlsSignalsMiddleware.d.ts +14 -1
  25. package/dist/api/rawTlsSignalsMiddleware.d.ts.map +1 -1
  26. package/dist/api/rawTlsSignalsMiddleware.js +111 -23
  27. package/dist/api/rawTlsSignalsMiddleware.js.map +1 -1
  28. package/dist/api/startProviderApi.js +2 -2
  29. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/constants.cjs +10 -0
  30. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +14 -7
  31. package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.cjs +20 -0
  32. package/dist/cjs/api/captcha/getPuzzleCaptchaChallenge.cjs +24 -0
  33. package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +10 -15
  34. package/dist/cjs/api/rawTlsSignalsMiddleware.cjs +111 -22
  35. package/dist/cjs/api/startProviderApi.cjs +2 -2
  36. package/dist/cjs/compositeIpAddress.cjs +21 -7
  37. package/dist/cjs/tasks/captchaManager.cjs +15 -0
  38. package/dist/cjs/tasks/captchaTypeSelection.cjs +23 -2
  39. package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +26 -23
  40. package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +2 -9
  41. package/dist/cjs/tasks/powCaptcha/powTasks.cjs +7 -11
  42. package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +2 -0
  43. package/dist/cjs/tasks/puzzle/backgroundBuffer.cjs +3 -3
  44. package/dist/cjs/tasks/puzzle/nativeBackground.cjs +12 -5
  45. package/dist/cjs/tasks/puzzle/puzzleRenderer.cjs +4 -3
  46. package/dist/cjs/tasks/puzzleCaptcha/puzzleTasks.cjs +2 -9
  47. package/dist/compositeIpAddress.d.ts.map +1 -1
  48. package/dist/compositeIpAddress.js +21 -7
  49. package/dist/compositeIpAddress.js.map +1 -1
  50. package/dist/tasks/captchaManager.d.ts.map +1 -1
  51. package/dist/tasks/captchaManager.js +16 -1
  52. package/dist/tasks/captchaManager.js.map +1 -1
  53. package/dist/tasks/captchaTypeSelection.d.ts +3 -1
  54. package/dist/tasks/captchaTypeSelection.d.ts.map +1 -1
  55. package/dist/tasks/captchaTypeSelection.js +23 -3
  56. package/dist/tasks/captchaTypeSelection.js.map +1 -1
  57. package/dist/tasks/frictionless/frictionlessTasks.d.ts +3 -1
  58. package/dist/tasks/frictionless/frictionlessTasks.d.ts.map +1 -1
  59. package/dist/tasks/frictionless/frictionlessTasks.js +28 -25
  60. package/dist/tasks/frictionless/frictionlessTasks.js.map +1 -1
  61. package/dist/tasks/frictionless/routingMachine.d.ts +1 -2
  62. package/dist/tasks/frictionless/routingMachine.d.ts.map +1 -1
  63. package/dist/tasks/frictionless/routingMachine.js.map +1 -1
  64. package/dist/tasks/imgCaptcha/imgCaptchaTasks.d.ts.map +1 -1
  65. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +2 -9
  66. package/dist/tasks/imgCaptcha/imgCaptchaTasks.js.map +1 -1
  67. package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
  68. package/dist/tasks/powCaptcha/powTasks.js +8 -12
  69. package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
  70. package/dist/tasks/powCaptcha/powTasksUtils.d.ts +1 -0
  71. package/dist/tasks/powCaptcha/powTasksUtils.d.ts.map +1 -1
  72. package/dist/tasks/powCaptcha/powTasksUtils.js +2 -1
  73. package/dist/tasks/powCaptcha/powTasksUtils.js.map +1 -1
  74. package/dist/tasks/puzzle/backgroundBuffer.d.ts +3 -2
  75. package/dist/tasks/puzzle/backgroundBuffer.d.ts.map +1 -1
  76. package/dist/tasks/puzzle/backgroundBuffer.js +3 -3
  77. package/dist/tasks/puzzle/backgroundBuffer.js.map +1 -1
  78. package/dist/tasks/puzzle/nativeBackground.d.ts +5 -1
  79. package/dist/tasks/puzzle/nativeBackground.d.ts.map +1 -1
  80. package/dist/tasks/puzzle/nativeBackground.js +12 -5
  81. package/dist/tasks/puzzle/nativeBackground.js.map +1 -1
  82. package/dist/tasks/puzzle/puzzleRenderer.d.ts +2 -0
  83. package/dist/tasks/puzzle/puzzleRenderer.d.ts.map +1 -1
  84. package/dist/tasks/puzzle/puzzleRenderer.js +4 -3
  85. package/dist/tasks/puzzle/puzzleRenderer.js.map +1 -1
  86. package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts.map +1 -1
  87. package/dist/tasks/puzzleCaptcha/puzzleTasks.js +2 -9
  88. package/dist/tasks/puzzleCaptcha/puzzleTasks.js.map +1 -1
  89. package/dist/tests/integration/clientSettingsPersistence.integration.test.js +2 -0
  90. package/dist/tests/integration/clientSettingsPersistence.integration.test.js.map +1 -1
  91. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/constants.unit.test.js +35 -2
  92. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/constants.unit.test.js.map +1 -1
  93. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.d.ts +2 -0
  94. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.d.ts.map +1 -0
  95. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.js +45 -0
  96. package/dist/tests/unit/api/captcha/getFrictionlessCaptchaChallenge/refreshLineage.unit.test.js.map +1 -0
  97. package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.js +15 -1
  98. package/dist/tests/unit/api/captcha/submitPoWCaptchaSolution.escalation.unit.test.js.map +1 -1
  99. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +148 -0
  100. package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
  101. package/dist/tests/unit/api/rawTlsSignalsMiddleware.unit.test.js +96 -1
  102. package/dist/tests/unit/api/rawTlsSignalsMiddleware.unit.test.js.map +1 -1
  103. package/dist/tests/unit/compositeIpAddress.unit.test.js +12 -3
  104. package/dist/tests/unit/compositeIpAddress.unit.test.js.map +1 -1
  105. package/dist/tests/unit/tasks/captchaManager.unit.test.js +51 -0
  106. package/dist/tests/unit/tasks/captchaManager.unit.test.js.map +1 -1
  107. package/dist/tests/unit/tasks/captchaTypeSelection.unit.test.js +20 -1
  108. package/dist/tests/unit/tasks/captchaTypeSelection.unit.test.js.map +1 -1
  109. package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.d.ts +2 -0
  110. package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.d.ts.map +1 -0
  111. package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.js +94 -0
  112. package/dist/tests/unit/tasks/frictionless/allowedCaptchaTypes.unit.test.js.map +1 -0
  113. package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.d.ts +2 -0
  114. package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.d.ts.map +1 -0
  115. package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.js +103 -0
  116. package/dist/tests/unit/tasks/frictionless/refreshSwitch.unit.test.js.map +1 -0
  117. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js +23 -1
  118. package/dist/tests/unit/tasks/powCaptcha/powTasksUtils.unit.test.js.map +1 -1
  119. package/dist/tests/unit/tasks/puzzle/backgroundBuffer.unit.test.js +1 -4
  120. package/dist/tests/unit/tasks/puzzle/backgroundBuffer.unit.test.js.map +1 -1
  121. package/dist/tests/unit/tasks/puzzle/nativeBackground.unit.test.js +10 -3
  122. package/dist/tests/unit/tasks/puzzle/nativeBackground.unit.test.js.map +1 -1
  123. package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.d.ts +2 -0
  124. package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.d.ts.map +1 -0
  125. package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.js +35 -0
  126. package/dist/tests/unit/tasks/puzzle/puzzleRenderer.unit.test.js.map +1 -0
  127. package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.d.ts +2 -0
  128. package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.d.ts.map +1 -0
  129. package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.js +49 -0
  130. package/dist/tests/unit/tasks/puzzleDifficultyDeviceCap.unit.test.js.map +1 -0
  131. package/dist/tests/unit/testUtils/mockProviderEnv.d.ts +17 -14
  132. package/dist/tests/unit/testUtils/mockProviderEnv.d.ts.map +1 -1
  133. package/dist/tests/unit/testUtils/mockProviderEnv.js.map +1 -1
  134. package/package.json +105 -103
@@ -7,9 +7,44 @@ var HEADER_ACK_NS = "x-tls-ack-ns";
7
7
  var HEADER_OBSERVED_TTL = "x-tls-observed-ttl";
8
8
  var HEADER_TCP_MSS = "x-tls-tcp-mss";
9
9
  var HEADER_TCP_WSCALE = "x-tls-tcp-wscale";
10
+ var HEADER_TCP_WINDOW = "x-tls-tcp-window";
11
+ var HEADER_TCP_OPTS_KINDS = "x-tls-tcp-opts-kinds";
12
+ var HEADER_TCP_OPTS_PRESENT = "x-tls-tcp-opts-present";
13
+ var HEADER_TCP_OPTS_COUNT = "x-tls-tcp-opts-count";
14
+ var HEADER_TCP_TSVAL = "x-tls-tcp-tsval";
15
+ var HEADER_TCP_TSECR = "x-tls-tcp-tsecr";
16
+ var HEADER_TCP_FLAGS = "x-tls-tcp-flags";
17
+ var HEADER_TCP_DATA_OFFSET_RESV = "x-tls-tcp-data-offset-resv";
18
+ var HEADER_TCP_URG_PTR = "x-tls-tcp-urg-ptr";
19
+ var HEADER_IP_IDENT = "x-tls-ip-ident";
20
+ var HEADER_IP_TOTAL_LEN = "x-tls-ip-total-len";
21
+ var HEADER_IP_FRAG_FLAGS = "x-tls-ip-frag-flags";
22
+ var HEADER_IP_TOS = "x-tls-ip-tos";
10
23
  var HEADER_TCP_OPTS_FLAGS = "x-tls-tcp-opts-flags";
11
24
  var HEADER_TCP_OPTS_ORDER = "x-tls-tcp-opts-order";
12
- var HEADER_TCP_WINDOW = "x-tls-tcp-window";
25
+ var RAW_TLS_SIGNAL_KEYS = [
26
+ "synNs",
27
+ "synackNs",
28
+ "ackNs",
29
+ "observedTtl",
30
+ "tcpMss",
31
+ "tcpWscale",
32
+ "tcpWindow",
33
+ "tcpOptsKinds",
34
+ "tcpOptsPresent",
35
+ "tcpOptsCount",
36
+ "tcpTsval",
37
+ "tcpTsecr",
38
+ "tcpFlags",
39
+ "tcpDataOffsetResv",
40
+ "tcpUrgPtr",
41
+ "ipIdent",
42
+ "ipTotalLen",
43
+ "ipFragFlags",
44
+ "ipTos",
45
+ "tcpOptsFlags",
46
+ "tcpOptsOrder"
47
+ ];
13
48
  var parseIntHeader = (raw, logger, headerName, max) => {
14
49
  if (raw === void 0) return;
15
50
  const value = Array.isArray(raw) ? raw[0] : raw;
@@ -31,6 +66,46 @@ var MAX_NS = 2 ** 63;
31
66
  var MAX_U8 = 255;
32
67
  var MAX_U16 = 65535;
33
68
  var MAX_U32 = 4294967295;
69
+ var OPTS_KINDS_SLOTS = 8;
70
+ var MAX_U64 = (1n << 64n) - 1n;
71
+ var parseOptsKindsHeader = (raw, logger) => {
72
+ if (raw === void 0) return;
73
+ const value = Array.isArray(raw) ? raw[0] : raw;
74
+ if (value === void 0 || !/^\d+$/.test(value)) {
75
+ if (value !== void 0) logger.debug(() => ({
76
+ msg: "Ignoring malformed raw TLS signal header",
77
+ data: {
78
+ header: HEADER_TCP_OPTS_KINDS,
79
+ raw: value
80
+ }
81
+ }));
82
+ return;
83
+ }
84
+ let packed;
85
+ try {
86
+ packed = BigInt(value);
87
+ } catch {
88
+ return;
89
+ }
90
+ if (packed > MAX_U64) {
91
+ logger.debug(() => ({
92
+ msg: "Ignoring out-of-range raw TLS signal header",
93
+ data: {
94
+ header: HEADER_TCP_OPTS_KINDS,
95
+ raw: value
96
+ }
97
+ }));
98
+ return;
99
+ }
100
+ if (packed === 0n) return;
101
+ const kinds = [];
102
+ for (let slot = 0; slot < OPTS_KINDS_SLOTS; slot++) {
103
+ const kind = Number(packed >> BigInt(slot * 8) & 255n);
104
+ if (kind === 0) break;
105
+ kinds.push(kind);
106
+ }
107
+ return kinds.length > 0 ? kinds : void 0;
108
+ };
34
109
  var getRawTlsSignals = (headers, logger) => {
35
110
  const log = logger ?? (0, _prosopo_logger.getLogger)("info", "provider:raw-tls-signals");
36
111
  return {
@@ -40,37 +115,50 @@ var getRawTlsSignals = (headers, logger) => {
40
115
  observedTtl: parseIntHeader(headers[HEADER_OBSERVED_TTL], log, HEADER_OBSERVED_TTL, MAX_U8),
41
116
  tcpMss: parseIntHeader(headers[HEADER_TCP_MSS], log, HEADER_TCP_MSS, MAX_U16),
42
117
  tcpWscale: parseIntHeader(headers[HEADER_TCP_WSCALE], log, HEADER_TCP_WSCALE, MAX_U8),
118
+ tcpWindow: parseIntHeader(headers[HEADER_TCP_WINDOW], log, HEADER_TCP_WINDOW, MAX_U16),
119
+ tcpOptsKinds: parseOptsKindsHeader(headers[HEADER_TCP_OPTS_KINDS], log),
120
+ tcpOptsPresent: parseIntHeader(headers[HEADER_TCP_OPTS_PRESENT], log, HEADER_TCP_OPTS_PRESENT, MAX_U16),
121
+ tcpOptsCount: parseIntHeader(headers[HEADER_TCP_OPTS_COUNT], log, HEADER_TCP_OPTS_COUNT, MAX_U8),
122
+ tcpTsval: parseIntHeader(headers[HEADER_TCP_TSVAL], log, HEADER_TCP_TSVAL, MAX_U32),
123
+ tcpTsecr: parseIntHeader(headers[HEADER_TCP_TSECR], log, HEADER_TCP_TSECR, MAX_U32),
124
+ tcpFlags: parseIntHeader(headers[HEADER_TCP_FLAGS], log, HEADER_TCP_FLAGS, MAX_U8),
125
+ tcpDataOffsetResv: parseIntHeader(headers[HEADER_TCP_DATA_OFFSET_RESV], log, HEADER_TCP_DATA_OFFSET_RESV, MAX_U8),
126
+ tcpUrgPtr: parseIntHeader(headers[HEADER_TCP_URG_PTR], log, HEADER_TCP_URG_PTR, MAX_U16),
127
+ ipIdent: parseIntHeader(headers[HEADER_IP_IDENT], log, HEADER_IP_IDENT, MAX_U16),
128
+ ipTotalLen: parseIntHeader(headers[HEADER_IP_TOTAL_LEN], log, HEADER_IP_TOTAL_LEN, MAX_U16),
129
+ ipFragFlags: parseIntHeader(headers[HEADER_IP_FRAG_FLAGS], log, HEADER_IP_FRAG_FLAGS, MAX_U16),
130
+ ipTos: parseIntHeader(headers[HEADER_IP_TOS], log, HEADER_IP_TOS, MAX_U8),
43
131
  tcpOptsFlags: parseIntHeader(headers[HEADER_TCP_OPTS_FLAGS], log, HEADER_TCP_OPTS_FLAGS, MAX_U8),
44
- tcpOptsOrder: parseIntHeader(headers[HEADER_TCP_OPTS_ORDER], log, HEADER_TCP_OPTS_ORDER, MAX_U32),
45
- tcpWindow: parseIntHeader(headers[HEADER_TCP_WINDOW], log, HEADER_TCP_WINDOW, MAX_U16)
132
+ tcpOptsOrder: parseIntHeader(headers[HEADER_TCP_OPTS_ORDER], log, HEADER_TCP_OPTS_ORDER, MAX_U32)
46
133
  };
47
134
  };
48
- var rawTlsSignalsForSession = (req) => {
135
+ var rawTlsSignalsForSession = (req) => rawTlsSignalsFromRecord(req);
136
+ /**
137
+ * Pull the raw TLS signals out of a persisted Session — or anything shaped
138
+ * like one — for a decision machine's `raw` bag, or to carry forward onto a
139
+ * new Session record.
140
+ *
141
+ * Six call sites used to name every field by hand, so adding one to the
142
+ * probe meant remembering six places; the fields that were forgotten read as
143
+ * `undefined` and the rules gating on them silently never fired.
144
+ */
145
+ var rawTlsSignalsFromRecord = (record) => {
49
146
  const out = {};
50
- if (req.synNs !== void 0) out.synNs = req.synNs;
51
- if (req.synackNs !== void 0) out.synackNs = req.synackNs;
52
- if (req.ackNs !== void 0) out.ackNs = req.ackNs;
53
- if (req.observedTtl !== void 0) out.observedTtl = req.observedTtl;
54
- if (req.tcpMss !== void 0) out.tcpMss = req.tcpMss;
55
- if (req.tcpWscale !== void 0) out.tcpWscale = req.tcpWscale;
56
- if (req.tcpOptsFlags !== void 0) out.tcpOptsFlags = req.tcpOptsFlags;
57
- if (req.tcpOptsOrder !== void 0) out.tcpOptsOrder = req.tcpOptsOrder;
58
- if (req.tcpWindow !== void 0) out.tcpWindow = req.tcpWindow;
147
+ if (!record) return out;
148
+ for (const key of RAW_TLS_SIGNAL_KEYS) {
149
+ const value = record[key];
150
+ if (value !== void 0) Object.assign(out, { [key]: value });
151
+ }
59
152
  return out;
60
153
  };
61
154
  var rawTlsSignalsMiddleware = (env) => {
62
155
  return async (req, res, next) => {
63
156
  try {
64
157
  const signals = getRawTlsSignals(req.headers, req.logger);
65
- if (signals.synNs !== void 0) req.synNs = signals.synNs;
66
- if (signals.synackNs !== void 0) req.synackNs = signals.synackNs;
67
- if (signals.ackNs !== void 0) req.ackNs = signals.ackNs;
68
- if (signals.observedTtl !== void 0) req.observedTtl = signals.observedTtl;
69
- if (signals.tcpMss !== void 0) req.tcpMss = signals.tcpMss;
70
- if (signals.tcpWscale !== void 0) req.tcpWscale = signals.tcpWscale;
71
- if (signals.tcpOptsFlags !== void 0) req.tcpOptsFlags = signals.tcpOptsFlags;
72
- if (signals.tcpOptsOrder !== void 0) req.tcpOptsOrder = signals.tcpOptsOrder;
73
- if (signals.tcpWindow !== void 0) req.tcpWindow = signals.tcpWindow;
158
+ for (const key of RAW_TLS_SIGNAL_KEYS) {
159
+ const value = signals[key];
160
+ if (value !== void 0) Object.assign(req, { [key]: value });
161
+ }
74
162
  if (Object.values(signals).some((v) => v !== void 0)) req.logger = req.logger.with(signals, "rawTlsSignals");
75
163
  next();
76
164
  } catch (err) {
@@ -81,4 +169,5 @@ var rawTlsSignalsMiddleware = (env) => {
81
169
  //#endregion
82
170
  exports.getRawTlsSignals = getRawTlsSignals;
83
171
  exports.rawTlsSignalsForSession = rawTlsSignalsForSession;
172
+ exports.rawTlsSignalsFromRecord = rawTlsSignalsFromRecord;
84
173
  exports.rawTlsSignalsMiddleware = rawTlsSignalsMiddleware;
@@ -1,9 +1,9 @@
1
1
  const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
2
  const require_metrics = require("./metrics.cjs");
3
+ const require_rawTlsSignalsMiddleware = require("./rawTlsSignalsMiddleware.cjs");
3
4
  const require_blacklistRequestInspector = require("./blacklistRequestInspector.cjs");
4
5
  const require_bundlePool = require("../tasks/detection/bundlePool.cjs");
5
6
  const require_block = require("./block.cjs");
6
- const require_rawTlsSignalsMiddleware = require("./rawTlsSignalsMiddleware.cjs");
7
7
  const require_captcha = require("./captcha.cjs");
8
8
  const require_verify = require("./verify.cjs");
9
9
  const require_ja4Middleware = require("./ja4Middleware.cjs");
@@ -20,13 +20,13 @@ const require_ipInfoMiddleware = require("./ipInfoMiddleware.cjs");
20
20
  const require_robotsMiddleware = require("./robotsMiddleware.cjs");
21
21
  let _prosopo_logger = require("@prosopo/logger");
22
22
  let _prosopo_types = require("@prosopo/types");
23
+ let _prosopo_api_express_router = require("@prosopo/api-express-router");
23
24
  let node_fs = require("node:fs");
24
25
  node_fs = require_runtime.__toESM(node_fs, 1);
25
26
  let node_path = require("node:path");
26
27
  node_path = require_runtime.__toESM(node_path, 1);
27
28
  let node_https = require("node:https");
28
29
  node_https = require_runtime.__toESM(node_https, 1);
29
- let _prosopo_api_express_router = require("@prosopo/api-express-router");
30
30
  let express = require("express");
31
31
  express = require_runtime.__toESM(express, 1);
32
32
  let node_url = require("node:url");
@@ -4,6 +4,11 @@ let ip_address = require("ip-address");
4
4
  //#region src/compositeIpAddress.ts
5
5
  var V6_SHIFT = 64n;
6
6
  var v6_LOWER_MASK = (1n << V6_SHIFT) - 1n;
7
+ /**
8
+ * The part of a v4 address treated as the host rather than the network, for
9
+ * the purposes of `isSameIpOrigin`. 8 bits — a /24.
10
+ */
11
+ var V4_HOST_BITS = 8n;
7
12
  var getCompositeIpAddress = (ip) => {
8
13
  let ipAddress;
9
14
  try {
@@ -60,10 +65,19 @@ var isUnknownIp = (ip) => ip.type === _prosopo_types.IpAddressType.v4 && readPar
60
65
  /**
61
66
  * Do two observations of a client come from the same place on the network?
62
67
  *
63
- * v4 is compared exactly. v6 is compared on the /64 prefix alone — the
64
- * interface identifier in the low 64 bits is designed to rotate (RFC 8981
65
- * privacy extensions), often several times a day on one unchanged connection,
66
- * so comparing it would call an ordinary phone a different host.
68
+ * Both families are compared on the network part and neither on the host part.
69
+ *
70
+ * v6 is the /64 prefix: the interface identifier in the low 64 bits is designed
71
+ * to rotate (RFC 8981 privacy extensions), often several times a day on one
72
+ * unchanged connection, so comparing it would call an ordinary phone a
73
+ * different host.
74
+ *
75
+ * v4 is the /24. A carrier NAT or mobile pool reassigns the low octet mid
76
+ * session — an EE subscriber was observed moving one address in four seconds —
77
+ * so comparing the whole address called every rotating mobile and CGNAT client
78
+ * a different host, which is the opposite of the leniency this check is for.
79
+ * The /24 still separates an unrelated network, which is the case worth
80
+ * catching: a challenge handed to a second host to farm the work out.
67
81
  *
68
82
  * A value we do not actually have counts as the same — one that will not
69
83
  * parse, or the all-zero v4 `getCompositeIpAddress` returns when handed an
@@ -73,13 +87,13 @@ var isUnknownIp = (ip) => ip.type === _prosopo_types.IpAddressType.v4 && readPar
73
87
  var isSameIpOrigin = (a, b) => {
74
88
  if (isUnknownIp(a) || isUnknownIp(b)) return true;
75
89
  if (a.type !== b.type) return false;
76
- const compare = (left, right) => {
90
+ const sameNetwork = (left, right, hostBits) => {
77
91
  const leftPart = readPart(left);
78
92
  const rightPart = readPart(right);
79
93
  if (leftPart === void 0 || rightPart === void 0) return true;
80
- return leftPart === rightPart;
94
+ return leftPart >> hostBits === rightPart >> hostBits;
81
95
  };
82
- return a.type === _prosopo_types.IpAddressType.v6 ? compare(a.upper, b.upper) : compare(a.lower, b.lower);
96
+ return a.type === _prosopo_types.IpAddressType.v6 ? sameNetwork(a.upper, b.upper, 0n) : sameNetwork(a.lower, b.lower, V4_HOST_BITS);
83
97
  };
84
98
  var never = () => {
85
99
  throw new Error("Unhandled type");
@@ -225,6 +225,21 @@ var CaptchaManager = class CaptchaManager {
225
225
  sessionId
226
226
  }
227
227
  }));
228
+ if (!(0, _prosopo_types.isCaptchaTypeFeatureEnabled)(requestedCaptchaType, clientSettings.settings?.captchaTypeFeatureFlags)) {
229
+ this.logger.warn(() => ({
230
+ msg: "Captcha type is switched off for this site",
231
+ data: {
232
+ account: clientSettings.account,
233
+ requestedCaptchaType,
234
+ sessionId
235
+ }
236
+ }));
237
+ return {
238
+ valid: false,
239
+ reason: _prosopo_types.ResultReason.INCORRECT_CAPTCHA_TYPE,
240
+ type: requestedCaptchaType
241
+ };
242
+ }
228
243
  if (sessionId) {
229
244
  const cachedBeforeRemove = this.writeQueue ? await this.writeQueue.getCachedSession(sessionId) : null;
230
245
  const cachedHash = typeof cachedBeforeRemove?.userSitekeyIpHash === "string" ? cachedBeforeRemove.userSitekeyIpHash : void 0;
@@ -18,12 +18,16 @@ let _prosopo_types = require("@prosopo/types");
18
18
  * Restrict rules, traffic-filter category policies, routing-machine actions
19
19
  * and detector-generated rules.
20
20
  *
21
+ * Pass `allowedTypes` from `resolveAllowedCaptchaTypes`, so Prosopo's
22
+ * per-site captcha type feature flags are applied alongside the site owner's
23
+ * own `frictionlessTypes`. Absent means every type is allowed.
24
+ *
21
25
  * Coercion only ever narrows. A disabled type falls back to the other
22
26
  * interactive type if that is permitted, and to PoW otherwise — never the
23
27
  * reverse, so this can't hand a user a harder challenge than was asked for.
24
28
  */
25
- var coerceToEnabledCaptchaType = (requested, frictionlessTypes, logger) => {
26
- const types = (0, _prosopo_types.resolveFrictionlessTypes)(frictionlessTypes);
29
+ var coerceToEnabledCaptchaType = (requested, allowedTypes, logger) => {
30
+ const types = (0, _prosopo_types.resolveFrictionlessTypes)(allowedTypes);
27
31
  const puzzleAllowed = types.puzzle && require_puzzleRenderer.isPuzzleRenderAvailable();
28
32
  const imageAllowed = types.image;
29
33
  const resolved = (() => {
@@ -49,5 +53,22 @@ var coerceToEnabledCaptchaType = (requested, frictionlessTypes, logger) => {
49
53
  }));
50
54
  return resolved;
51
55
  };
56
+ /**
57
+ * Swap a puzzle for an image challenge once the user has refreshed it
58
+ * `PUZZLE_REFRESHES_BEFORE_IMAGE` times in a row.
59
+ *
60
+ * A user who keeps refreshing either cannot solve this kind of puzzle or is a
61
+ * solver shopping for an easy instance. The image challenge answers both.
62
+ *
63
+ * The refresh count is client-reported, so this only moves one way: from
64
+ * puzzle to image, never back. Lying about it can only earn a harder
65
+ * challenge. Leaving it out looks like a fresh visit, which is what a page
66
+ * reload already gets.
67
+ *
68
+ * A site that has not enabled image keeps its puzzle. Serving a type the site
69
+ * turned off is exactly what `coerceToEnabledCaptchaType` exists to stop.
70
+ */
71
+ var switchTypeAfterRefreshes = (resolved, refreshCount, allowedTypes) => _prosopo_types.CaptchaType.puzzle === resolved && (refreshCount ?? 0) >= 3 && (0, _prosopo_types.resolveFrictionlessTypes)(allowedTypes).image ? _prosopo_types.CaptchaType.image : resolved;
52
72
  //#endregion
53
73
  exports.coerceToEnabledCaptchaType = coerceToEnabledCaptchaType;
74
+ exports.switchTypeAfterRefreshes = switchTypeAfterRefreshes;
@@ -1,6 +1,7 @@
1
1
  const require_usageCounters = require("../../util/usageCounters.cjs");
2
2
  const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
3
3
  const require_dnsEventUrl = require("../../api/dnsEventUrl.cjs");
4
+ const require_rawTlsSignalsMiddleware = require("../../api/rawTlsSignalsMiddleware.cjs");
4
5
  const require_lang = require("../../rules/lang.cjs");
5
6
  const require_clientMetaData = require("../../utils/clientMetaData.cjs");
6
7
  const require_captchaManager = require("../captchaManager.cjs");
@@ -33,6 +34,15 @@ var FrictionlessManager = class extends require_captchaManager.CaptchaManager {
33
34
  this.routingContext = ctx;
34
35
  }
35
36
  /**
37
+ * The types this site may be served, from `resolveAllowedCaptchaTypes`.
38
+ * Set before any path can mint a session, including the short-circuits
39
+ * that skip routing, so the site's feature flags hold on every path.
40
+ * Unset means every type is allowed.
41
+ */
42
+ setAllowedCaptchaTypes(allowed) {
43
+ this.allowedCaptchaTypes = allowed;
44
+ }
45
+ /**
36
46
  * Evaluate the configured routing machine without going through
37
47
  * `sendCaptcha`. Returns the supplied baseline on any failure (no machine,
38
48
  * machine throws, counter fetch failure), matching applyRouter's contract.
@@ -63,15 +73,10 @@ var FrictionlessManager = class extends require_captchaManager.CaptchaManager {
63
73
  d: params.d,
64
74
  tcpToChelloUs: params.tcpToChelloUs,
65
75
  chelloToHandshakeUs: params.chelloToHandshakeUs,
66
- synNs: params.synNs,
67
- synackNs: params.synackNs,
68
- ackNs: params.ackNs,
69
- observedTtl: params.observedTtl,
70
- tcpMss: params.tcpMss,
71
- tcpWscale: params.tcpWscale,
72
- tcpOptsFlags: params.tcpOptsFlags,
73
- tcpOptsOrder: params.tcpOptsOrder,
74
- tcpWindow: params.tcpWindow
76
+ ...require_rawTlsSignalsMiddleware.rawTlsSignalsFromRecord(params),
77
+ refreshOf: params.refreshOf,
78
+ refreshCount: params.refreshCount,
79
+ refreshedAfterMs: params.refreshedAfterMs
75
80
  };
76
81
  }
77
82
  /**
@@ -91,7 +96,7 @@ var FrictionlessManager = class extends require_captchaManager.CaptchaManager {
91
96
  return require_lang.checkLangRules(this.config, acceptLanguage);
92
97
  }
93
98
  async createSession(input) {
94
- const { token, score, threshold, scoreComponents, ipAddress, captchaType, siteKey, mode, solvedImagesCount, powDifficulty, userSitekeyIpHash, reason, blocked, deleted, ipInfo, headers, bundleId, currentUrl, iframeUrl, d, tcpToChelloUs, chelloToHandshakeUs, synNs, synackNs, ackNs, observedTtl, tcpMss, tcpWscale, tcpOptsFlags, tcpOptsOrder, tcpWindow, simdReadings, puzzleTolerance, puzzle, isEscalation, originSessionId, isProtect, matchedRule, clientMetaData, webView = false, iFrame = false, decryptedHeadHash = "" } = input;
99
+ const { token, score, threshold, scoreComponents, ipAddress, captchaType, siteKey, mode, solvedImagesCount, powDifficulty, userSitekeyIpHash, reason, blocked, deleted, ipInfo, headers, bundleId, currentUrl, iframeUrl, d, tcpToChelloUs, chelloToHandshakeUs, simdReadings, puzzleTolerance, puzzle, isEscalation, originSessionId, refreshOf, refreshCount, refreshedAfterMs, isProtect, matchedRule, clientMetaData, webView = false, iFrame = false, decryptedHeadHash = "" } = input;
95
100
  const sessionRecord = {
96
101
  sessionId: `${getSessionIDPrefix(this.config.host)}-${(0, uuid.v4)()}`,
97
102
  createdAt: /* @__PURE__ */ new Date(),
@@ -111,6 +116,9 @@ var FrictionlessManager = class extends require_captchaManager.CaptchaManager {
111
116
  iFrame,
112
117
  ...isEscalation && { isEscalation: true },
113
118
  ...originSessionId && { originSessionId },
119
+ ...refreshOf && { refreshOf },
120
+ ...refreshCount !== void 0 && { refreshCount },
121
+ ...refreshedAfterMs !== void 0 && { refreshedAfterMs },
114
122
  decryptedHeadHash,
115
123
  bundleId,
116
124
  reason,
@@ -127,15 +135,7 @@ var FrictionlessManager = class extends require_captchaManager.CaptchaManager {
127
135
  d,
128
136
  tcpToChelloUs,
129
137
  chelloToHandshakeUs,
130
- synNs,
131
- synackNs,
132
- ackNs,
133
- observedTtl,
134
- tcpMss,
135
- tcpWscale,
136
- tcpOptsFlags,
137
- tcpOptsOrder,
138
- tcpWindow,
138
+ ...require_rawTlsSignalsMiddleware.rawTlsSignalsFromRecord(input),
139
139
  ...matchedRule && { matchedRule },
140
140
  ...clientMetaData && { clientMetaData }
141
141
  };
@@ -247,14 +247,16 @@ var FrictionlessManager = class extends require_captchaManager.CaptchaManager {
247
247
  powDifficulty: captchaType === _prosopo_types.CaptchaType.pow ? effectiveParams.powDifficulty : void 0
248
248
  };
249
249
  const routed = this.routingContext ? await require_routingMachine.applyRouter(this.decisionMachineRunner, this.usageCounters, baseline, this.routingContext, this.logger) : baseline;
250
- const finalCaptchaType = require_captchaTypeSelection.coerceToEnabledCaptchaType(routed.captchaType, this.routingContext?.frictionlessTypes, this.logger);
250
+ const enabledCaptchaType = require_captchaTypeSelection.coerceToEnabledCaptchaType(routed.captchaType, this.allowedCaptchaTypes, this.logger);
251
+ const finalCaptchaType = require_captchaTypeSelection.switchTypeAfterRefreshes(enabledCaptchaType, effectiveParams.refreshCount, this.allowedCaptchaTypes);
252
+ const switchedByRefreshes = finalCaptchaType !== enabledCaptchaType;
251
253
  const requestedSolvedImagesCount = routed.solvedImagesCount ?? effectiveParams.solvedImagesCount;
252
254
  const imageRoundsBounds = this.routingContext ?? {};
253
255
  const finalSolvedImagesCount = finalCaptchaType === _prosopo_types.CaptchaType.image ? requestedSolvedImagesCount !== void 0 ? (0, _prosopo_types.clampImageRounds)(requestedSolvedImagesCount, imageRoundsBounds) : requestedSolvedImagesCount : void 0;
254
256
  const finalPowDifficulty = finalCaptchaType === _prosopo_types.CaptchaType.pow ? routed.powDifficulty ?? effectiveParams.powDifficulty : void 0;
255
- const finalReason = routed.reason ?? effectiveParams.reason;
257
+ const finalReason = switchedByRefreshes ? _prosopo_types.FrictionlessReason.PUZZLE_REFRESH_LIMIT : routed.reason ?? effectiveParams.reason;
256
258
  const finalPuzzleOverrides = finalCaptchaType === _prosopo_types.CaptchaType.puzzle ? (() => {
257
- const maxLevel = this.routingContext?.puzzleMaxDifficulty ?? _prosopo_types.puzzleMaxDifficultyDefault;
259
+ const maxLevel = (0, _prosopo_captcha_severity.resolveMaxEscalationLevel)(this.routingContext?.puzzleMaxDifficulty ?? _prosopo_types.puzzleMaxDifficultyDefault, this.routingContext?.platform.isMobile ?? false);
258
260
  const level = finalReason !== void 0 && _prosopo_types.NO_MEASUREMENT_REASONS.has(finalReason) ? 0 : (0, _prosopo_captcha_severity.severityToPuzzleDifficulty)(requestedSolvedImagesCount, this.routingContext?.baseImageRounds ?? this.config.captchas.solved.count, maxLevel);
259
261
  const difficulty = level > 0 ? require_puzzleDifficulty.samplePuzzleDifficulty(level, _prosopo_puzzle_assets.DEFAULT_RENDER_SETTINGS.holeDarken) : void 0;
260
262
  const tolerance = routed.puzzleTolerance ?? difficulty?.tolerance;
@@ -264,7 +266,8 @@ var FrictionlessManager = class extends require_captchaManager.CaptchaManager {
264
266
  } : void 0;
265
267
  return {
266
268
  ...tolerance !== void 0 && { puzzleTolerance: tolerance },
267
- ...puzzle !== void 0 && { puzzle }
269
+ ...puzzle !== void 0 && { puzzle },
270
+ ...difficulty !== void 0 && { puzzleLevel: difficulty.level }
268
271
  };
269
272
  })() : {};
270
273
  const blocked = finalCaptchaType === _prosopo_types.CaptchaType.image ? effectiveParams.blocked : void 0;
@@ -1,5 +1,6 @@
1
1
  const require_usageCounters = require("../../util/usageCounters.cjs");
2
2
  const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
3
+ const require_rawTlsSignalsMiddleware = require("../../api/rawTlsSignalsMiddleware.cjs");
3
4
  const require_lang = require("../../rules/lang.cjs");
4
5
  const require_clientMetaData = require("../../utils/clientMetaData.cjs");
5
6
  const require_compositeIpAddress = require("../../compositeIpAddress.cjs");
@@ -566,15 +567,7 @@ var ImgCaptchaManager = class extends require_captchaManager.CaptchaManager {
566
567
  currentUrl: sessionRecord?.currentUrl,
567
568
  iframeUrl: sessionRecord?.iframeUrl,
568
569
  coords: solution.coords,
569
- synNs: sessionRecord?.synNs,
570
- synackNs: sessionRecord?.synackNs,
571
- ackNs: sessionRecord?.ackNs,
572
- observedTtl: sessionRecord?.observedTtl,
573
- tcpMss: sessionRecord?.tcpMss,
574
- tcpWscale: sessionRecord?.tcpWscale,
575
- tcpOptsFlags: sessionRecord?.tcpOptsFlags,
576
- tcpOptsOrder: sessionRecord?.tcpOptsOrder,
577
- tcpWindow: sessionRecord?.tcpWindow,
570
+ ...require_rawTlsSignalsMiddleware.rawTlsSignalsFromRecord(sessionRecord),
578
571
  trafficPolicies: require_devicePlatform.deriveTrafficPolicies(trafficFilter)
579
572
  };
580
573
  try {
@@ -1,5 +1,6 @@
1
1
  const require_usageCounters = require("../../util/usageCounters.cjs");
2
2
  const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
3
+ const require_rawTlsSignalsMiddleware = require("../../api/rawTlsSignalsMiddleware.cjs");
3
4
  const require_clientMetaData = require("../../utils/clientMetaData.cjs");
4
5
  const require_compositeIpAddress = require("../../compositeIpAddress.cjs");
5
6
  const require_enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
@@ -209,7 +210,8 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
209
210
  let routingOutput = this.postPowContext ? await this.runPostPowRouting({
210
211
  challengeRecord,
211
212
  challengeSplit,
212
- behavioralDataPacked: decryptedBehavioralDataPacked
213
+ behavioralDataPacked: decryptedBehavioralDataPacked,
214
+ coords
213
215
  }) : void 0;
214
216
  if ((escalateForMissingCoords || escalateForIpChange) && routingOutput?.captchaType !== _prosopo_types.CaptchaType.image && routingOutput?.captchaType !== _prosopo_types.CaptchaType.puzzle) routingOutput = {
215
217
  captchaType: _prosopo_types.CaptchaType.image,
@@ -228,7 +230,7 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
228
230
  */
229
231
  async runPostPowRouting(args) {
230
232
  if (!this.postPowContext) return void 0;
231
- const { challengeRecord, challengeSplit, behavioralDataPacked } = args;
233
+ const { challengeRecord, challengeSplit, behavioralDataPacked, coords } = args;
232
234
  if (!challengeRecord.sessionId) {
233
235
  this.logger.debug(() => ({ msg: "Skipping post-pow routing: PoW record has no linked session" }));
234
236
  return;
@@ -259,6 +261,8 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
259
261
  raw: {
260
262
  ...this.postPowContext.raw,
261
263
  ...behavioralDataPacked && { behavioralDataPacked },
264
+ ...sessionRecord.mode && { mode: sessionRecord.mode },
265
+ coordsAllZero: require_powTasksUtils.isCoordsAllZero(coords),
262
266
  ...sessionRecord.simdReadings && { simd: sessionRecord.simdReadings },
263
267
  ...sessionRecord.currentUrl && { currentUrl: sessionRecord.currentUrl },
264
268
  ...sessionRecord.iframeUrl && { iframeUrl: sessionRecord.iframeUrl }
@@ -518,15 +522,7 @@ var PowCaptchaManager = class extends require_captchaManager.CaptchaManager {
518
522
  currentUrl: sessionRecord?.currentUrl,
519
523
  iframeUrl: sessionRecord?.iframeUrl,
520
524
  coords: challengeRecord.coords,
521
- synNs: sessionRecord?.synNs,
522
- synackNs: sessionRecord?.synackNs,
523
- ackNs: sessionRecord?.ackNs,
524
- observedTtl: sessionRecord?.observedTtl,
525
- tcpMss: sessionRecord?.tcpMss,
526
- tcpWscale: sessionRecord?.tcpWscale,
527
- tcpOptsFlags: sessionRecord?.tcpOptsFlags,
528
- tcpOptsOrder: sessionRecord?.tcpOptsOrder,
529
- tcpWindow: sessionRecord?.tcpWindow,
525
+ ...require_rawTlsSignalsMiddleware.rawTlsSignalsFromRecord(sessionRecord),
530
526
  trafficPolicies: require_devicePlatform.deriveTrafficPolicies(trafficFilter)
531
527
  };
532
528
  const decision = await this.decisionMachineRunner.decide(decisionInput, logger);
@@ -15,6 +15,8 @@ var checkPowSignature = (message, signature, address, signatureType) => {
15
15
  signatureType
16
16
  } });
17
17
  };
18
+ var isCoordsAllZero = (coords) => coords !== void 0 && coords.length > 0 && coords.every((group) => group.length > 0 && group.every(([x, y]) => x === 0 && y === 0));
18
19
  //#endregion
19
20
  exports.checkPowSignature = checkPowSignature;
21
+ exports.isCoordsAllZero = isCoordsAllZero;
20
22
  exports.validateSolution = validateSolution;
@@ -15,12 +15,12 @@ var createPuzzleBackgroundBuffer = (options = {}) => {
15
15
  timer.unref?.();
16
16
  return {
17
17
  take() {
18
- const image = ready.pop();
19
- if (!image) {
18
+ const background = ready.pop();
19
+ if (!background) {
20
20
  starved++;
21
21
  return require_nativeBackground.createBackgroundNative(geometry);
22
22
  }
23
- return image;
23
+ return background;
24
24
  },
25
25
  depth: () => ready.length,
26
26
  starvations: () => starved,
@@ -15,15 +15,22 @@ var nativePuzzle = (() => {
15
15
  * Byte-identical to `createBackground` from @prosopo/puzzle-assets given the
16
16
  * same seed — the JS remains the reference implementation and the contract
17
17
  * the differential test pins. Single-use is unchanged and still the caller's
18
- * responsibility: this mints a fresh CSPRNG seed per call and the seed never
19
- * leaves the process.
18
+ * responsibility.
19
+ *
20
+ * The seed is returned so the challenge record can keep it and the portal can
21
+ * regenerate this background later. See the secrecy note in prng.ts for where
22
+ * it may and may not go.
20
23
  */
21
24
  var createBackgroundNative = (geometry = _prosopo_puzzle_assets.DEFAULT_GEOMETRY) => {
22
25
  const { width, height } = geometry;
26
+ const seed = (0, _prosopo_puzzle_assets.createSeed)();
23
27
  return {
24
- data: require_metrics.measureSync("puzzle_background", () => nativePuzzle.generateBackground((0, _prosopo_puzzle_assets.createSeed)(), width, height)),
25
- width,
26
- height
28
+ image: {
29
+ data: require_metrics.measureSync("puzzle_background", () => nativePuzzle.generateBackground(seed, width, height)),
30
+ width,
31
+ height
32
+ },
33
+ seed
27
34
  };
28
35
  };
29
36
  //#endregion
@@ -79,15 +79,16 @@ var isPuzzleRenderAvailable = () => {
79
79
  };
80
80
  var renderPuzzleImages = async (placement, settings = _prosopo_puzzle_assets.DEFAULT_RENDER_SETTINGS, pieceSize) => {
81
81
  const background = (require_backgroundBuffer.getPuzzleBackgroundBuffer() ?? require_backgroundBuffer.initPuzzleBackgroundBuffer()).take();
82
- if (!background) throw new Error("puzzle renderer: no background available");
83
- const rendered = await require_metrics.measureSync("puzzle_render", () => (0, _prosopo_puzzle_assets.renderPuzzle)(background, placement, pieceSize !== void 0 ? {
82
+ const rendered = await require_metrics.measureSync("puzzle_render", () => (0, _prosopo_puzzle_assets.renderPuzzle)(background.image, placement, pieceSize !== void 0 ? {
84
83
  ..._prosopo_puzzle_assets.DEFAULT_GEOMETRY,
85
84
  pieceSize
86
85
  } : _prosopo_puzzle_assets.DEFAULT_GEOMETRY, settings));
87
86
  return {
88
87
  background: (0, _prosopo_puzzle_assets.toDataUri)(rendered.background),
89
88
  piece: (0, _prosopo_puzzle_assets.toDataUri)(rendered.piece),
90
- pieceSize: rendered.pieceSize
89
+ pieceSize: rendered.pieceSize,
90
+ backgroundSeed: background.seed.toString("hex"),
91
+ renderSeed: rendered.seed.toString("hex")
91
92
  };
92
93
  };
93
94
  //#endregion
@@ -1,5 +1,6 @@
1
1
  const require_usageCounters = require("../../util/usageCounters.cjs");
2
2
  const require_decisionMachineRunner = require("../decisionMachine/decisionMachineRunner.cjs");
3
+ const require_rawTlsSignalsMiddleware = require("../../api/rawTlsSignalsMiddleware.cjs");
3
4
  const require_clientMetaData = require("../../utils/clientMetaData.cjs");
4
5
  const require_compositeIpAddress = require("../../compositeIpAddress.cjs");
5
6
  const require_enrichDnsEvent = require("../dnsEvent/enrichDnsEvent.cjs");
@@ -470,15 +471,7 @@ var PuzzleCaptchaManager = class extends require_captchaManager.CaptchaManager {
470
471
  iframeUrl: sessionRecord?.iframeUrl,
471
472
  coords: challengeRecord.coords,
472
473
  puzzleEvents: challengeRecord.puzzleEvents,
473
- synNs: sessionRecord?.synNs,
474
- synackNs: sessionRecord?.synackNs,
475
- ackNs: sessionRecord?.ackNs,
476
- observedTtl: sessionRecord?.observedTtl,
477
- tcpMss: sessionRecord?.tcpMss,
478
- tcpWscale: sessionRecord?.tcpWscale,
479
- tcpOptsFlags: sessionRecord?.tcpOptsFlags,
480
- tcpOptsOrder: sessionRecord?.tcpOptsOrder,
481
- tcpWindow: sessionRecord?.tcpWindow,
474
+ ...require_rawTlsSignalsMiddleware.rawTlsSignalsFromRecord(sessionRecord),
482
475
  trafficPolicies: require_devicePlatform.deriveTrafficPolicies(trafficFilter)
483
476
  };
484
477
  const decision = await this.decisionMachineRunner.decide(decisionInput, logger);
@@ -1 +1 @@
1
- {"version":3,"file":"compositeIpAddress.d.ts","sourceRoot":"","sources":["../src/compositeIpAddress.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,KAAK,kBAAkB,EAAiB,MAAM,gBAAgB,CAAC;AAOxE,eAAO,MAAM,qBAAqB,OAC7B,MAAM,GAAG,SAAS,KACpB,kBAaF,CAAC;AAuBF,eAAO,MAAM,yBAAyB,uBACjB,kBAAkB,KACpC,SAaF,CAAC;AAuCF,eAAO,MAAM,cAAc,MACvB,kBAAkB,KAClB,kBAAkB,KACnB,OAiBF,CAAC"}
1
+ {"version":3,"file":"compositeIpAddress.d.ts","sourceRoot":"","sources":["../src/compositeIpAddress.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,KAAK,kBAAkB,EAAiB,MAAM,gBAAgB,CAAC;AAaxE,eAAO,MAAM,qBAAqB,OAC7B,MAAM,GAAG,SAAS,KACpB,kBAaF,CAAC;AAuBF,eAAO,MAAM,yBAAyB,uBACjB,kBAAkB,KACpC,SAaF,CAAC;AAgDF,eAAO,MAAM,cAAc,MACvB,kBAAkB,KAClB,kBAAkB,KACnB,OAoBF,CAAC"}