@apifuse/provider-sdk 2.2.0-beta.62 → 2.2.0-beta.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/AUTHORING.md +367 -9
  2. package/CHANGELOG.md +8 -0
  3. package/LICENSE +21 -0
  4. package/README.md +1 -0
  5. package/bin/apifuse-check.ts +84 -2
  6. package/bin/apifuse-dev.ts +11 -31
  7. package/bin/apifuse-migrate-deployment.ts +200 -0
  8. package/bin/apifuse-pack-check.ts +11 -4
  9. package/bin/apifuse-pack-types.ts +187 -4
  10. package/bin/apifuse-record.ts +44 -32
  11. package/bin/apifuse-submit-check.ts +9 -5
  12. package/bin/apifuse-test.ts +3 -1
  13. package/dist/cli/commands.d.ts +1 -1
  14. package/dist/cli/commands.js +11 -0
  15. package/dist/cli/deployment-intent.d.ts +178 -0
  16. package/dist/cli/deployment-intent.js +277 -0
  17. package/dist/cli/migrate-deployment-intent.d.ts +132 -0
  18. package/dist/cli/migrate-deployment-intent.js +1552 -0
  19. package/dist/cli/migrate-provider-shape.d.ts +5 -1
  20. package/dist/cli/migrate-provider-shape.js +4 -2
  21. package/dist/cli/resolver-runtime.d.ts +21 -0
  22. package/dist/cli/resolver-runtime.js +31 -0
  23. package/dist/define.d.ts +3 -0
  24. package/dist/define.js +5 -0
  25. package/dist/dev.d.ts +3 -1
  26. package/dist/dev.js +6 -1
  27. package/dist/engine.d.ts +35 -1
  28. package/dist/engine.js +21 -2
  29. package/dist/error-resolution.d.ts +1 -0
  30. package/dist/error-resolution.js +54 -0
  31. package/dist/errors.d.ts +39 -1
  32. package/dist/errors.js +50 -0
  33. package/dist/handle-meta.d.ts +36 -1
  34. package/dist/handle-meta.js +16 -0
  35. package/dist/handle.d.ts +23 -5
  36. package/dist/handle.js +54 -8
  37. package/dist/health-scenario.d.ts +38 -0
  38. package/dist/i18n/error-messages.d.ts +86 -0
  39. package/dist/i18n/error-messages.js +192 -0
  40. package/dist/i18n/index.d.ts +1 -0
  41. package/dist/i18n/index.js +1 -0
  42. package/dist/i18n/keys.d.ts +12 -0
  43. package/dist/i18n/keys.js +76 -5
  44. package/dist/index.d.ts +11 -3
  45. package/dist/index.js +9 -1
  46. package/dist/lint.d.ts +15 -0
  47. package/dist/lint.js +469 -82
  48. package/dist/provider.d.ts +6 -6
  49. package/dist/provider.js +3 -3
  50. package/dist/runtime/browser-telemetry-binding.d.ts +5 -0
  51. package/dist/runtime/browser-telemetry-binding.js +83 -0
  52. package/dist/runtime/browser-telemetry.d.ts +76 -0
  53. package/dist/runtime/browser-telemetry.js +165 -0
  54. package/dist/runtime/browser.d.ts +3 -0
  55. package/dist/runtime/browser.js +208 -47
  56. package/dist/runtime/cache-telemetry.d.ts +71 -0
  57. package/dist/runtime/cache-telemetry.js +177 -0
  58. package/dist/runtime/cache.js +67 -7
  59. package/dist/runtime/capability-response.d.ts +3 -0
  60. package/dist/runtime/capability-response.js +56 -0
  61. package/dist/runtime/capability-telemetry.d.ts +46 -0
  62. package/dist/runtime/capability-telemetry.js +68 -0
  63. package/dist/runtime/diagnostic-env.d.ts +3 -0
  64. package/dist/runtime/diagnostic-env.js +10 -1
  65. package/dist/runtime/engine-mode.d.ts +74 -0
  66. package/dist/runtime/engine-mode.js +152 -0
  67. package/dist/runtime/handle.js +9 -1
  68. package/dist/runtime/http-telemetry-guard.d.ts +10 -0
  69. package/dist/runtime/http-telemetry-guard.js +62 -10
  70. package/dist/runtime/http.js +141 -35
  71. package/dist/runtime/instrumentation.js +92 -13
  72. package/dist/runtime/ocr-telemetry.d.ts +82 -0
  73. package/dist/runtime/ocr-telemetry.js +192 -0
  74. package/dist/runtime/ocr.js +35 -8
  75. package/dist/runtime/request-telemetry.d.ts +2 -0
  76. package/dist/runtime/request-telemetry.js +2 -1
  77. package/dist/runtime/resolver-runtime-options.d.ts +14 -0
  78. package/dist/runtime/resolver-runtime-options.js +33 -0
  79. package/dist/runtime/resolver-shared.d.ts +3 -2
  80. package/dist/runtime/resolver-shared.js +4 -4
  81. package/dist/runtime/resolver-telemetry.d.ts +1 -0
  82. package/dist/runtime/resolver-telemetry.js +1 -1
  83. package/dist/runtime/resolver-vendors/browser.d.ts +2 -0
  84. package/dist/runtime/resolver-vendors/browser.js +46 -0
  85. package/dist/runtime/resolver-vendors/hosts.d.ts +21 -0
  86. package/dist/runtime/resolver-vendors/hosts.js +35 -0
  87. package/dist/runtime/resolver-vendors/hypersolutions.js +2 -2
  88. package/dist/runtime/resolver-vendors/types.d.ts +5 -4
  89. package/dist/runtime/resolver.d.ts +4 -1
  90. package/dist/runtime/resolver.js +46 -13
  91. package/dist/runtime/state-telemetry.d.ts +79 -0
  92. package/dist/runtime/state-telemetry.js +194 -0
  93. package/dist/runtime/state.d.ts +3 -0
  94. package/dist/runtime/state.js +26 -7
  95. package/dist/runtime/stealth-cookies.d.ts +5 -1
  96. package/dist/runtime/stealth-cookies.js +21 -1
  97. package/dist/runtime/stealth-owned-headers.d.ts +26 -0
  98. package/dist/runtime/stealth-owned-headers.js +37 -0
  99. package/dist/runtime/stealth-telemetry.d.ts +92 -0
  100. package/dist/runtime/stealth-telemetry.js +179 -0
  101. package/dist/runtime/stealth.d.ts +4 -1
  102. package/dist/runtime/stealth.js +228 -85
  103. package/dist/runtime/stt-telemetry.d.ts +77 -0
  104. package/dist/runtime/stt-telemetry.js +176 -0
  105. package/dist/runtime/stt.js +15 -6
  106. package/dist/runtime-boundary-lint.d.ts +132 -0
  107. package/dist/runtime-boundary-lint.js +586 -0
  108. package/dist/server/error-stack-frames.d.ts +35 -0
  109. package/dist/server/error-stack-frames.js +219 -0
  110. package/dist/server/index.d.ts +7 -0
  111. package/dist/server/index.js +4 -0
  112. package/dist/server/sdk-version.d.ts +3 -0
  113. package/dist/server/sdk-version.js +19 -0
  114. package/dist/server/self-test.js +1 -18
  115. package/dist/server/sensitive-values.d.ts +1 -1
  116. package/dist/server/sensitive-values.js +9 -0
  117. package/dist/server/serve-implementation.d.ts +51 -2
  118. package/dist/server/serve-implementation.js +337 -90
  119. package/dist/server/types.d.ts +1 -0
  120. package/dist/server/types.js +7 -0
  121. package/dist/stateful/stateful-provider-owner-forwarder.js +22 -0
  122. package/dist/stateful/stateful-provider-runtime-context.d.ts +3 -0
  123. package/dist/stateful/stateful-provider-runtime-context.js +1 -0
  124. package/dist/types.d.ts +123 -1
  125. package/dist/typescript-module.d.ts +39 -0
  126. package/dist/typescript-module.js +72 -0
  127. package/package.json +6 -1
  128. package/src/cli/commands.ts +14 -0
  129. package/src/cli/deployment-intent.ts +364 -0
  130. package/src/cli/migrate-deployment-intent.ts +1908 -0
  131. package/src/cli/migrate-provider-shape.ts +10 -4
  132. package/src/cli/resolver-runtime.ts +72 -0
  133. package/src/define.ts +13 -0
  134. package/src/dev.ts +9 -2
  135. package/src/engine.ts +38 -2
  136. package/src/error-resolution.ts +58 -0
  137. package/src/errors.ts +77 -1
  138. package/src/handle-meta.ts +51 -1
  139. package/src/handle.ts +92 -10
  140. package/src/health-scenario.ts +38 -0
  141. package/src/i18n/error-messages.ts +255 -0
  142. package/src/i18n/index.ts +1 -0
  143. package/src/i18n/keys.ts +80 -6
  144. package/src/index.ts +86 -0
  145. package/src/lint.ts +604 -91
  146. package/src/provider.ts +12 -0
  147. package/src/runtime/browser-telemetry-binding.ts +92 -0
  148. package/src/runtime/browser-telemetry.ts +289 -0
  149. package/src/runtime/browser.ts +249 -65
  150. package/src/runtime/cache-telemetry.ts +247 -0
  151. package/src/runtime/cache.ts +68 -17
  152. package/src/runtime/capability-response.ts +53 -0
  153. package/src/runtime/capability-telemetry.ts +101 -0
  154. package/src/runtime/diagnostic-env.ts +11 -1
  155. package/src/runtime/engine-mode.ts +233 -0
  156. package/src/runtime/handle.ts +9 -1
  157. package/src/runtime/http-telemetry-guard.ts +66 -13
  158. package/src/runtime/http.ts +168 -37
  159. package/src/runtime/instrumentation.ts +105 -16
  160. package/src/runtime/ocr-telemetry.ts +308 -0
  161. package/src/runtime/ocr.ts +114 -74
  162. package/src/runtime/request-telemetry.ts +2 -1
  163. package/src/runtime/resolver-runtime-options.ts +50 -0
  164. package/src/runtime/resolver-shared.ts +9 -4
  165. package/src/runtime/resolver-telemetry.ts +1 -1
  166. package/src/runtime/resolver-vendors/browser.ts +65 -7
  167. package/src/runtime/resolver-vendors/hosts.ts +43 -0
  168. package/src/runtime/resolver-vendors/hypersolutions.ts +2 -2
  169. package/src/runtime/resolver-vendors/types.ts +5 -4
  170. package/src/runtime/resolver.ts +64 -21
  171. package/src/runtime/state-telemetry.ts +298 -0
  172. package/src/runtime/state.ts +46 -45
  173. package/src/runtime/stealth-cookies.ts +24 -1
  174. package/src/runtime/stealth-owned-headers.ts +41 -0
  175. package/src/runtime/stealth-telemetry.ts +304 -0
  176. package/src/runtime/stealth.ts +355 -150
  177. package/src/runtime/stt-telemetry.ts +282 -0
  178. package/src/runtime/stt.ts +93 -71
  179. package/src/runtime-boundary-lint.ts +703 -0
  180. package/src/server/error-stack-frames.ts +214 -0
  181. package/src/server/index.ts +53 -0
  182. package/src/server/sdk-version.ts +22 -0
  183. package/src/server/self-test.ts +1 -21
  184. package/src/server/sensitive-values.ts +14 -0
  185. package/src/server/serve-implementation.ts +569 -108
  186. package/src/server/types.ts +7 -0
  187. package/src/stateful/stateful-provider-owner-forwarder.ts +23 -0
  188. package/src/stateful/stateful-provider-runtime-context.ts +4 -0
  189. package/src/types.ts +128 -1
  190. package/src/typescript-module.ts +100 -0
  191. package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +0 -6
  192. package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +0 -3
  193. package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +0 -10
  194. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-a.ts.txt +0 -3
  195. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-b.ts.txt +0 -3
  196. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-barrel.ts.txt +0 -2
  197. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-index.ts.txt +0 -3
  198. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-computed.ts.txt +0 -6
  199. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-a.ts.txt +0 -1
  200. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-b.ts.txt +0 -1
  201. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-index.ts.txt +0 -3
  202. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-barrel.ts.txt +0 -7
  203. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-catalog.ts.txt +0 -19
  204. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-docs.ts.txt +0 -6
  205. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-index.ts.txt +0 -3
  206. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-stores.ts.txt +0 -8
  207. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-indirect-config.ts.txt +0 -5
  208. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-nonstatic.ts.txt +0 -4
  209. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-package-index.ts.txt +0 -3
  210. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-index.ts.txt +0 -3
  211. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-leaf.ts.txt +0 -10
  212. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-one.ts.txt +0 -1
  213. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-two.ts.txt +0 -1
  214. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-index.ts.txt +0 -3
  215. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-one.ts.txt +0 -6
  216. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-two.ts.txt +0 -6
  217. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-mixed-index.ts.txt +0 -14
  218. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-registry.ts.txt +0 -3
  219. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-barrel.ts.txt +0 -2
  220. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-index.ts.txt +0 -3
  221. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-leaf.ts.txt +0 -3
  222. package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +0 -8
  223. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +0 -15
  224. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +0 -9
  225. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-kebab-operation-id.ts.txt +0 -17
  226. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +0 -5
  227. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +0 -24
  228. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +0 -16
  229. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-snake-operation-id.ts.txt +0 -21
  230. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-duplicate-provider.ts.txt +0 -11
  231. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-id-unresolved.ts.txt +0 -7
  232. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +0 -3
  233. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-many.ts.txt +0 -18
  234. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-one.ts.txt +0 -13
  235. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +0 -31
  236. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +0 -11
  237. package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +0 -11
  238. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +0 -11
  239. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +0 -21
  240. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +0 -11
  241. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +0 -14
  242. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-en.json +0 -1
  243. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ja.json +0 -1
  244. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ko.json +0 -1
  245. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-existing-operation-namespace-en.json +0 -8
  246. package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +0 -7
  247. package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +0 -6
  248. package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +0 -7
  249. package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +0 -6
  250. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-binding-ambiguous.ts.txt +0 -12
  251. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported-other.ts.txt +0 -7
  252. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported.ts.txt +0 -5
  253. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-key-ambiguous.ts.txt +0 -19
  254. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-shorthand.ts.txt +0 -9
  255. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-typed.ts.txt +0 -11
  256. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-unrelated.ts.txt +0 -13
  257. package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +0 -7
  258. package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +0 -7
  259. package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +0 -15
  260. package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +0 -4
  261. package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +0 -12
@@ -8,6 +8,7 @@ import type {
8
8
  } from "../../types.js";
9
9
  import { type BrowserClientOptions, createBrowserClient } from "../browser.js";
10
10
  import type { TraceRecorder } from "../trace.js";
11
+ import type { BrowserTelemetrySink } from "../browser-telemetry.js";
11
12
  import { resolverChallengeIssuingIdentity } from "./bindings.js";
12
13
  import { assertResolverHostAllowed, normalizedResolverHostname } from "./hosts.js";
13
14
  import {
@@ -31,6 +32,59 @@ type SupportedBrowserChallengeKind = keyof typeof SUCCESS_COOKIE_NAMES;
31
32
 
32
33
  type BrowserClientFactory = (options: BrowserClientOptions) => BrowserClient;
33
34
 
35
+ const RESOLVER_PAGE_METHODS = new Set([
36
+ "goto",
37
+ "evaluate",
38
+ "fill",
39
+ "click",
40
+ "type",
41
+ "waitForSelector",
42
+ "content",
43
+ "screenshot",
44
+ "cookies",
45
+ "url",
46
+ "title",
47
+ "userAgent",
48
+ ]);
49
+
50
+ function instrumentResolverBrowser(client: BrowserClient, recorder: TraceRecorder): BrowserClient {
51
+ const wrapPage = (page: BrowserPage): BrowserPage =>
52
+ new Proxy(page, {
53
+ get(target, property, receiver) {
54
+ const value = Reflect.get(target, property, receiver);
55
+ if (
56
+ typeof property !== "string" ||
57
+ !RESOLVER_PAGE_METHODS.has(property) ||
58
+ typeof value !== "function"
59
+ )
60
+ return value;
61
+ return (...args: unknown[]) =>
62
+ recorder.runSpan(`browser.page.${property}`, () => Reflect.apply(value, target, args));
63
+ },
64
+ });
65
+ return new Proxy(client, {
66
+ get(target, property, receiver) {
67
+ const value = Reflect.get(target, property, receiver);
68
+ if (property === "newPage" && typeof value === "function")
69
+ return () =>
70
+ recorder.runSpan("browser.newPage", async () =>
71
+ wrapPage(await Reflect.apply(value, target, [])),
72
+ );
73
+ if (property === "rawPage" && typeof value === "function")
74
+ return () =>
75
+ recorder.runSpan("browser.rawPage", async () =>
76
+ wrapPage(await Reflect.apply(value, target, [])),
77
+ );
78
+ if (property === "withIsolatedContext" && typeof value === "function")
79
+ return (handler: (page: BrowserPage) => Promise<unknown>) =>
80
+ recorder.runSpan("browser.withIsolatedContext", () =>
81
+ Reflect.apply(value, target, [(page: BrowserPage) => handler(wrapPage(page))]),
82
+ );
83
+ return value;
84
+ },
85
+ });
86
+ }
87
+
34
88
  let createResolverBrowserClient: BrowserClientFactory = createBrowserClient;
35
89
 
36
90
  /** Internal test seam; deliberately not re-exported from the package root. */
@@ -53,6 +107,7 @@ export interface BrowserResolverVendorOptions {
53
107
  readonly pollIntervalMs?: number;
54
108
  readonly allowedHosts: readonly string[];
55
109
  readonly createClient?: BrowserClientFactory;
110
+ readonly telemetry?: BrowserTelemetrySink;
56
111
  }
57
112
 
58
113
  export interface BrowserResolverVendorAdapter extends ResolverVendorAdapter {
@@ -67,9 +122,7 @@ export interface BrowserResolverVendorAdapter extends ResolverVendorAdapter {
67
122
 
68
123
  class BrowserSolveTimeoutError extends Error {
69
124
  constructor(blockedRequests: readonly string[]) {
70
- super(
71
- `Browser resolver solve budget elapsed${formatBlockedRequests(blockedRequests)}`,
72
- );
125
+ super(`Browser resolver solve budget elapsed${formatBlockedRequests(blockedRequests)}`);
73
126
  this.name = "BrowserSolveTimeoutError";
74
127
  }
75
128
  }
@@ -274,10 +327,7 @@ async function solveInPage(
274
327
  ],
275
328
  },
276
329
  async () => {
277
- const userAgent = await raceWithAbort(
278
- () => page.userAgent(),
279
- signal,
280
- );
330
+ const userAgent = await raceWithAbort(() => page.userAgent(), signal);
281
331
  try {
282
332
  await raceWithAbort(
283
333
  () =>
@@ -467,7 +517,15 @@ export function createBrowserResolverVendorAdapter(
467
517
  ...(proxyUrl === undefined ? {} : { proxy: proxyUrl }),
468
518
  requireCdpPool: cdpUrl !== undefined,
469
519
  serviceWorkers: "block",
520
+ telemetry: options.telemetry,
470
521
  });
522
+ /**
523
+ * Direct vendor callers without a telemetry sink keep the historical trace shape.
524
+ * Bound server requests record browser page spans under resolver.vendor.attempt,
525
+ * with resolver.vendor.cleanup as a sibling of the browser context span.
526
+ */
527
+ if (traceRecorder && options.telemetry)
528
+ client = instrumentResolverBrowser(client, traceRecorder);
471
529
  const contextOperation = client.withIsolatedContext(async (page) => {
472
530
  handlerEntered = true;
473
531
  return await solveInPage(
@@ -1,4 +1,25 @@
1
1
  import { ProviderError } from "../../errors.js";
2
+ import type { ProviderResolverVendor } from "../../types.js";
3
+
4
+ /**
5
+ * Exact SDK-owned service hosts each vendor's adapter may reach through its bound
6
+ * transport, in addition to the provider's declared `allowedHosts`. This table is
7
+ * the trust boundary for `ResolverVendorAdapter.transportAllowedHosts`: a
8
+ * declaration outside its vendor's entry is rejected, whoever supplied the adapter.
9
+ * Only Hyper's observed-IP reflector rides the identity-bound transport (ADR-0008
10
+ * v1.1 amend, PR #251); every other vendor talks to its own service directly.
11
+ * Frozen at runtime, not just in the type: the Hyper adapter hands its entry out by
12
+ * reference as `transportAllowedHosts`, so a mutable table would let any holder of a
13
+ * registry adapter widen the boundary for every later adapter in the process.
14
+ */
15
+ export const RESOLVER_VENDOR_TRANSPORT_HOSTS = Object.freeze({
16
+ "2captcha": Object.freeze([] as const),
17
+ browser: Object.freeze([] as const),
18
+ capmonster: Object.freeze([] as const),
19
+ capsolver: Object.freeze([] as const),
20
+ custom: Object.freeze([] as const),
21
+ hypersolutions: Object.freeze(["ip.hypersolutions.co"] as const),
22
+ }) satisfies Readonly<Record<ProviderResolverVendor, readonly string[]>>;
2
23
 
3
24
  export function normalizedResolverHostname(hostname: string): string {
4
25
  return hostname.trim().toLowerCase().replace(/\.$/, "");
@@ -36,3 +57,25 @@ export function assertResolverHostAllowed(
36
57
  fix: "Add the exact target hostname to the provider's allowedHosts declaration.",
37
58
  });
38
59
  }
60
+
61
+ export function assertResolverVendorTransportHosts(
62
+ vendor: ProviderResolverVendor,
63
+ declaredHosts: readonly string[],
64
+ ): void {
65
+ // A vendor id outside the table (only reachable from untyped callers) owns no hosts and
66
+ // is rejected below like any other overreach; `hasOwn` keeps prototype keys out too.
67
+ const ownedHosts: readonly string[] = Object.hasOwn(RESOLVER_VENDOR_TRANSPORT_HOSTS, vendor)
68
+ ? RESOLVER_VENDOR_TRANSPORT_HOSTS[vendor]
69
+ : [];
70
+ for (const declaredHost of declaredHosts) {
71
+ const normalizedHost = normalizedResolverHostname(declaredHost);
72
+ if (ownedHosts.some((host) => normalizedResolverHostname(host) === normalizedHost)) continue;
73
+ throw new ProviderError(
74
+ `Resolver vendor "${vendor}" may not declare transport host "${normalizedHost}"`,
75
+ {
76
+ code: "RESOLVER_VENDOR_HOST_NOT_ALLOWED",
77
+ fix: "Remove the host from transportAllowedHosts: an adapter reaches only the provider's allowedHosts plus the SDK-owned service hosts of its vendor.",
78
+ },
79
+ );
80
+ }
81
+ }
@@ -3,7 +3,7 @@ import { isIP } from "node:net";
3
3
  import type { ChallengeSolution, ProviderChallenge } from "../../types.js";
4
4
  import { recordPaidResolverCreate } from "../resolver-usage.js";
5
5
  import type { TraceRecorder } from "../trace.js";
6
- import { assertResolverHostAllowed } from "./hosts.js";
6
+ import { assertResolverHostAllowed, RESOLVER_VENDOR_TRANSPORT_HOSTS } from "./hosts.js";
7
7
  import {
8
8
  ResolverChallengeVerdictError,
9
9
  type ResolverIdentity,
@@ -21,7 +21,7 @@ const HYPER_IP_URL = "https://ip.hypersolutions.co/ip";
21
21
  * egress address the upstream will see. The payload-generation POST carries no
22
22
  * identity and goes direct, as in the measured zozotown source.
23
23
  */
24
- const HYPER_TRANSPORT_HOSTS = ["ip.hypersolutions.co"] as const;
24
+ const HYPER_TRANSPORT_HOSTS = RESOLVER_VENDOR_TRANSPORT_HOSTS.hypersolutions;
25
25
  const IP_RESPONSE_MAX_BYTES = 4_096;
26
26
  /** Measured bound shared by the script, the Hyper envelope, and the payload submission. */
27
27
  const BODY_MAX_BYTES = 1_000_000;
@@ -157,10 +157,11 @@ export interface ResolverVendorAdapter {
157
157
  readonly id: ProviderResolverVendor;
158
158
  readonly requiresTransport?: boolean | ((kind: ProviderChallengeKind) => boolean);
159
159
  /**
160
- * Exact SDK-owned service hosts this adapter may reach through its bound transport.
161
- * Honored for every adapter the chain runs, so whoever supplies `adapters` to
162
- * `createResolverClient` is the trust boundary; the engine path
163
- * (`createResolverClientFromEnv`) only constructs registry adapters.
160
+ * Exact SDK-owned service hosts this adapter may reach through its bound transport,
161
+ * in addition to the provider's `allowedHosts`. Every host must appear in the
162
+ * SDK-owned `RESOLVER_VENDOR_TRANSPORT_HOSTS` entry for `id`; the chain rejects any
163
+ * other declaration with `RESOLVER_VENDOR_HOST_NOT_ALLOWED`, whoever supplied the
164
+ * adapter. The transport handed to `solve` is revoked once `solve` settles.
164
165
  */
165
166
  readonly transportAllowedHosts?: readonly string[];
166
167
  supports(kind: ProviderChallengeKind): boolean;
@@ -29,7 +29,10 @@ import {
29
29
  import { createBrowserResolverVendorAdapter } from "./resolver-vendors/browser.js";
30
30
  import { createCapsolverResolverVendorAdapter } from "./resolver-vendors/capsolver.js";
31
31
  import { createHypersolutionsResolverVendorAdapter } from "./resolver-vendors/hypersolutions.js";
32
- import { assertResolverHostAllowed } from "./resolver-vendors/hosts.js";
32
+ import {
33
+ assertResolverHostAllowed,
34
+ assertResolverVendorTransportHosts,
35
+ } from "./resolver-vendors/hosts.js";
33
36
  import { createTwoCaptchaResolverVendorAdapter } from "./resolver-vendors/twocaptcha.js";
34
37
  import {
35
38
  RESOLVER_VENDOR_CAPABILITIES,
@@ -63,6 +66,7 @@ import {
63
66
  } from "./resolver-config.js";
64
67
  import { DEFAULT_STEALTH_PROFILE } from "./stealth.js";
65
68
  import type { TraceRecorder } from "./trace.js";
69
+ import type { BrowserTelemetrySink } from "./browser-telemetry.js";
66
70
  import type {
67
71
  ResolverTelemetryErrorClass,
68
72
  ResolverTelemetryPhase,
@@ -127,6 +131,8 @@ export interface ResolverRuntimeOptions {
127
131
  readonly cache?: ProviderCache;
128
132
  /** Optional request-scoped observability sink; never used as resolver identity. */
129
133
  readonly telemetry?: ResolverTelemetrySink;
134
+ /** Request-scoped browser sink used by the resolver-owned browser vendor. */
135
+ readonly browserTelemetry?: BrowserTelemetrySink;
130
136
  /** Inputs for SDK-owned lazy proxy resolution. The SDK never accepts a caller-built identity. */
131
137
  readonly proxyIntent?: {
132
138
  readonly mode: ProviderProxyMode;
@@ -222,6 +228,7 @@ export type ResolverAdapterFactory = (
222
228
  configuration: string | undefined,
223
229
  timeoutMs: number,
224
230
  allowedHosts: readonly string[],
231
+ telemetry?: BrowserTelemetrySink,
225
232
  ) => ResolverVendorAdapter;
226
233
 
227
234
  const resolverAdapterRegistry: Partial<Record<ProviderResolverVendor, ResolverAdapterFactory>> = {
@@ -242,11 +249,12 @@ const resolverAdapterRegistry: Partial<Record<ProviderResolverVendor, ResolverAd
242
249
  timeoutMs,
243
250
  });
244
251
  },
245
- browser(configuration, timeoutMs, allowedHosts) {
252
+ browser(configuration, timeoutMs, allowedHosts, telemetry) {
246
253
  return createBrowserResolverVendorAdapter({
247
254
  allowedHosts,
248
255
  cdpUrl: configuration,
249
256
  timeoutMs,
257
+ telemetry,
250
258
  });
251
259
  },
252
260
  hypersolutions(configuration, timeoutMs, allowedHosts) {
@@ -306,7 +314,7 @@ const KNOWN_UNIMPLEMENTED_RESOLVER_VENDORS: ReadonlySet<ProviderResolverVendor>
306
314
  type ResolverChainEntry = {
307
315
  readonly id: ProviderResolverVendor;
308
316
  supports(kind: ProviderChallengeKind): boolean;
309
- createAdapter(): ResolverVendorAdapter;
317
+ createAdapter(browserTelemetry?: BrowserTelemetrySink): ResolverVendorAdapter;
310
318
  };
311
319
 
312
320
  function normalizedEnvValue(env: EnvLike, key: string): string | undefined {
@@ -365,6 +373,7 @@ function createAdapter(
365
373
  timeoutMs: number,
366
374
  allowedHosts: readonly string[],
367
375
  adapterFactories: Partial<Readonly<Record<ProviderResolverVendor, ResolverAdapterFactory>>>,
376
+ browserTelemetry?: BrowserTelemetrySink,
368
377
  ): ResolverVendorAdapter {
369
378
  const factory = adapterFactories[vendor.vendor];
370
379
  if (!factory && !KNOWN_UNIMPLEMENTED_RESOLVER_VENDORS.has(vendor.vendor)) {
@@ -377,7 +386,7 @@ function createAdapter(
377
386
  }
378
387
 
379
388
  if (factory) {
380
- return factory(vendor.configuration, timeoutMs, allowedHosts);
389
+ return factory(vendor.configuration, timeoutMs, allowedHosts, browserTelemetry);
381
390
  }
382
391
  return createUnavailableAdapter(vendor.vendor, "not_implemented");
383
392
  }
@@ -480,15 +489,26 @@ function sanitizeCauseMessage(message: string): string {
480
489
  .slice(0, 512);
481
490
  }
482
491
 
492
+ function assertResolverTransportLive(revoked: boolean): void {
493
+ if (!revoked) return;
494
+ throw new ProviderError("Resolver transport was revoked when the vendor solve settled", {
495
+ code: "RESOLVER_TRANSPORT_REVOKED",
496
+ fix: "Complete every bound-transport call before solve() settles; the transport is per-attempt and must not be retained.",
497
+ });
498
+ }
499
+
483
500
  function restrictResolverTransport(
484
501
  transport: ResolverVendorTransport,
485
502
  allowedHosts: readonly string[],
486
- ): ResolverVendorTransport {
487
- return {
503
+ ): { readonly transport: ResolverVendorTransport; revoke(): void } {
504
+ // A retained reference must fail closed once the adapter's solve has settled.
505
+ let revoked = false;
506
+ const restricted: ResolverVendorTransport = {
488
507
  sessionHeaders: transport.sessionHeaders,
489
508
  ...(transport.getCookie
490
509
  ? {
491
510
  getCookie(name, url) {
511
+ assertResolverTransportLive(revoked);
492
512
  // Jar reads are gated like fetches: an adapter may only read state for declared hosts.
493
513
  assertResolverHostAllowed(url, allowedHosts);
494
514
  return transport.getCookie?.(name, url);
@@ -496,6 +516,7 @@ function restrictResolverTransport(
496
516
  }
497
517
  : {}),
498
518
  async fetch(url, init) {
519
+ assertResolverTransportLive(revoked);
499
520
  // Empty declarations remain deny-by-default, matching the adapter-factory/browser path.
500
521
  assertResolverHostAllowed(url, allowedHosts);
501
522
  const response = await transport.fetch(url, { ...init, redirect: "manual" });
@@ -511,6 +532,12 @@ function restrictResolverTransport(
511
532
  return response;
512
533
  },
513
534
  };
535
+ return {
536
+ transport: restricted,
537
+ revoke() {
538
+ revoked = true;
539
+ },
540
+ };
514
541
  }
515
542
 
516
543
  function safeCause(error: ResolverVendorUnavailableError): ResolverChainAttempt["cause"] {
@@ -1042,7 +1069,8 @@ async function resolveResolverIdentity(
1042
1069
  }
1043
1070
 
1044
1071
  function createChainTelemetryBinding(options: Parameters<typeof createResolverChainClient>[0]) {
1045
- return (telemetry: ResolverTelemetrySink) => createResolverChainClient({ ...options, telemetry });
1072
+ return (telemetry: ResolverTelemetrySink, browserTelemetry?: BrowserTelemetrySink) =>
1073
+ createResolverChainClient({ ...options, telemetry, browserTelemetry });
1046
1074
  }
1047
1075
 
1048
1076
  function createResolverChainClient(options: {
@@ -1059,6 +1087,7 @@ function createResolverChainClient(options: {
1059
1087
  readonly clientProfile?: string;
1060
1088
  readonly allowedHosts?: readonly string[];
1061
1089
  readonly telemetry?: ResolverTelemetrySink;
1090
+ readonly browserTelemetry?: BrowserTelemetrySink;
1062
1091
  }): ResolverChainClient {
1063
1092
  assertClientProfileTransportContract(options.clientProfile, options.transport);
1064
1093
  const cache =
@@ -1167,7 +1196,7 @@ function createResolverChainClient(options: {
1167
1196
  }
1168
1197
  const attempts: ResolverChainAttempt[] = [];
1169
1198
  for (const [entryIndex, entry] of supportingEntries.entries()) {
1170
- const adapter = entry.createAdapter();
1199
+ const adapter = entry.createAdapter(options.browserTelemetry);
1171
1200
  const attemptStartedAt = Date.now();
1172
1201
  const diagnostics: ResolverAttemptDiagnostics = {};
1173
1202
  const telemetryTraceRecorder = createResolverTelemetryTraceRecorder({
@@ -1179,7 +1208,11 @@ function createResolverChainClient(options: {
1179
1208
  });
1180
1209
  let solution: ChallengeSolution;
1181
1210
  try {
1182
- const solveAttempt = () => {
1211
+ const solveAttempt = async () => {
1212
+ // Boundary first: an overreaching declaration is a caller fault even when no
1213
+ // transport is configured, not a "missing_transport" vendor unavailability.
1214
+ const adapterHosts = adapter.transportAllowedHosts ?? [];
1215
+ assertResolverVendorTransportHosts(adapter.id, adapterHosts);
1183
1216
  const requiresTransport = adapterRequiresTransport(adapter, challenge.kind);
1184
1217
  const unrestrictedTransport =
1185
1218
  options.transport ??
@@ -1192,10 +1225,10 @@ function createResolverChainClient(options: {
1192
1225
  if (requiresTransport && unrestrictedTransport === undefined) {
1193
1226
  throw new ResolverVendorUnavailableError(adapter.id, "missing_transport");
1194
1227
  }
1195
- const transport = unrestrictedTransport
1228
+ const boundTransport = unrestrictedTransport
1196
1229
  ? restrictResolverTransport(unrestrictedTransport, [
1197
1230
  ...(options.allowedHosts ?? []),
1198
- ...(adapter.transportAllowedHosts ?? []),
1231
+ ...adapterHosts,
1199
1232
  ])
1200
1233
  : undefined;
1201
1234
  const usage: ResolverPaidUsageContext = {
@@ -1209,14 +1242,18 @@ function createResolverChainClient(options: {
1209
1242
  }
1210
1243
  : {}),
1211
1244
  };
1212
- return adapter.solve(
1213
- challenge,
1214
- identity,
1215
- signal,
1216
- telemetryTraceRecorder,
1217
- transport,
1218
- usage,
1219
- );
1245
+ try {
1246
+ return await adapter.solve(
1247
+ challenge,
1248
+ identity,
1249
+ signal,
1250
+ telemetryTraceRecorder,
1251
+ boundTransport?.transport,
1252
+ usage,
1253
+ );
1254
+ } finally {
1255
+ boundTransport?.revoke();
1256
+ }
1220
1257
  };
1221
1258
  solution = traceRecorder
1222
1259
  ? await traceRecorder.runSpan("resolver.vendor.attempt", solveAttempt, {
@@ -1334,7 +1371,7 @@ function createResolverChainClient(options: {
1334
1371
  },
1335
1372
  };
1336
1373
  resolverCaches.set(client, cache ?? null);
1337
- const reusableOptions = { ...options, telemetry: undefined };
1374
+ const reusableOptions = { ...options, telemetry: undefined, browserTelemetry: undefined };
1338
1375
  registerResolverTelemetryBinding(client, createChainTelemetryBinding(reusableOptions));
1339
1376
  return client;
1340
1377
  }
@@ -1352,6 +1389,10 @@ export function createResolverClient(options: {
1352
1389
  readonly allowedHosts?: readonly string[];
1353
1390
  readonly telemetry?: ResolverTelemetrySink;
1354
1391
  }): ResolverChainClient {
1392
+ for (const adapter of options.adapters) {
1393
+ // Fail at construction, not on the first solve, when a supplied adapter oversteps its vendor.
1394
+ assertResolverVendorTransportHosts(adapter.id, adapter.transportAllowedHosts ?? []);
1395
+ }
1355
1396
  return createResolverChainClient({
1356
1397
  kinds: options.kinds,
1357
1398
  entries: options.adapters.map((adapter) => ({
@@ -1459,12 +1500,13 @@ function createResolverClientFromEnvInternal(
1459
1500
  return {
1460
1501
  id: vendor,
1461
1502
  supports: (kind: ProviderChallengeKind) => resolverVendorSupports(vendor, kind),
1462
- createAdapter: () =>
1503
+ createAdapter: (browserTelemetry) =>
1463
1504
  createAdapter(
1464
1505
  resolveVendorAvailability(vendor, env),
1465
1506
  timeoutMs,
1466
1507
  allowedHosts,
1467
1508
  adapterFactories,
1509
+ browserTelemetry,
1468
1510
  ),
1469
1511
  };
1470
1512
  }),
@@ -1477,6 +1519,7 @@ function createResolverClientFromEnvInternal(
1477
1519
  clientProfile: config.clientProfile,
1478
1520
  allowedHosts,
1479
1521
  telemetry: options.telemetry,
1522
+ browserTelemetry: options.browserTelemetry,
1480
1523
  });
1481
1524
  }
1482
1525