@apifuse/provider-sdk 2.2.0-beta.7 → 2.2.0-beta.70

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 (478) hide show
  1. package/AUTHORING.md +943 -51
  2. package/CHANGELOG.md +273 -1
  3. package/LICENSE +21 -0
  4. package/README.md +117 -29
  5. package/SUBMISSION.md +3 -2
  6. package/bin/apifuse-check.ts +293 -13
  7. package/bin/apifuse-dev.ts +42 -19
  8. package/bin/apifuse-migrate-deployment.ts +200 -0
  9. package/bin/apifuse-migrate-operation-declaration.ts +55 -0
  10. package/bin/apifuse-migrate-shape.ts +202 -0
  11. package/bin/apifuse-pack-check.ts +19 -6
  12. package/bin/apifuse-pack-smoke.ts +57 -2
  13. package/bin/apifuse-pack-types.ts +736 -38
  14. package/bin/apifuse-perf.ts +59 -23
  15. package/bin/apifuse-record.ts +923 -94
  16. package/bin/apifuse-submit-check.ts +2313 -281
  17. package/bin/apifuse-test.ts +3 -1
  18. package/bin/submit-check-delimited-text.ts +50 -0
  19. package/dist/auth-turn/index.d.ts +3 -3
  20. package/dist/auth-turn/index.js +1 -1
  21. package/dist/auth.d.ts +14 -0
  22. package/dist/auth.js +67 -0
  23. package/dist/ceremonies/index.d.ts +16 -0
  24. package/dist/ceremonies/index.js +141 -36
  25. package/dist/cli/commands.d.ts +1 -1
  26. package/dist/cli/commands.js +30 -0
  27. package/dist/cli/create.d.ts +1 -1
  28. package/dist/cli/create.js +8 -2
  29. package/dist/cli/deployment-intent.d.ts +178 -0
  30. package/dist/cli/deployment-intent.js +277 -0
  31. package/dist/cli/local-connection.d.ts +111 -0
  32. package/dist/cli/local-connection.js +151 -0
  33. package/dist/cli/migrate-deployment-intent.d.ts +132 -0
  34. package/dist/cli/migrate-deployment-intent.js +1552 -0
  35. package/dist/cli/migrate-operation-declaration.d.ts +70 -0
  36. package/dist/cli/migrate-operation-declaration.js +2206 -0
  37. package/dist/cli/migrate-operation-shape.d.ts +44 -0
  38. package/dist/cli/migrate-operation-shape.js +113 -0
  39. package/dist/cli/migrate-provider-shape.d.ts +56 -0
  40. package/dist/cli/migrate-provider-shape.js +580 -0
  41. package/dist/cli/resolver-runtime.d.ts +21 -0
  42. package/dist/cli/resolver-runtime.js +31 -0
  43. package/dist/cli/templates/provider/.agents/skills/health-checks-and-fail-closed/SKILL.md.tpl +141 -23
  44. package/dist/cli/templates/provider/Dockerfile.tpl +1 -1
  45. package/dist/cli/templates/provider/README.md.tpl +41 -19
  46. package/dist/cli/templates/provider/index.ts.tpl +6 -3
  47. package/dist/cli/templates/provider/operations/ping.ts.tpl +4 -1
  48. package/dist/cli/templates/provider/provider.json.tpl +6 -0
  49. package/dist/config/loader.d.ts +202 -16
  50. package/dist/config/loader.js +491 -141
  51. package/dist/contract-serialization.js +4 -8
  52. package/dist/contract-types.d.ts +12 -5
  53. package/dist/contract.js +24 -10
  54. package/dist/declaration-validation.d.ts +34 -0
  55. package/dist/declaration-validation.js +305 -0
  56. package/dist/define.d.ts +71 -29
  57. package/dist/define.js +807 -69
  58. package/dist/dev.d.ts +5 -0
  59. package/dist/dev.js +8 -1
  60. package/dist/engine.d.ts +129 -0
  61. package/dist/engine.js +209 -0
  62. package/dist/error-observability.d.ts +7 -0
  63. package/dist/error-observability.js +61 -0
  64. package/dist/error-resolution.d.ts +18 -0
  65. package/dist/error-resolution.js +243 -0
  66. package/dist/errors.d.ts +74 -0
  67. package/dist/errors.js +99 -0
  68. package/dist/fixture-sanitization.d.ts +28 -0
  69. package/dist/fixture-sanitization.js +371 -0
  70. package/dist/handle-meta.d.ts +90 -0
  71. package/dist/handle-meta.js +73 -0
  72. package/dist/handle.d.ts +226 -0
  73. package/dist/handle.js +345 -0
  74. package/dist/health-scenario.d.ts +1901 -0
  75. package/dist/health-scenario.js +653 -0
  76. package/dist/i18n/catalog.js +21 -1
  77. package/dist/i18n/error-messages.d.ts +86 -0
  78. package/dist/i18n/error-messages.js +192 -0
  79. package/dist/i18n/index.d.ts +1 -0
  80. package/dist/i18n/index.js +1 -0
  81. package/dist/i18n/keys.d.ts +12 -0
  82. package/dist/i18n/keys.js +76 -5
  83. package/dist/i18n/operation-locale-namespace.d.ts +2 -0
  84. package/dist/i18n/operation-locale-namespace.js +7 -0
  85. package/dist/index.d.ts +40 -15
  86. package/dist/index.js +29 -11
  87. package/dist/lint.d.ts +43 -11
  88. package/dist/lint.js +2512 -177
  89. package/dist/native-address.d.ts +43 -0
  90. package/dist/native-address.js +281 -0
  91. package/dist/native-egress-policy.d.ts +31 -0
  92. package/dist/native-egress-policy.js +288 -0
  93. package/dist/observability.d.ts +5 -2
  94. package/dist/observability.js +48 -1
  95. package/dist/provider.d.ts +18 -8
  96. package/dist/provider.js +11 -6
  97. package/dist/runtime/auth-flow.d.ts +6 -1
  98. package/dist/runtime/auth-flow.js +8 -0
  99. package/dist/runtime/bounded-expiring-map.d.ts +21 -0
  100. package/dist/runtime/bounded-expiring-map.js +64 -0
  101. package/dist/runtime/browser-telemetry-binding.d.ts +5 -0
  102. package/dist/runtime/browser-telemetry-binding.js +83 -0
  103. package/dist/runtime/browser-telemetry.d.ts +76 -0
  104. package/dist/runtime/browser-telemetry.js +165 -0
  105. package/dist/runtime/browser.d.ts +4 -0
  106. package/dist/runtime/browser.js +688 -83
  107. package/dist/runtime/cache-telemetry.d.ts +71 -0
  108. package/dist/runtime/cache-telemetry.js +177 -0
  109. package/dist/runtime/cache.d.ts +3 -0
  110. package/dist/runtime/cache.js +245 -23
  111. package/dist/runtime/capability-response.d.ts +3 -0
  112. package/dist/runtime/capability-response.js +56 -0
  113. package/dist/runtime/capability-telemetry.d.ts +46 -0
  114. package/dist/runtime/capability-telemetry.js +68 -0
  115. package/dist/runtime/chrome149-header-order.d.ts +58 -0
  116. package/dist/runtime/chrome149-header-order.js +289 -0
  117. package/dist/runtime/diagnostic-env-values.d.ts +5 -0
  118. package/dist/runtime/diagnostic-env-values.js +57 -0
  119. package/dist/runtime/diagnostic-env.d.ts +14 -0
  120. package/dist/runtime/diagnostic-env.js +44 -0
  121. package/dist/runtime/diagnostic-redactor.d.ts +54 -0
  122. package/dist/runtime/diagnostic-redactor.js +571 -0
  123. package/dist/runtime/egress-lease.d.ts +65 -0
  124. package/dist/runtime/egress-lease.js +236 -0
  125. package/dist/runtime/engine-mode.d.ts +74 -0
  126. package/dist/runtime/engine-mode.js +152 -0
  127. package/dist/runtime/env.js +14 -1
  128. package/dist/runtime/executor.d.ts +3 -2
  129. package/dist/runtime/executor.js +23 -26
  130. package/dist/runtime/handle-wordlist.d.ts +43 -0
  131. package/dist/runtime/handle-wordlist.js +256 -0
  132. package/dist/runtime/handle.d.ts +71 -0
  133. package/dist/runtime/handle.js +908 -0
  134. package/dist/runtime/http-telemetry-binding.d.ts +10 -0
  135. package/dist/runtime/http-telemetry-binding.js +152 -0
  136. package/dist/runtime/http-telemetry-guard.d.ts +16 -0
  137. package/dist/runtime/http-telemetry-guard.js +202 -0
  138. package/dist/runtime/http-telemetry.d.ts +104 -0
  139. package/dist/runtime/http-telemetry.js +190 -0
  140. package/dist/runtime/http.d.ts +34 -0
  141. package/dist/runtime/http.js +680 -121
  142. package/dist/runtime/insights.js +2 -2
  143. package/dist/runtime/instrumentation.d.ts +2 -2
  144. package/dist/runtime/instrumentation.js +462 -19
  145. package/dist/runtime/native-network-errors.d.ts +33 -0
  146. package/dist/runtime/native-network-errors.js +69 -0
  147. package/dist/runtime/native-network.d.ts +105 -0
  148. package/dist/runtime/native-network.js +1433 -0
  149. package/dist/runtime/native-telemetry.d.ts +142 -0
  150. package/dist/runtime/native-telemetry.js +231 -0
  151. package/dist/runtime/ocr-telemetry.d.ts +82 -0
  152. package/dist/runtime/ocr-telemetry.js +192 -0
  153. package/dist/runtime/ocr.d.ts +29 -0
  154. package/dist/runtime/ocr.js +468 -0
  155. package/dist/runtime/otlp.d.ts +71 -2
  156. package/dist/runtime/otlp.js +398 -16
  157. package/dist/runtime/provider.d.ts +7 -0
  158. package/dist/runtime/provider.js +14 -0
  159. package/dist/runtime/proxy-errors.js +6 -2
  160. package/dist/runtime/proxy-nodemaven.d.ts +56 -0
  161. package/dist/runtime/proxy-nodemaven.js +147 -0
  162. package/dist/runtime/proxy-retry-policy.d.ts +4 -1
  163. package/dist/runtime/proxy-retry-policy.js +11 -2
  164. package/dist/runtime/proxy-telemetry.d.ts +133 -3
  165. package/dist/runtime/proxy-telemetry.js +218 -70
  166. package/dist/runtime/redirect-hop-headers.d.ts +19 -0
  167. package/dist/runtime/redirect-hop-headers.js +58 -0
  168. package/dist/runtime/redirects.d.ts +61 -0
  169. package/dist/runtime/redirects.js +149 -0
  170. package/dist/runtime/redis.d.ts +1 -1
  171. package/dist/runtime/redis.js +4 -2
  172. package/dist/runtime/request-options.d.ts +75 -1
  173. package/dist/runtime/request-options.js +588 -0
  174. package/dist/runtime/request-telemetry.d.ts +70 -0
  175. package/dist/runtime/request-telemetry.js +229 -0
  176. package/dist/runtime/resolver-config.d.ts +13 -0
  177. package/dist/runtime/resolver-config.js +14 -0
  178. package/dist/runtime/resolver-public.d.ts +3 -0
  179. package/dist/runtime/resolver-public.js +1 -0
  180. package/dist/runtime/resolver-runtime-options.d.ts +14 -0
  181. package/dist/runtime/resolver-runtime-options.js +33 -0
  182. package/dist/runtime/resolver-shared.d.ts +24 -0
  183. package/dist/runtime/resolver-shared.js +69 -0
  184. package/dist/runtime/resolver-span-attributes.d.ts +34 -0
  185. package/dist/runtime/resolver-span-attributes.js +93 -0
  186. package/dist/runtime/resolver-telemetry.d.ts +135 -0
  187. package/dist/runtime/resolver-telemetry.js +204 -0
  188. package/dist/runtime/resolver-usage.d.ts +32 -0
  189. package/dist/runtime/resolver-usage.js +54 -0
  190. package/dist/runtime/resolver-vendors/bindings.d.ts +53 -0
  191. package/dist/runtime/resolver-vendors/bindings.js +45 -0
  192. package/dist/runtime/resolver-vendors/browser.d.ts +24 -0
  193. package/dist/runtime/resolver-vendors/browser.js +423 -0
  194. package/dist/runtime/resolver-vendors/capsolver.d.ts +22 -0
  195. package/dist/runtime/resolver-vendors/capsolver.js +544 -0
  196. package/dist/runtime/resolver-vendors/hosts.d.ts +23 -0
  197. package/dist/runtime/resolver-vendors/hosts.js +68 -0
  198. package/dist/runtime/resolver-vendors/hypersolutions.d.ts +27 -0
  199. package/dist/runtime/resolver-vendors/hypersolutions.js +369 -0
  200. package/dist/runtime/resolver-vendors/twocaptcha.d.ts +24 -0
  201. package/dist/runtime/resolver-vendors/twocaptcha.js +425 -0
  202. package/dist/runtime/resolver-vendors/types.d.ts +125 -0
  203. package/dist/runtime/resolver-vendors/types.js +106 -0
  204. package/dist/runtime/resolver.d.ts +79 -0
  205. package/dist/runtime/resolver.js +1094 -0
  206. package/dist/runtime/state-telemetry.d.ts +79 -0
  207. package/dist/runtime/state-telemetry.js +194 -0
  208. package/dist/runtime/state.d.ts +10 -1
  209. package/dist/runtime/state.js +322 -82
  210. package/dist/runtime/stealth-akamai-sbsd.d.ts +54 -0
  211. package/dist/runtime/stealth-akamai-sbsd.js +142 -0
  212. package/dist/runtime/stealth-cookies.d.ts +24 -0
  213. package/dist/runtime/stealth-cookies.js +131 -0
  214. package/dist/runtime/stealth-owned-headers.d.ts +39 -0
  215. package/dist/runtime/stealth-owned-headers.js +57 -0
  216. package/dist/runtime/stealth-telemetry.d.ts +92 -0
  217. package/dist/runtime/stealth-telemetry.js +179 -0
  218. package/dist/runtime/stealth.d.ts +45 -6
  219. package/dist/runtime/stealth.js +1775 -320
  220. package/dist/runtime/stt-telemetry.d.ts +77 -0
  221. package/dist/runtime/stt-telemetry.js +176 -0
  222. package/dist/runtime/stt.js +18 -19
  223. package/dist/runtime/timeout.d.ts +5 -0
  224. package/dist/runtime/timeout.js +12 -0
  225. package/dist/runtime/trace-config.d.ts +12 -0
  226. package/dist/runtime/trace-config.js +62 -0
  227. package/dist/runtime/trace.d.ts +17 -0
  228. package/dist/runtime/trace.js +176 -25
  229. package/dist/runtime-boundary-lint.d.ts +137 -0
  230. package/dist/runtime-boundary-lint.js +590 -0
  231. package/dist/schema.d.ts +20 -0
  232. package/dist/schema.js +72 -2
  233. package/dist/serve.d.ts +1 -1
  234. package/dist/serve.js +1 -1
  235. package/dist/server/error-observability.d.ts +1 -0
  236. package/dist/server/error-observability.js +1 -0
  237. package/dist/server/error-stack-frames.d.ts +35 -0
  238. package/dist/server/error-stack-frames.js +219 -0
  239. package/dist/server/index.d.ts +21 -2
  240. package/dist/server/index.js +11 -2
  241. package/dist/server/runtime-diagnostics.d.ts +165 -0
  242. package/dist/server/runtime-diagnostics.js +360 -0
  243. package/dist/server/sdk-version.d.ts +3 -0
  244. package/dist/server/sdk-version.js +19 -0
  245. package/dist/server/self-test-input-tokens.d.ts +2 -1
  246. package/dist/server/self-test-input-tokens.js +18 -14
  247. package/dist/server/self-test-redaction.js +8 -33
  248. package/dist/server/self-test.d.ts +18 -3
  249. package/dist/server/self-test.js +139 -76
  250. package/dist/server/sensitive-values.d.ts +26 -0
  251. package/dist/server/sensitive-values.js +137 -0
  252. package/dist/server/serve-implementation.d.ts +285 -0
  253. package/dist/server/serve-implementation.js +3172 -0
  254. package/dist/server/serve.d.ts +1 -75
  255. package/dist/server/serve.js +1 -1170
  256. package/dist/server/state-backend-report.d.ts +70 -0
  257. package/dist/server/state-backend-report.js +113 -0
  258. package/dist/server/trace-output.d.ts +7 -0
  259. package/dist/server/trace-output.js +111 -0
  260. package/dist/server/types.d.ts +37 -5
  261. package/dist/server/types.js +34 -1
  262. package/dist/stateful/errors.d.ts +19 -0
  263. package/dist/stateful/errors.js +24 -0
  264. package/dist/stateful/http-provider-event-emitter.d.ts +40 -0
  265. package/dist/stateful/http-provider-event-emitter.js +237 -0
  266. package/dist/stateful/http-session-owner-registry.d.ts +44 -0
  267. package/dist/stateful/http-session-owner-registry.js +210 -0
  268. package/dist/stateful/index.d.ts +18 -0
  269. package/dist/stateful/index.js +18 -0
  270. package/dist/stateful/provider-event-delivery-failures.d.ts +32 -0
  271. package/dist/stateful/provider-event-delivery-failures.js +43 -0
  272. package/dist/stateful/provider-event-pipeline-metrics.d.ts +46 -0
  273. package/dist/stateful/provider-event-pipeline-metrics.js +48 -0
  274. package/dist/stateful/provider-event-pipeline.d.ts +50 -0
  275. package/dist/stateful/provider-event-pipeline.js +1 -0
  276. package/dist/stateful/provider-events.d.ts +101 -0
  277. package/dist/stateful/provider-events.js +289 -0
  278. package/dist/stateful/session-key.d.ts +15 -0
  279. package/dist/stateful/session-key.js +86 -0
  280. package/dist/stateful/stateful-provider-adapter-context.d.ts +5 -0
  281. package/dist/stateful/stateful-provider-adapter-context.js +42 -0
  282. package/dist/stateful/stateful-provider-adapter-metrics.d.ts +15 -0
  283. package/dist/stateful/stateful-provider-adapter-metrics.js +21 -0
  284. package/dist/stateful/stateful-provider-adapter.d.ts +98 -0
  285. package/dist/stateful/stateful-provider-adapter.js +287 -0
  286. package/dist/stateful/stateful-provider-observability.d.ts +62 -0
  287. package/dist/stateful/stateful-provider-observability.js +161 -0
  288. package/dist/stateful/stateful-provider-owner-forwarder.d.ts +41 -0
  289. package/dist/stateful/stateful-provider-owner-forwarder.js +237 -0
  290. package/dist/stateful/stateful-provider-runtime-context.d.ts +35 -0
  291. package/dist/stateful/stateful-provider-runtime-context.js +61 -0
  292. package/dist/stateful/stateful-provider-runtime-executor.d.ts +34 -0
  293. package/dist/stateful/stateful-provider-runtime-executor.js +52 -0
  294. package/dist/stateful/stateful-provider-session-routing.d.ts +67 -0
  295. package/dist/stateful/stateful-provider-session-routing.js +345 -0
  296. package/dist/stateful/stateful-provider-session-runtime.d.ts +98 -0
  297. package/dist/stateful/stateful-provider-session-runtime.js +245 -0
  298. package/dist/stateful-signing.d.ts +18 -0
  299. package/dist/stateful-signing.js +27 -0
  300. package/dist/stealth/profiles.d.ts +15 -4
  301. package/dist/stealth/profiles.js +169 -211
  302. package/dist/stream-evidence.d.ts +74 -0
  303. package/dist/stream-evidence.js +785 -0
  304. package/dist/stream.js +7 -1
  305. package/dist/testing/index.d.ts +2 -1
  306. package/dist/testing/index.js +2 -1
  307. package/dist/testing/run.d.ts +32 -2
  308. package/dist/testing/run.js +509 -25
  309. package/dist/trace-sanitization.d.ts +6 -0
  310. package/dist/trace-sanitization.js +68 -0
  311. package/dist/types.d.ts +899 -210
  312. package/dist/types.js +1 -0
  313. package/dist/typescript-module.d.ts +39 -0
  314. package/dist/typescript-module.js +72 -0
  315. package/package.json +52 -6
  316. package/src/auth-turn/index.ts +1 -1
  317. package/src/auth.ts +118 -0
  318. package/src/ceremonies/index.ts +189 -46
  319. package/src/cli/commands.ts +37 -0
  320. package/src/cli/create.ts +8 -2
  321. package/src/cli/deployment-intent.ts +364 -0
  322. package/src/cli/local-connection.ts +221 -0
  323. package/src/cli/migrate-deployment-intent.ts +1908 -0
  324. package/src/cli/migrate-operation-declaration.ts +3026 -0
  325. package/src/cli/migrate-operation-shape.ts +184 -0
  326. package/src/cli/migrate-provider-shape.ts +778 -0
  327. package/src/cli/resolver-runtime.ts +72 -0
  328. package/src/cli/templates/provider/.agents/skills/health-checks-and-fail-closed/SKILL.md.tpl +141 -23
  329. package/src/cli/templates/provider/Dockerfile.tpl +1 -1
  330. package/src/cli/templates/provider/README.md.tpl +41 -19
  331. package/src/cli/templates/provider/index.ts.tpl +6 -3
  332. package/src/cli/templates/provider/operations/ping.ts.tpl +4 -1
  333. package/src/cli/templates/provider/provider.json.tpl +6 -0
  334. package/src/config/loader.ts +774 -181
  335. package/src/contract-serialization.ts +5 -7
  336. package/src/contract-types.ts +12 -5
  337. package/src/contract.ts +24 -10
  338. package/src/declaration-validation.ts +376 -0
  339. package/src/define.ts +1105 -131
  340. package/src/dev.ts +13 -1
  341. package/src/engine.ts +390 -0
  342. package/src/error-observability.ts +64 -0
  343. package/src/error-resolution.ts +269 -0
  344. package/src/errors.ts +157 -0
  345. package/src/fixture-sanitization.ts +422 -0
  346. package/src/handle-meta.ts +143 -0
  347. package/src/handle.ts +694 -0
  348. package/src/health-scenario.ts +960 -0
  349. package/src/i18n/catalog.ts +23 -1
  350. package/src/i18n/error-messages.ts +255 -0
  351. package/src/i18n/index.ts +1 -0
  352. package/src/i18n/keys.ts +80 -6
  353. package/src/i18n/operation-locale-namespace.ts +10 -0
  354. package/src/index.ts +390 -23
  355. package/src/lint.ts +2975 -234
  356. package/src/native-address.ts +340 -0
  357. package/src/native-egress-policy.ts +358 -0
  358. package/src/observability.ts +51 -1
  359. package/src/provider.ts +207 -27
  360. package/src/runtime/auth-flow.ts +15 -0
  361. package/src/runtime/bounded-expiring-map.ts +67 -0
  362. package/src/runtime/browser-telemetry-binding.ts +92 -0
  363. package/src/runtime/browser-telemetry.ts +289 -0
  364. package/src/runtime/browser.ts +882 -99
  365. package/src/runtime/cache-telemetry.ts +247 -0
  366. package/src/runtime/cache.ts +258 -22
  367. package/src/runtime/capability-response.ts +53 -0
  368. package/src/runtime/capability-telemetry.ts +101 -0
  369. package/src/runtime/chrome149-header-order.ts +330 -0
  370. package/src/runtime/diagnostic-env-values.ts +56 -0
  371. package/src/runtime/diagnostic-env.ts +65 -0
  372. package/src/runtime/diagnostic-redactor.ts +668 -0
  373. package/src/runtime/egress-lease.ts +341 -0
  374. package/src/runtime/engine-mode.ts +233 -0
  375. package/src/runtime/env.ts +15 -1
  376. package/src/runtime/executor.ts +39 -32
  377. package/src/runtime/handle-wordlist.ts +266 -0
  378. package/src/runtime/handle.ts +1180 -0
  379. package/src/runtime/http-telemetry-binding.ts +162 -0
  380. package/src/runtime/http-telemetry-guard.ts +208 -0
  381. package/src/runtime/http-telemetry.ts +292 -0
  382. package/src/runtime/http.ts +896 -150
  383. package/src/runtime/insights.ts +2 -2
  384. package/src/runtime/instrumentation.ts +628 -28
  385. package/src/runtime/native-network-errors.ts +99 -0
  386. package/src/runtime/native-network.ts +1853 -0
  387. package/src/runtime/native-telemetry.ts +366 -0
  388. package/src/runtime/ocr-telemetry.ts +308 -0
  389. package/src/runtime/ocr.ts +564 -0
  390. package/src/runtime/otlp.ts +468 -21
  391. package/src/runtime/provider.ts +15 -0
  392. package/src/runtime/proxy-errors.ts +12 -4
  393. package/src/runtime/proxy-nodemaven.ts +222 -0
  394. package/src/runtime/proxy-retry-policy.ts +12 -1
  395. package/src/runtime/proxy-telemetry.ts +358 -103
  396. package/src/runtime/redirect-hop-headers.ts +71 -0
  397. package/src/runtime/redirects.ts +215 -0
  398. package/src/runtime/redis.ts +7 -2
  399. package/src/runtime/request-options.ts +728 -1
  400. package/src/runtime/request-telemetry.ts +375 -0
  401. package/src/runtime/resolver-config.ts +18 -0
  402. package/src/runtime/resolver-public.ts +44 -0
  403. package/src/runtime/resolver-runtime-options.ts +50 -0
  404. package/src/runtime/resolver-shared.ts +113 -0
  405. package/src/runtime/resolver-span-attributes.ts +139 -0
  406. package/src/runtime/resolver-telemetry.ts +362 -0
  407. package/src/runtime/resolver-usage.ts +99 -0
  408. package/src/runtime/resolver-vendors/bindings.ts +61 -0
  409. package/src/runtime/resolver-vendors/browser.ts +591 -0
  410. package/src/runtime/resolver-vendors/capsolver.ts +727 -0
  411. package/src/runtime/resolver-vendors/hosts.ts +81 -0
  412. package/src/runtime/resolver-vendors/hypersolutions.ts +480 -0
  413. package/src/runtime/resolver-vendors/twocaptcha.ts +555 -0
  414. package/src/runtime/resolver-vendors/types.ts +261 -0
  415. package/src/runtime/resolver.ts +1543 -0
  416. package/src/runtime/state-telemetry.ts +298 -0
  417. package/src/runtime/state.ts +435 -89
  418. package/src/runtime/stealth-akamai-sbsd.ts +207 -0
  419. package/src/runtime/stealth-cookies.ts +155 -0
  420. package/src/runtime/stealth-owned-headers.ts +67 -0
  421. package/src/runtime/stealth-telemetry.ts +309 -0
  422. package/src/runtime/stealth.ts +2275 -372
  423. package/src/runtime/stt-telemetry.ts +282 -0
  424. package/src/runtime/stt.ts +96 -91
  425. package/src/runtime/timeout.ts +18 -0
  426. package/src/runtime/trace-config.ts +78 -0
  427. package/src/runtime/trace.ts +257 -35
  428. package/src/runtime-boundary-lint.ts +707 -0
  429. package/src/schema.ts +80 -2
  430. package/src/serve.ts +6 -1
  431. package/src/server/error-observability.ts +1 -0
  432. package/src/server/error-stack-frames.ts +214 -0
  433. package/src/server/index.ts +184 -2
  434. package/src/server/runtime-diagnostics.ts +522 -0
  435. package/src/server/sdk-version.ts +22 -0
  436. package/src/server/self-test-input-tokens.ts +29 -14
  437. package/src/server/self-test-redaction.ts +10 -40
  438. package/src/server/self-test.ts +205 -89
  439. package/src/server/sensitive-values.ts +211 -0
  440. package/src/server/serve-implementation.ts +4596 -0
  441. package/src/server/serve.ts +1 -1685
  442. package/src/server/state-backend-report.ts +185 -0
  443. package/src/server/trace-output.ts +189 -0
  444. package/src/server/types.ts +34 -1
  445. package/src/stateful/README.md +146 -0
  446. package/src/stateful/errors.ts +35 -0
  447. package/src/stateful/http-provider-event-emitter.ts +314 -0
  448. package/src/stateful/http-session-owner-registry.ts +306 -0
  449. package/src/stateful/index.ts +18 -0
  450. package/src/stateful/provider-event-delivery-failures.ts +80 -0
  451. package/src/stateful/provider-event-pipeline-metrics.ts +95 -0
  452. package/src/stateful/provider-event-pipeline.ts +61 -0
  453. package/src/stateful/provider-events.ts +462 -0
  454. package/src/stateful/session-key.ts +111 -0
  455. package/src/stateful/stateful-provider-adapter-context.ts +59 -0
  456. package/src/stateful/stateful-provider-adapter-metrics.ts +48 -0
  457. package/src/stateful/stateful-provider-adapter.ts +562 -0
  458. package/src/stateful/stateful-provider-observability.ts +261 -0
  459. package/src/stateful/stateful-provider-owner-forwarder.ts +310 -0
  460. package/src/stateful/stateful-provider-runtime-context.ts +96 -0
  461. package/src/stateful/stateful-provider-runtime-executor.ts +96 -0
  462. package/src/stateful/stateful-provider-session-routing.ts +546 -0
  463. package/src/stateful/stateful-provider-session-runtime.ts +403 -0
  464. package/src/stateful-signing.ts +46 -0
  465. package/src/stealth/profiles.ts +212 -231
  466. package/src/stream-evidence.ts +988 -0
  467. package/src/stream.ts +8 -1
  468. package/src/testing/index.ts +10 -1
  469. package/src/testing/run.ts +685 -19
  470. package/src/trace-sanitization.ts +110 -0
  471. package/src/types.ts +1014 -273
  472. package/src/typescript-module.ts +100 -0
  473. package/dist/choice-token.d.ts +0 -24
  474. package/dist/choice-token.js +0 -74
  475. package/dist/runtime/choice.d.ts +0 -15
  476. package/dist/runtime/choice.js +0 -413
  477. package/src/choice-token.ts +0 -165
  478. package/src/runtime/choice.ts +0 -686
@@ -0,0 +1,147 @@
1
+ import { readDiagnosticEnv } from "./diagnostic-env.js";
2
+ import { createHash, randomBytes } from "node:crypto";
3
+ export const NODEMAVEN_USERNAME_ENV = "APIFUSE__PROXY__NODEMAVEN_USERNAME";
4
+ export const NODEMAVEN_PASSWORD_ENV = "APIFUSE__PROXY__NODEMAVEN_PASSWORD";
5
+ export const NODEMAVEN_FILTER_ENV = "APIFUSE__PROXY__NODEMAVEN_FILTER";
6
+ export const NODEMAVEN_GATEWAY_HOST = "gate.nodemaven.com";
7
+ /**
8
+ * NodeMaven's fastest protocol: HTTP CONNECT. Benchmarks (KR, cold + warm)
9
+ * showed socks5 through the gateway adds ~500ms per request over http, so
10
+ * NodeMaven never defaults to socks5.
11
+ */
12
+ export const NODEMAVEN_DEFAULT_PROTOCOL = "http";
13
+ /** NodeMaven gateway port ranges per protocol (docs: HTTP 8080-9080, SOCKS5 1080-2080). */
14
+ const NODEMAVEN_PORTS = {
15
+ http: { min: 8080, max: 9080 },
16
+ socks5: { min: 1080, max: 2080 },
17
+ };
18
+ const NODEMAVEN_FILTERS = new Set(["medium", "high"]);
19
+ const DEFAULT_NODEMAVEN_FILTER = "medium";
20
+ const DEFAULT_NODEMAVEN_POOL_SIZE = 20;
21
+ export const NODEMAVEN_MAX_POOL_SIZE = 50;
22
+ /** NodeMaven sticky sessions persist up to 24h server-side, keyed by the sid. */
23
+ const NODEMAVEN_MAX_LIFETIME_MINUTES = 1440;
24
+ const SID_LENGTH = 10;
25
+ export function hasNodemavenCredentials() {
26
+ return Boolean(readNodemavenUsername() && readNodemavenPassword());
27
+ }
28
+ function readNodemavenUsername() {
29
+ return readDiagnosticEnv(NODEMAVEN_USERNAME_ENV)?.trim() || undefined;
30
+ }
31
+ function readNodemavenPassword() {
32
+ return readDiagnosticEnv(NODEMAVEN_PASSWORD_ENV)?.trim() || undefined;
33
+ }
34
+ function resolveNodemavenFilter(value) {
35
+ const raw = value?.trim().toLowerCase();
36
+ if (!raw)
37
+ return DEFAULT_NODEMAVEN_FILTER;
38
+ if (!NODEMAVEN_FILTERS.has(raw)) {
39
+ throw new Error(`${NODEMAVEN_FILTER_ENV} must be "medium" or "high"`);
40
+ }
41
+ return raw;
42
+ }
43
+ export function nodemavenPoolSize(policy) {
44
+ return Math.min(NODEMAVEN_MAX_POOL_SIZE, Math.max(1, Math.floor(policy.session?.poolSize ?? DEFAULT_NODEMAVEN_POOL_SIZE)));
45
+ }
46
+ export function nodemavenLifetimeMinutes(policy) {
47
+ const configured = policy.session?.lifetimeMinutes;
48
+ if (typeof configured !== "number" || !Number.isFinite(configured) || configured <= 0) {
49
+ return NODEMAVEN_MAX_LIFETIME_MINUTES;
50
+ }
51
+ return Math.min(NODEMAVEN_MAX_LIFETIME_MINUTES, Math.max(1, Math.floor(configured)));
52
+ }
53
+ /** Stable wall-clock window shared by every process deriving the same sticky sid. */
54
+ export function nodemavenSessionWindow(policy, now = Date.now()) {
55
+ const lifetimeMs = nodemavenLifetimeMinutes(policy) * 60_000;
56
+ const refreshEpoch = Math.floor(now / lifetimeMs);
57
+ return {
58
+ refreshEpoch,
59
+ expiresAt: new Date((refreshEpoch + 1) * lifetimeMs).toISOString(),
60
+ };
61
+ }
62
+ /** NodeMaven username tokens accept `[a-z0-9]`; slugify geo values to that set. */
63
+ function slugifyGeo(value) {
64
+ if (!value)
65
+ return undefined;
66
+ const slug = value
67
+ .trim()
68
+ .toLowerCase()
69
+ .replace(/[^a-z0-9]+/g, "");
70
+ return slug || undefined;
71
+ }
72
+ function isStickyAffinity(policy) {
73
+ return (policy.session?.affinity ?? "request") !== "request";
74
+ }
75
+ /**
76
+ * A sticky sid is deterministic from the affinity key so every process serving
77
+ * the same connection derives the same egress IP without shared storage. A
78
+ * rotating sid is random per call (a fresh egress IP per request).
79
+ */
80
+ function deriveSid(policy, affinityKey, poolIndex, refreshEpoch) {
81
+ if (!isStickyAffinity(policy) || !affinityKey) {
82
+ return randomBytes(SID_LENGTH).toString("hex").slice(0, SID_LENGTH);
83
+ }
84
+ const digest = createHash("sha256")
85
+ .update(`${affinityKey}:${refreshEpoch}:${poolIndex}`)
86
+ .digest("hex");
87
+ // hex digits are a subset of the allowed [a-z0-9] sid charset.
88
+ return digest.slice(0, SID_LENGTH);
89
+ }
90
+ function selectPort(protocol, sid, poolIndex) {
91
+ const { min, max } = NODEMAVEN_PORTS[protocol];
92
+ const span = max - min + 1;
93
+ const hashInt = Number.parseInt(createHash("sha256").update(`${sid}:${poolIndex}`).digest("hex").slice(0, 8), 16);
94
+ return min + (hashInt % span);
95
+ }
96
+ /**
97
+ * Synthesize a NodeMaven gateway proxy URL locally from static credentials.
98
+ * There is no allocation API — geo/session are encoded in the username.
99
+ */
100
+ export function synthesizeNodemavenProxy(input) {
101
+ const username = input.credentials.username.trim();
102
+ const password = input.credentials.password.trim();
103
+ if (!username || !password) {
104
+ throw new Error(`NodeMaven credentials missing: set ${NODEMAVEN_USERNAME_ENV} and ${NODEMAVEN_PASSWORD_ENV}.`);
105
+ }
106
+ const filter = resolveNodemavenFilter(input.credentials.filter);
107
+ const sid = deriveSid(input.policy, input.affinityKey, input.poolIndex, input.refreshEpoch);
108
+ const port = selectPort(input.protocol, sid, input.poolIndex);
109
+ const lifetimeMinutes = nodemavenLifetimeMinutes(input.policy);
110
+ const sticky = isStickyAffinity(input.policy);
111
+ const country = slugifyGeo(input.country ?? input.policy.geo?.country);
112
+ const region = slugifyGeo(input.policy.geo?.subdivision);
113
+ const city = slugifyGeo(input.policy.geo?.city);
114
+ const tokens = [username];
115
+ if (country)
116
+ tokens.push("country", country);
117
+ if (region)
118
+ tokens.push("region", region);
119
+ if (city)
120
+ tokens.push("city", city);
121
+ tokens.push("sid", sid);
122
+ tokens.push("filter", filter);
123
+ tokens.push("ipv4", "true");
124
+ const proxyUsername = tokens.join("-");
125
+ // Username tokens are [a-z0-9-] only, which survive URL encoding unchanged.
126
+ const url = `${input.protocol}://${proxyUsername}:${encodeURIComponent(password)}@${NODEMAVEN_GATEWAY_HOST}:${port}`;
127
+ return {
128
+ url,
129
+ protocol: input.protocol,
130
+ sticky,
131
+ sessionId: sid,
132
+ ...(sticky
133
+ ? {
134
+ expiresAt: input.expiresAt ??
135
+ new Date((input.now ?? Date.now()) + lifetimeMinutes * 60_000).toISOString(),
136
+ }
137
+ : {}),
138
+ diagnostics: {
139
+ vendor: "nodemaven",
140
+ protocol: input.protocol,
141
+ sticky,
142
+ filter,
143
+ lifetimeMinutes,
144
+ ...(country ? { country } : {}),
145
+ },
146
+ };
147
+ }
@@ -21,7 +21,10 @@ export declare function normalizeProxyTransportRetryOptions(retry: RequestOption
21
21
  label?: RetryPolicyLabel;
22
22
  }): NormalizedProxyTransportRetryOptions | undefined;
23
23
  export declare function validateUnsafeProxyTransportRetryMethods(options: NormalizedProxyTransportRetryOptions, label?: RetryPolicyLabel): void;
24
- export declare function isProxyTransportRetryMethod(method: HttpMethod | string, options: NormalizedProxyTransportRetryOptions): boolean;
24
+ export declare function isProxyTransportRetryMethod(method: HttpMethod | string, options: NormalizedProxyTransportRetryOptions, request?: {
25
+ readonly body?: unknown;
26
+ readonly headers?: Readonly<Record<string, string | readonly string[] | undefined>>;
27
+ }): boolean;
25
28
  export declare function shouldRetryProxyTransportError(error: unknown, options: NormalizedProxyTransportRetryOptions): boolean;
26
29
  export declare function shouldRetryProxyTransportAttempt(input: {
27
30
  error: unknown;
@@ -1,5 +1,6 @@
1
1
  import { ProviderError, TransportError } from "../errors.js";
2
2
  import { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "../types.js";
3
+ import { isSensitiveKey } from "./request-options.js";
3
4
  export const DEFAULT_PROXY_TRANSPORT_RETRY_METHODS = ["GET", "HEAD", "OPTIONS"];
4
5
  export const DEFAULT_PROXY_TRANSPORT_RETRY_ERROR_CODES = [
5
6
  "transport_network_error",
@@ -250,10 +251,18 @@ export function validateUnsafeProxyTransportRetryMethods(options, label = "Proxy
250
251
  return;
251
252
  throw new ProviderError(`${label} retry methods include unsafe method(s): ${unsafeMethods.join(", ")}`, { code: "retry_unsafe_method" });
252
253
  }
253
- export function isProxyTransportRetryMethod(method, options) {
254
- return options.methods
254
+ export function isProxyTransportRetryMethod(method, options, request) {
255
+ const methodAllowed = options.methods
255
256
  .map((allowedMethod) => allowedMethod.toUpperCase())
256
257
  .includes(method.toUpperCase());
258
+ if (!methodAllowed || request === undefined)
259
+ return methodAllowed;
260
+ if (request.body !== undefined)
261
+ return false;
262
+ return !Object.keys(request.headers ?? {}).some((name) => {
263
+ const normalized = name.toLowerCase();
264
+ return normalized === "cookie" || normalized === "proxy-authorization" || isSensitiveKey(name);
265
+ });
257
266
  }
258
267
  export function shouldRetryProxyTransportError(error, options) {
259
268
  const code = retryErrorCode(error);
@@ -1,8 +1,138 @@
1
- import type { ProxyAttemptTelemetryEvent, ProxyResolutionTelemetryEvent, ProxyTelemetrySink } from "../config/loader.js";
2
- export declare const PROVIDER_TELEMETRY_HEADER = "X-ApiFuse-Provider-Telemetry";
3
- export declare class ProxyTelemetryCollector implements ProxyTelemetrySink {
1
+ import type { ProxyAttemptTelemetryEvent, ProxyCacheStatus, ProxyProtocol, ProxyResolutionTelemetryEvent, ProxyTelemetrySink, ProxyUserAgentSource, ProxyVendorFailoverTelemetryEvent, ProxyVendorName, SmartproxyAllocatorBodyClass } from "../config/loader.js";
2
+ import { type ClosedEnum, type TelemetryContributor } from "./request-telemetry.js";
3
+ export { PROVIDER_TELEMETRY_HEADER } from "./request-telemetry.js";
4
+ declare const PROXY_HASH: unique symbol;
5
+ /** Bounded hexadecimal host hash used in proxy attempt samples. */
6
+ export type ProxyHash = ClosedEnum<string> & {
7
+ readonly [PROXY_HASH]: true;
8
+ };
9
+ export type ProxyTelemetryResolvedPayload = {
10
+ kind: "resolved";
11
+ provider: ProxyVendorName;
12
+ userAgentSource?: ProxyUserAgentSource;
13
+ protocol?: ProxyProtocol;
14
+ cacheStatus: ProxyCacheStatus;
15
+ cacheHit: boolean;
16
+ resolutionMs: number;
17
+ allocatorMs?: number;
18
+ allocatorStatus?: number;
19
+ allocatorBodyClass?: SmartproxyAllocatorBodyClass;
20
+ allocatorAttempts?: number;
21
+ lockWaitMs?: number;
22
+ redisReadMs?: number;
23
+ redisWriteMs?: number;
24
+ poolAgeMs?: number;
25
+ poolExpiresInMs?: number;
26
+ attempts: number;
27
+ refreshes?: number;
28
+ attemptSamples?: {
29
+ n: number;
30
+ a: number;
31
+ i?: number;
32
+ h?: string;
33
+ o: ProxyAttemptTelemetryEvent["outcome"];
34
+ c?: string;
35
+ s?: number;
36
+ d?: number;
37
+ }[];
38
+ /** Distinct vendors attempted across the resolution chain, in order seen. */
39
+ vendors?: ProxyVendorName[];
40
+ /** Cross-vendor failover events (bounded). */
41
+ failovers?: {
42
+ v: ProxyVendorName;
43
+ nx?: ProxyVendorName;
44
+ p: ProxyVendorFailoverTelemetryEvent["phase"];
45
+ r: ProxyVendorFailoverTelemetryEvent["reason"];
46
+ a?: number;
47
+ }[];
48
+ };
49
+ export type ProxyTelemetryUnresolvedPayload = {
50
+ kind: "unresolved";
51
+ /** Distinct vendors that failed resolution or recorded a failover, in order seen. */
52
+ vendors: ProxyVendorName[];
53
+ cacheStatus?: ProxyCacheStatus;
54
+ cacheHit?: boolean;
55
+ resolutionMs?: number;
56
+ allocatorMs?: number;
57
+ allocatorStatus?: number;
58
+ allocatorBodyClass?: SmartproxyAllocatorBodyClass;
59
+ allocatorAttempts?: number;
60
+ lockWaitMs?: number;
61
+ redisReadMs?: number;
62
+ redisWriteMs?: number;
63
+ poolAgeMs?: number;
64
+ poolExpiresInMs?: number;
65
+ attempts?: number;
66
+ refreshes?: number;
67
+ failovers?: {
68
+ v: ProxyVendorName;
69
+ nx?: ProxyVendorName;
70
+ p: ProxyVendorFailoverTelemetryEvent["phase"];
71
+ r: ProxyVendorFailoverTelemetryEvent["reason"];
72
+ a?: number;
73
+ }[];
74
+ attemptSamples?: {
75
+ n: number;
76
+ a: number;
77
+ i?: number;
78
+ h?: string;
79
+ o: ProxyAttemptTelemetryEvent["outcome"];
80
+ c?: string;
81
+ s?: number;
82
+ d?: number;
83
+ }[];
84
+ };
85
+ export type ProxyTelemetryLogPayload = ProxyTelemetryResolvedPayload | ProxyTelemetryUnresolvedPayload;
86
+ /** Concrete gateway-safe projection of the unchanged proxy sibling. */
87
+ export type ProxyTelemetryHeaderPayload = {
88
+ kind: ClosedEnum<"resolved" | "unresolved">;
89
+ provider?: ClosedEnum<ProxyVendorName>;
90
+ userAgentSource?: ClosedEnum<ProxyUserAgentSource>;
91
+ protocol?: ClosedEnum<ProxyProtocol>;
92
+ cacheStatus?: ClosedEnum<ProxyCacheStatus>;
93
+ cacheHit?: boolean;
94
+ resolutionMs?: number;
95
+ allocatorMs?: number;
96
+ allocatorStatus?: number;
97
+ allocatorBodyClass?: ClosedEnum<SmartproxyAllocatorBodyClass>;
98
+ allocatorAttempts?: number;
99
+ lockWaitMs?: number;
100
+ redisReadMs?: number;
101
+ redisWriteMs?: number;
102
+ poolAgeMs?: number;
103
+ poolExpiresInMs?: number;
104
+ attempts?: number;
105
+ refreshes?: number;
106
+ attemptSamples?: {
107
+ n: number;
108
+ a: number;
109
+ i?: number;
110
+ h?: ProxyHash;
111
+ o: ClosedEnum<ProxyAttemptTelemetryEvent["outcome"]>;
112
+ c?: ClosedEnum<string>;
113
+ s?: number;
114
+ d?: number;
115
+ }[];
116
+ vendors?: ClosedEnum<ProxyVendorName>[];
117
+ failovers?: {
118
+ v: ClosedEnum<ProxyVendorName>;
119
+ nx?: ClosedEnum<ProxyVendorName>;
120
+ p: ClosedEnum<ProxyVendorFailoverTelemetryEvent["phase"]>;
121
+ r: ClosedEnum<ProxyVendorFailoverTelemetryEvent["reason"]>;
122
+ a?: number;
123
+ }[];
124
+ };
125
+ export declare class ProxyTelemetryCollector implements ProxyTelemetrySink, TelemetryContributor<ProxyTelemetryLogPayload, ProxyTelemetryHeaderPayload> {
4
126
  #private;
127
+ readonly key: "proxy";
5
128
  recordProxyResolution(event: ProxyResolutionTelemetryEvent): void;
129
+ /** Number of raw resolution events retained for bounded-history verification. */
130
+ get retainedResolutionEventCount(): number;
131
+ /** Total resolutions included in the incremental aggregate. */
132
+ get resolutionEventCount(): number;
133
+ recordProxyVendorFailover(event: ProxyVendorFailoverTelemetryEvent): void;
6
134
  recordProxyAttempt(event: ProxyAttemptTelemetryEvent): void;
135
+ toLogPayload(): ProxyTelemetryLogPayload | undefined;
136
+ toHeaderPayload(log: ProxyTelemetryLogPayload): ProxyTelemetryHeaderPayload;
7
137
  toHeaderValue(): string | undefined;
8
138
  }
@@ -1,6 +1,11 @@
1
- export const PROVIDER_TELEMETRY_HEADER = "X-ApiFuse-Provider-Telemetry";
2
- const MAX_HEADER_BYTES = 4_096;
1
+ import { closedEnum, RequestTelemetry, } from "./request-telemetry.js";
2
+ import { createTraceContext } from "./trace.js";
3
+ export { PROVIDER_TELEMETRY_HEADER } from "./request-telemetry.js";
3
4
  const MAX_PROXY_ATTEMPT_SAMPLES = 24;
5
+ const MAX_PROXY_FAILOVER_SAMPLES = 12;
6
+ const MAX_RETAINED_PROXY_RESOLUTIONS = 64;
7
+ const PROXY_HEADER_TOKEN = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,63}$/;
8
+ const PROXY_HEADER_HASH = /^[0-9a-f]{1,16}$/;
4
9
  const CACHE_STATUS_SEVERITY = {
5
10
  disabled: 0,
6
11
  memory_hit: 1,
@@ -22,15 +27,43 @@ function maxOptional(left, right) {
22
27
  function worseStatus(left, right) {
23
28
  return CACHE_STATUS_SEVERITY[right] > CACHE_STATUS_SEVERITY[left] ? right : left;
24
29
  }
25
- function encodeBase64Url(value) {
26
- return Buffer.from(value, "utf8").toString("base64url");
30
+ function aggregateResolution(acc, event) {
31
+ return {
32
+ provider: event.provider,
33
+ userAgentSource: event.userAgentSource ?? acc.userAgentSource,
34
+ cacheStatus: worseStatus(acc.cacheStatus, event.cacheStatus),
35
+ cacheHit: acc.cacheHit && event.cacheHit,
36
+ resolutionMs: acc.resolutionMs + event.resolutionMs,
37
+ allocatorMs: sumOptional(acc.allocatorMs, event.allocatorMs),
38
+ allocatorStatus: event.allocatorStatus ?? acc.allocatorStatus,
39
+ allocatorBodyClass: event.allocatorBodyClass ?? acc.allocatorBodyClass,
40
+ allocatorAttempts: sumOptional(acc.allocatorAttempts, event.allocatorAttempts),
41
+ lockWaitMs: sumOptional(acc.lockWaitMs, event.lockWaitMs),
42
+ redisReadMs: sumOptional(acc.redisReadMs, event.redisReadMs),
43
+ redisWriteMs: sumOptional(acc.redisWriteMs, event.redisWriteMs),
44
+ poolAgeMs: maxOptional(acc.poolAgeMs, event.poolAgeMs),
45
+ poolExpiresInMs: maxOptional(acc.poolExpiresInMs, event.poolExpiresInMs),
46
+ attempts: acc.attempts + event.attempts,
47
+ refreshes: sumOptional(acc.refreshes, event.refreshes),
48
+ };
27
49
  }
28
50
  export class ProxyTelemetryCollector {
51
+ key = "proxy";
29
52
  #events = [];
53
+ #resolutionCount = 0;
54
+ #aggregateResolution;
55
+ #lastSuccessfulResolution;
56
+ #vendors = [];
30
57
  #attempts = [];
58
+ #failovers = [];
59
+ #unresolvedVendors = [];
31
60
  recordProxyResolution(event) {
32
- this.#events.push({
33
- provider: "smartproxy",
61
+ const outcome = event.outcome === "error" ? "error" : "ok";
62
+ const normalized = {
63
+ provider: event.provider,
64
+ outcome,
65
+ ...(event.userAgentSource ? { userAgentSource: event.userAgentSource } : {}),
66
+ ...(event.protocol ? { protocol: event.protocol } : {}),
34
67
  cacheStatus: event.cacheStatus,
35
68
  cacheHit: event.cacheHit,
36
69
  resolutionMs: Math.max(0, Math.floor(event.resolutionMs)),
@@ -51,13 +84,48 @@ export class ProxyTelemetryCollector {
51
84
  : Math.max(0, Math.floor(event.poolExpiresInMs)),
52
85
  attempts: Math.max(1, Math.floor(event.attempts || 1)),
53
86
  refreshes: event.refreshes === undefined ? undefined : Math.max(0, Math.floor(event.refreshes)),
87
+ };
88
+ this.#resolutionCount += 1;
89
+ if (this.#events.length < MAX_RETAINED_PROXY_RESOLUTIONS)
90
+ this.#events.push(normalized);
91
+ this.#aggregateResolution = this.#aggregateResolution
92
+ ? aggregateResolution(this.#aggregateResolution, normalized)
93
+ : normalized;
94
+ if (outcome === "ok")
95
+ this.#lastSuccessfulResolution = normalized;
96
+ if (!this.#vendors.includes(event.provider))
97
+ this.#vendors.push(event.provider);
98
+ if (outcome === "error" && !this.#unresolvedVendors.includes(event.provider)) {
99
+ this.#unresolvedVendors.push(event.provider);
100
+ }
101
+ }
102
+ /** Number of raw resolution events retained for bounded-history verification. */
103
+ get retainedResolutionEventCount() {
104
+ return this.#events.length;
105
+ }
106
+ /** Total resolutions included in the incremental aggregate. */
107
+ get resolutionEventCount() {
108
+ return this.#resolutionCount;
109
+ }
110
+ recordProxyVendorFailover(event) {
111
+ if (this.#failovers.length >= MAX_PROXY_FAILOVER_SAMPLES)
112
+ return;
113
+ this.#failovers.push({
114
+ vendor: event.vendor,
115
+ ...(event.nextVendor ? { nextVendor: event.nextVendor } : {}),
116
+ phase: event.phase,
117
+ reason: event.reason,
118
+ ...(event.attempt === undefined ? {} : { attempt: Math.max(0, Math.floor(event.attempt)) }),
54
119
  });
120
+ if (!this.#unresolvedVendors.includes(event.vendor)) {
121
+ this.#unresolvedVendors.push(event.vendor);
122
+ }
55
123
  }
56
124
  recordProxyAttempt(event) {
57
125
  if (this.#attempts.length >= MAX_PROXY_ATTEMPT_SAMPLES)
58
126
  return;
59
127
  this.#attempts.push({
60
- provider: "smartproxy",
128
+ provider: event.provider,
61
129
  attempt: Math.max(1, Math.floor(event.attempt || 1)),
62
130
  ...(event.poolIndex === undefined
63
131
  ? {}
@@ -71,72 +139,152 @@ export class ProxyTelemetryCollector {
71
139
  : { durationMs: Math.max(0, Math.floor(event.durationMs)) }),
72
140
  });
73
141
  }
74
- toHeaderValue() {
75
- const [first, ...rest] = this.#events;
76
- if (!first)
77
- return undefined;
78
- const aggregate = rest.reduce((acc, event) => ({
79
- provider: "smartproxy",
80
- cacheStatus: worseStatus(acc.cacheStatus, event.cacheStatus),
81
- cacheHit: acc.cacheHit && event.cacheHit,
82
- resolutionMs: acc.resolutionMs + event.resolutionMs,
83
- allocatorMs: sumOptional(acc.allocatorMs, event.allocatorMs),
84
- allocatorStatus: event.allocatorStatus ?? acc.allocatorStatus,
85
- allocatorBodyClass: event.allocatorBodyClass ?? acc.allocatorBodyClass,
86
- allocatorAttempts: sumOptional(acc.allocatorAttempts, event.allocatorAttempts),
87
- lockWaitMs: sumOptional(acc.lockWaitMs, event.lockWaitMs),
88
- redisReadMs: sumOptional(acc.redisReadMs, event.redisReadMs),
89
- redisWriteMs: sumOptional(acc.redisWriteMs, event.redisWriteMs),
90
- poolAgeMs: maxOptional(acc.poolAgeMs, event.poolAgeMs),
91
- poolExpiresInMs: maxOptional(acc.poolExpiresInMs, event.poolExpiresInMs),
92
- attempts: acc.attempts + event.attempts,
93
- refreshes: sumOptional(acc.refreshes, event.refreshes),
94
- }), first);
95
- const payload = {
96
- v: 1,
97
- proxy: {
98
- provider: "smartproxy",
99
- cacheStatus: aggregate.cacheStatus,
100
- cacheHit: aggregate.cacheHit,
101
- resolutionMs: aggregate.resolutionMs,
102
- ...(aggregate.allocatorMs !== undefined ? { allocatorMs: aggregate.allocatorMs } : {}),
103
- ...(aggregate.allocatorStatus !== undefined
104
- ? { allocatorStatus: aggregate.allocatorStatus }
105
- : {}),
106
- ...(aggregate.allocatorBodyClass !== undefined
107
- ? { allocatorBodyClass: aggregate.allocatorBodyClass }
108
- : {}),
109
- ...(aggregate.allocatorAttempts !== undefined
110
- ? { allocatorAttempts: aggregate.allocatorAttempts }
111
- : {}),
112
- ...(aggregate.lockWaitMs !== undefined ? { lockWaitMs: aggregate.lockWaitMs } : {}),
113
- ...(aggregate.redisReadMs !== undefined ? { redisReadMs: aggregate.redisReadMs } : {}),
114
- ...(aggregate.redisWriteMs !== undefined ? { redisWriteMs: aggregate.redisWriteMs } : {}),
115
- ...(aggregate.poolAgeMs !== undefined ? { poolAgeMs: aggregate.poolAgeMs } : {}),
116
- ...(aggregate.poolExpiresInMs !== undefined
117
- ? { poolExpiresInMs: aggregate.poolExpiresInMs }
118
- : {}),
119
- attempts: aggregate.attempts,
120
- ...(aggregate.refreshes !== undefined ? { refreshes: aggregate.refreshes } : {}),
121
- ...(this.#attempts.length > 0
142
+ toLogPayload() {
143
+ const aggregate = this.#aggregateResolution;
144
+ const attemptSamples = this.#attempts.map((attempt, index) => ({
145
+ n: index + 1,
146
+ a: attempt.attempt,
147
+ ...(attempt.poolIndex === undefined ? {} : { i: attempt.poolIndex }),
148
+ ...(attempt.proxyHash ? { h: attempt.proxyHash } : {}),
149
+ o: attempt.outcome,
150
+ ...(attempt.errorCode ? { c: attempt.errorCode } : {}),
151
+ ...(attempt.status === undefined ? {} : { s: attempt.status }),
152
+ ...(attempt.durationMs === undefined ? {} : { d: attempt.durationMs }),
153
+ }));
154
+ const failovers = this.#failovers.map((failover) => ({
155
+ v: failover.vendor,
156
+ ...(failover.nextVendor ? { nx: failover.nextVendor } : {}),
157
+ p: failover.phase,
158
+ r: failover.reason,
159
+ ...(failover.attempt === undefined ? {} : { a: failover.attempt }),
160
+ }));
161
+ if (!this.#lastSuccessfulResolution) {
162
+ if (!aggregate && failovers.length === 0)
163
+ return undefined;
164
+ return {
165
+ kind: "unresolved",
166
+ vendors: [...this.#unresolvedVendors],
167
+ ...(aggregate
122
168
  ? {
123
- attemptSamples: this.#attempts.map((attempt, index) => ({
124
- n: index + 1,
125
- a: attempt.attempt,
126
- ...(attempt.poolIndex === undefined ? {} : { i: attempt.poolIndex }),
127
- ...(attempt.proxyHash ? { h: attempt.proxyHash } : {}),
128
- o: attempt.outcome,
129
- ...(attempt.errorCode ? { c: attempt.errorCode } : {}),
130
- ...(attempt.status === undefined ? {} : { s: attempt.status }),
131
- ...(attempt.durationMs === undefined ? {} : { d: attempt.durationMs }),
132
- })),
169
+ cacheStatus: aggregate.cacheStatus,
170
+ cacheHit: aggregate.cacheHit,
171
+ resolutionMs: aggregate.resolutionMs,
172
+ ...(aggregate.allocatorMs !== undefined
173
+ ? { allocatorMs: aggregate.allocatorMs }
174
+ : {}),
175
+ ...(aggregate.allocatorStatus !== undefined
176
+ ? { allocatorStatus: aggregate.allocatorStatus }
177
+ : {}),
178
+ ...(aggregate.allocatorBodyClass !== undefined
179
+ ? { allocatorBodyClass: aggregate.allocatorBodyClass }
180
+ : {}),
181
+ ...(aggregate.allocatorAttempts !== undefined
182
+ ? { allocatorAttempts: aggregate.allocatorAttempts }
183
+ : {}),
184
+ ...(aggregate.lockWaitMs !== undefined ? { lockWaitMs: aggregate.lockWaitMs } : {}),
185
+ ...(aggregate.redisReadMs !== undefined
186
+ ? { redisReadMs: aggregate.redisReadMs }
187
+ : {}),
188
+ ...(aggregate.redisWriteMs !== undefined
189
+ ? { redisWriteMs: aggregate.redisWriteMs }
190
+ : {}),
191
+ ...(aggregate.poolAgeMs !== undefined ? { poolAgeMs: aggregate.poolAgeMs } : {}),
192
+ ...(aggregate.poolExpiresInMs !== undefined
193
+ ? { poolExpiresInMs: aggregate.poolExpiresInMs }
194
+ : {}),
195
+ attempts: aggregate.attempts,
196
+ ...(aggregate.refreshes !== undefined ? { refreshes: aggregate.refreshes } : {}),
133
197
  }
134
198
  : {}),
135
- },
136
- };
137
- const encoded = encodeBase64Url(JSON.stringify(payload));
138
- if (encoded.length > MAX_HEADER_BYTES)
199
+ ...(failovers.length > 0 ? { failovers } : {}),
200
+ ...(attemptSamples.length > 0 ? { attemptSamples } : {}),
201
+ };
202
+ }
203
+ // The serving vendor/protocol is the last successful resolution.
204
+ if (!aggregate)
139
205
  return undefined;
140
- return encoded;
206
+ const serving = this.#lastSuccessfulResolution;
207
+ return {
208
+ kind: "resolved",
209
+ provider: serving.provider,
210
+ ...(aggregate.userAgentSource ? { userAgentSource: aggregate.userAgentSource } : {}),
211
+ ...(serving.protocol ? { protocol: serving.protocol } : {}),
212
+ cacheStatus: aggregate.cacheStatus,
213
+ cacheHit: aggregate.cacheHit,
214
+ resolutionMs: aggregate.resolutionMs,
215
+ ...(aggregate.allocatorMs !== undefined ? { allocatorMs: aggregate.allocatorMs } : {}),
216
+ ...(aggregate.allocatorStatus !== undefined
217
+ ? { allocatorStatus: aggregate.allocatorStatus }
218
+ : {}),
219
+ ...(aggregate.allocatorBodyClass !== undefined
220
+ ? { allocatorBodyClass: aggregate.allocatorBodyClass }
221
+ : {}),
222
+ ...(aggregate.allocatorAttempts !== undefined
223
+ ? { allocatorAttempts: aggregate.allocatorAttempts }
224
+ : {}),
225
+ ...(aggregate.lockWaitMs !== undefined ? { lockWaitMs: aggregate.lockWaitMs } : {}),
226
+ ...(aggregate.redisReadMs !== undefined ? { redisReadMs: aggregate.redisReadMs } : {}),
227
+ ...(aggregate.redisWriteMs !== undefined ? { redisWriteMs: aggregate.redisWriteMs } : {}),
228
+ ...(aggregate.poolAgeMs !== undefined ? { poolAgeMs: aggregate.poolAgeMs } : {}),
229
+ ...(aggregate.poolExpiresInMs !== undefined
230
+ ? { poolExpiresInMs: aggregate.poolExpiresInMs }
231
+ : {}),
232
+ attempts: aggregate.attempts,
233
+ ...(aggregate.refreshes !== undefined ? { refreshes: aggregate.refreshes } : {}),
234
+ ...(attemptSamples.length > 0 ? { attemptSamples } : {}),
235
+ ...(this.#vendors.length > 1 ? { vendors: [...this.#vendors] } : {}),
236
+ ...(failovers.length > 0 ? { failovers } : {}),
237
+ };
238
+ }
239
+ toHeaderPayload(log) {
240
+ const attemptSamples = log.attemptSamples?.map((sample) => ({
241
+ n: sample.n,
242
+ a: sample.a,
243
+ ...(sample.i === undefined ? {} : { i: sample.i }),
244
+ ...(sample.h && PROXY_HEADER_HASH.test(sample.h)
245
+ ? { h: closedEnum(sample.h) }
246
+ : {}),
247
+ o: closedEnum(sample.o),
248
+ ...(sample.c && PROXY_HEADER_TOKEN.test(sample.c) ? { c: closedEnum(sample.c) } : {}),
249
+ ...(sample.s === undefined ? {} : { s: sample.s }),
250
+ ...(sample.d === undefined ? {} : { d: sample.d }),
251
+ }));
252
+ const failovers = log.failovers?.map((failover) => ({
253
+ ...failover,
254
+ v: closedEnum(failover.v),
255
+ ...(failover.nx ? { nx: closedEnum(failover.nx) } : {}),
256
+ p: closedEnum(failover.p),
257
+ r: closedEnum(failover.r),
258
+ }));
259
+ if (log.kind === "resolved") {
260
+ return {
261
+ ...log,
262
+ kind: closedEnum(log.kind),
263
+ provider: closedEnum(log.provider),
264
+ ...(log.userAgentSource ? { userAgentSource: closedEnum(log.userAgentSource) } : {}),
265
+ ...(log.protocol ? { protocol: closedEnum(log.protocol) } : {}),
266
+ cacheStatus: closedEnum(log.cacheStatus),
267
+ ...(log.allocatorBodyClass
268
+ ? { allocatorBodyClass: closedEnum(log.allocatorBodyClass) }
269
+ : {}),
270
+ ...(attemptSamples ? { attemptSamples } : {}),
271
+ ...(log.vendors ? { vendors: log.vendors.map((vendor) => closedEnum(vendor)) } : {}),
272
+ ...(failovers ? { failovers } : {}),
273
+ };
274
+ }
275
+ return {
276
+ ...log,
277
+ kind: closedEnum(log.kind),
278
+ vendors: log.vendors.map((vendor) => closedEnum(vendor)),
279
+ ...(log.cacheStatus ? { cacheStatus: closedEnum(log.cacheStatus) } : {}),
280
+ ...(log.allocatorBodyClass ? { allocatorBodyClass: closedEnum(log.allocatorBodyClass) } : {}),
281
+ ...(failovers ? { failovers } : {}),
282
+ ...(attemptSamples ? { attemptSamples } : {}),
283
+ };
284
+ }
285
+ toHeaderValue() {
286
+ const telemetry = new RequestTelemetry(createTraceContext());
287
+ telemetry.register(this);
288
+ return telemetry.toHeaderValue();
141
289
  }
142
290
  }