@apifuse/provider-sdk 2.2.0-beta.3 → 2.2.0-beta.31

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 (342) hide show
  1. package/AUTHORING.md +493 -5
  2. package/CHANGELOG.md +131 -1
  3. package/README.md +52 -6
  4. package/SUBMISSION.md +1 -1
  5. package/bin/apifuse-check.ts +106 -62
  6. package/bin/apifuse-create.ts +1 -1
  7. package/bin/apifuse-dev.ts +63 -55
  8. package/bin/apifuse-pack-check.ts +22 -2
  9. package/bin/apifuse-pack-smoke.ts +78 -82
  10. package/bin/apifuse-pack-types.ts +583 -0
  11. package/bin/apifuse-perf.ts +59 -140
  12. package/bin/apifuse-record.ts +698 -113
  13. package/bin/apifuse-submit-check.ts +517 -44
  14. package/bin/apifuse-sync-assets.ts +117 -0
  15. package/bin/apifuse.ts +1 -1
  16. package/bin/submit-check-delimited-text.ts +50 -0
  17. package/bin/submit-check-xml.ts +1 -1
  18. package/dist/auth-turn/index.d.ts +4 -4
  19. package/dist/auth-turn/index.js +1 -1
  20. package/dist/auth.d.ts +16 -2
  21. package/dist/auth.js +76 -18
  22. package/dist/ceremonies/index.d.ts +9 -1
  23. package/dist/ceremonies/index.js +117 -29
  24. package/dist/cli/commands.d.ts +1 -1
  25. package/dist/cli/commands.js +8 -0
  26. package/dist/cli/create.d.ts +3 -0
  27. package/dist/cli/create.js +34 -35
  28. package/dist/cli/prompt-assets.d.ts +80 -0
  29. package/dist/cli/prompt-assets.js +743 -0
  30. package/dist/cli/templates/provider/AGENTS.md.tpl +17 -8
  31. package/dist/cli/templates/provider/README.md.tpl +4 -4
  32. package/dist/config/loader.d.ts +176 -17
  33. package/dist/config/loader.js +434 -161
  34. package/dist/contract-serialization.d.ts +2 -2
  35. package/dist/contract-serialization.js +7 -14
  36. package/dist/contract-types.d.ts +3 -2
  37. package/dist/contract.d.ts +3 -3
  38. package/dist/contract.js +6 -6
  39. package/dist/declaration-validation.d.ts +23 -0
  40. package/dist/declaration-validation.js +159 -0
  41. package/dist/define.d.ts +13 -1
  42. package/dist/define.js +391 -122
  43. package/dist/dev.d.ts +1 -1
  44. package/dist/dev.js +1 -1
  45. package/dist/error-resolution.d.ts +4 -0
  46. package/dist/error-resolution.js +123 -0
  47. package/dist/errors.d.ts +19 -1
  48. package/dist/errors.js +41 -3
  49. package/dist/fixture-sanitization.d.ts +26 -0
  50. package/dist/fixture-sanitization.js +216 -0
  51. package/dist/i18n/catalog.d.ts +2 -2
  52. package/dist/i18n/catalog.js +4 -10
  53. package/dist/i18n/index.d.ts +2 -2
  54. package/dist/i18n/index.js +2 -2
  55. package/dist/i18n/keys.d.ts +2 -2
  56. package/dist/index.d.ts +50 -42
  57. package/dist/index.js +41 -37
  58. package/dist/lint.d.ts +6 -1
  59. package/dist/lint.js +370 -18
  60. package/dist/native-address.d.ts +43 -0
  61. package/dist/native-address.js +281 -0
  62. package/dist/native-egress-policy.d.ts +31 -0
  63. package/dist/native-egress-policy.js +288 -0
  64. package/dist/observability.d.ts +5 -2
  65. package/dist/observability.js +48 -1
  66. package/dist/provider.d.ts +13 -11
  67. package/dist/provider.js +10 -9
  68. package/dist/public-schema-field-lint.d.ts +1 -1
  69. package/dist/recipes/gov-api.js +1 -1
  70. package/dist/runtime/auth-flow.d.ts +3 -1
  71. package/dist/runtime/auth-flow.js +8 -3
  72. package/dist/runtime/browser.d.ts +1 -1
  73. package/dist/runtime/browser.js +138 -40
  74. package/dist/runtime/cache.d.ts +2 -1
  75. package/dist/runtime/cache.js +173 -23
  76. package/dist/runtime/choice-wordlist.d.ts +9 -0
  77. package/dist/runtime/choice-wordlist.js +138 -0
  78. package/dist/runtime/choice.d.ts +14 -1
  79. package/dist/runtime/choice.js +566 -101
  80. package/dist/runtime/credential.d.ts +1 -1
  81. package/dist/runtime/credential.js +1 -1
  82. package/dist/runtime/env.d.ts +1 -1
  83. package/dist/runtime/executor.d.ts +1 -1
  84. package/dist/runtime/executor.js +25 -3
  85. package/dist/runtime/http.d.ts +3 -2
  86. package/dist/runtime/http.js +517 -55
  87. package/dist/runtime/insights.d.ts +1 -1
  88. package/dist/runtime/insights.js +6 -13
  89. package/dist/runtime/instrumentation.d.ts +2 -2
  90. package/dist/runtime/instrumentation.js +371 -23
  91. package/dist/runtime/keyring.js +1 -1
  92. package/dist/runtime/namespace.js +1 -1
  93. package/dist/runtime/native-network-errors.d.ts +33 -0
  94. package/dist/runtime/native-network-errors.js +69 -0
  95. package/dist/runtime/native-network.d.ts +96 -0
  96. package/dist/runtime/native-network.js +1232 -0
  97. package/dist/runtime/ocr.d.ts +29 -0
  98. package/dist/runtime/ocr.js +440 -0
  99. package/dist/runtime/otlp.d.ts +1 -1
  100. package/dist/runtime/perf.d.ts +1 -1
  101. package/dist/runtime/provider.d.ts +1 -1
  102. package/dist/runtime/provider.js +1 -2
  103. package/dist/runtime/proxy-errors.d.ts +1 -1
  104. package/dist/runtime/proxy-errors.js +9 -7
  105. package/dist/runtime/proxy-nodemaven.d.ts +56 -0
  106. package/dist/runtime/proxy-nodemaven.js +146 -0
  107. package/dist/runtime/proxy-retry-policy.d.ts +2 -2
  108. package/dist/runtime/proxy-retry-policy.js +2 -2
  109. package/dist/runtime/proxy-telemetry.d.ts +2 -1
  110. package/dist/runtime/proxy-telemetry.js +58 -52
  111. package/dist/runtime/redirects.d.ts +29 -0
  112. package/dist/runtime/redirects.js +36 -0
  113. package/dist/runtime/redis.d.ts +1 -1
  114. package/dist/runtime/redis.js +5 -5
  115. package/dist/runtime/request-options.d.ts +68 -1
  116. package/dist/runtime/request-options.js +548 -0
  117. package/dist/runtime/resolver-config.d.ts +6 -0
  118. package/dist/runtime/resolver-config.js +6 -0
  119. package/dist/runtime/resolver-public.d.ts +1 -0
  120. package/dist/runtime/resolver-public.js +1 -0
  121. package/dist/runtime/resolver-shared.d.ts +3 -0
  122. package/dist/runtime/resolver-shared.js +12 -0
  123. package/dist/runtime/resolver-vendors/bindings.d.ts +48 -0
  124. package/dist/runtime/resolver-vendors/bindings.js +40 -0
  125. package/dist/runtime/resolver-vendors/browser.d.ts +20 -0
  126. package/dist/runtime/resolver-vendors/browser.js +282 -0
  127. package/dist/runtime/resolver-vendors/hosts.d.ts +2 -0
  128. package/dist/runtime/resolver-vendors/hosts.js +33 -0
  129. package/dist/runtime/resolver-vendors/twocaptcha.d.ts +24 -0
  130. package/dist/runtime/resolver-vendors/twocaptcha.js +368 -0
  131. package/dist/runtime/resolver-vendors/types.d.ts +83 -0
  132. package/dist/runtime/resolver-vendors/types.js +69 -0
  133. package/dist/runtime/resolver.d.ts +59 -0
  134. package/dist/runtime/resolver.js +705 -0
  135. package/dist/runtime/secrets.d.ts +27 -0
  136. package/dist/runtime/secrets.js +51 -0
  137. package/dist/runtime/state.d.ts +5 -2
  138. package/dist/runtime/state.js +280 -74
  139. package/dist/runtime/stealth-cookies.d.ts +20 -0
  140. package/dist/runtime/stealth-cookies.js +111 -0
  141. package/dist/runtime/stealth.d.ts +30 -5
  142. package/dist/runtime/stealth.js +523 -259
  143. package/dist/runtime/stt.d.ts +1 -1
  144. package/dist/runtime/stt.js +12 -27
  145. package/dist/runtime/timeout.d.ts +5 -0
  146. package/dist/runtime/timeout.js +12 -0
  147. package/dist/runtime/trace.d.ts +2 -2
  148. package/dist/runtime/trace.js +2 -4
  149. package/dist/runtime/waterfall.d.ts +1 -1
  150. package/dist/schema.d.ts +1 -1
  151. package/dist/schema.js +7 -15
  152. package/dist/serve.d.ts +1 -1
  153. package/dist/serve.js +1 -1
  154. package/dist/server/index.d.ts +7 -7
  155. package/dist/server/index.js +6 -6
  156. package/dist/server/self-test-input-tokens.d.ts +2 -1
  157. package/dist/server/self-test-input-tokens.js +18 -14
  158. package/dist/server/self-test-redaction.d.ts +1 -1
  159. package/dist/server/self-test-redaction.js +1 -1
  160. package/dist/server/self-test.d.ts +117 -3
  161. package/dist/server/self-test.js +787 -151
  162. package/dist/server/serve-implementation.d.ts +210 -0
  163. package/dist/server/serve-implementation.js +2078 -0
  164. package/dist/server/serve.d.ts +1 -70
  165. package/dist/server/serve.js +1 -1143
  166. package/dist/server/types.d.ts +34 -9
  167. package/dist/server/types.js +8 -1
  168. package/dist/stateful/errors.d.ts +19 -0
  169. package/dist/stateful/errors.js +24 -0
  170. package/dist/stateful/http-provider-event-emitter.d.ts +40 -0
  171. package/dist/stateful/http-provider-event-emitter.js +237 -0
  172. package/dist/stateful/http-session-owner-registry.d.ts +44 -0
  173. package/dist/stateful/http-session-owner-registry.js +210 -0
  174. package/dist/stateful/index.d.ts +18 -0
  175. package/dist/stateful/index.js +18 -0
  176. package/dist/stateful/provider-event-delivery-failures.d.ts +32 -0
  177. package/dist/stateful/provider-event-delivery-failures.js +43 -0
  178. package/dist/stateful/provider-event-pipeline-metrics.d.ts +46 -0
  179. package/dist/stateful/provider-event-pipeline-metrics.js +48 -0
  180. package/dist/stateful/provider-event-pipeline.d.ts +50 -0
  181. package/dist/stateful/provider-event-pipeline.js +1 -0
  182. package/dist/stateful/provider-events.d.ts +101 -0
  183. package/dist/stateful/provider-events.js +289 -0
  184. package/dist/stateful/session-key.d.ts +15 -0
  185. package/dist/stateful/session-key.js +86 -0
  186. package/dist/stateful/stateful-provider-adapter-context.d.ts +5 -0
  187. package/dist/stateful/stateful-provider-adapter-context.js +42 -0
  188. package/dist/stateful/stateful-provider-adapter-metrics.d.ts +15 -0
  189. package/dist/stateful/stateful-provider-adapter-metrics.js +21 -0
  190. package/dist/stateful/stateful-provider-adapter.d.ts +98 -0
  191. package/dist/stateful/stateful-provider-adapter.js +287 -0
  192. package/dist/stateful/stateful-provider-observability.d.ts +62 -0
  193. package/dist/stateful/stateful-provider-observability.js +161 -0
  194. package/dist/stateful/stateful-provider-owner-forwarder.d.ts +41 -0
  195. package/dist/stateful/stateful-provider-owner-forwarder.js +215 -0
  196. package/dist/stateful/stateful-provider-runtime-context.d.ts +32 -0
  197. package/dist/stateful/stateful-provider-runtime-context.js +60 -0
  198. package/dist/stateful/stateful-provider-runtime-executor.d.ts +34 -0
  199. package/dist/stateful/stateful-provider-runtime-executor.js +52 -0
  200. package/dist/stateful/stateful-provider-session-routing.d.ts +67 -0
  201. package/dist/stateful/stateful-provider-session-routing.js +345 -0
  202. package/dist/stateful/stateful-provider-session-runtime.d.ts +98 -0
  203. package/dist/stateful/stateful-provider-session-runtime.js +245 -0
  204. package/dist/stateful-signing.d.ts +18 -0
  205. package/dist/stateful-signing.js +27 -0
  206. package/dist/stealth/profiles.d.ts +1 -1
  207. package/dist/stealth/profiles.js +21 -21
  208. package/dist/stream-evidence.d.ts +74 -0
  209. package/dist/stream-evidence.js +785 -0
  210. package/dist/stream.d.ts +1 -1
  211. package/dist/stream.js +7 -1
  212. package/dist/testing/index.d.ts +3 -2
  213. package/dist/testing/index.js +3 -2
  214. package/dist/testing/run.d.ts +32 -2
  215. package/dist/testing/run.js +488 -28
  216. package/dist/types.d.ts +566 -19
  217. package/dist/types.js +1 -0
  218. package/dist/user-input.d.ts +30 -0
  219. package/dist/user-input.js +66 -0
  220. package/package.json +42 -7
  221. package/src/auth-turn/index.ts +2 -2
  222. package/src/auth.ts +146 -86
  223. package/src/ceremonies/index.ts +167 -92
  224. package/src/cli/commands.ts +10 -0
  225. package/src/cli/create.ts +42 -35
  226. package/src/cli/prompt-assets.ts +865 -0
  227. package/src/cli/templates/provider/AGENTS.md.tpl +17 -8
  228. package/src/cli/templates/provider/README.md.tpl +4 -4
  229. package/src/config/loader.ts +667 -289
  230. package/src/contract-serialization.ts +10 -18
  231. package/src/contract-types.ts +3 -2
  232. package/src/contract.ts +14 -28
  233. package/src/declaration-validation.ts +202 -0
  234. package/src/define.ts +631 -495
  235. package/src/dev.ts +4 -9
  236. package/src/error-resolution.ts +128 -0
  237. package/src/errors.ts +56 -11
  238. package/src/fixture-sanitization.ts +247 -0
  239. package/src/i18n/catalog.ts +10 -32
  240. package/src/i18n/index.ts +2 -2
  241. package/src/i18n/keys.ts +5 -11
  242. package/src/index.ts +158 -44
  243. package/src/lint.ts +488 -154
  244. package/src/native-address.ts +340 -0
  245. package/src/native-egress-policy.ts +358 -0
  246. package/src/observability.ts +51 -1
  247. package/src/provider.ts +66 -11
  248. package/src/public-schema-field-lint.ts +7 -33
  249. package/src/recipes/gov-api.ts +2 -5
  250. package/src/runtime/auth-flow.ts +13 -7
  251. package/src/runtime/browser.ts +252 -207
  252. package/src/runtime/cache.ts +209 -81
  253. package/src/runtime/choice-wordlist.ts +145 -0
  254. package/src/runtime/choice.ts +758 -197
  255. package/src/runtime/credential.ts +2 -2
  256. package/src/runtime/env.ts +1 -1
  257. package/src/runtime/executor.ts +37 -19
  258. package/src/runtime/http.ts +645 -65
  259. package/src/runtime/insights.ts +15 -53
  260. package/src/runtime/instrumentation.ts +530 -67
  261. package/src/runtime/keyring.ts +7 -19
  262. package/src/runtime/namespace.ts +2 -7
  263. package/src/runtime/native-network-errors.ts +99 -0
  264. package/src/runtime/native-network.ts +1605 -0
  265. package/src/runtime/ocr.ts +523 -0
  266. package/src/runtime/otlp.ts +12 -23
  267. package/src/runtime/perf.ts +1 -1
  268. package/src/runtime/provider.ts +4 -9
  269. package/src/runtime/proxy-errors.ts +29 -42
  270. package/src/runtime/proxy-nodemaven.ts +221 -0
  271. package/src/runtime/proxy-retry-policy.ts +3 -3
  272. package/src/runtime/proxy-telemetry.ts +84 -77
  273. package/src/runtime/redirects.ts +66 -0
  274. package/src/runtime/redis.ts +10 -13
  275. package/src/runtime/request-options.ts +679 -9
  276. package/src/runtime/resolver-config.ts +6 -0
  277. package/src/runtime/resolver-public.ts +18 -0
  278. package/src/runtime/resolver-shared.ts +17 -0
  279. package/src/runtime/resolver-vendors/bindings.ts +56 -0
  280. package/src/runtime/resolver-vendors/browser.ts +408 -0
  281. package/src/runtime/resolver-vendors/hosts.ts +38 -0
  282. package/src/runtime/resolver-vendors/twocaptcha.ts +500 -0
  283. package/src/runtime/resolver-vendors/types.ts +173 -0
  284. package/src/runtime/resolver.ts +1060 -0
  285. package/src/runtime/secrets.ts +64 -0
  286. package/src/runtime/state.ts +399 -161
  287. package/src/runtime/stealth-cookies.ts +132 -0
  288. package/src/runtime/stealth.ts +681 -295
  289. package/src/runtime/stt.ts +39 -113
  290. package/src/runtime/timeout.ts +18 -0
  291. package/src/runtime/trace.ts +14 -44
  292. package/src/runtime/waterfall.ts +5 -18
  293. package/src/schema.ts +23 -84
  294. package/src/serve.ts +6 -1
  295. package/src/server/index.ts +30 -7
  296. package/src/server/self-test-input-tokens.ts +29 -14
  297. package/src/server/self-test-redaction.ts +2 -2
  298. package/src/server/self-test.ts +1030 -180
  299. package/src/server/serve-implementation.ts +3062 -0
  300. package/src/server/serve.ts +1 -1781
  301. package/src/server/types.ts +12 -13
  302. package/src/stateful/README.md +146 -0
  303. package/src/stateful/errors.ts +35 -0
  304. package/src/stateful/http-provider-event-emitter.ts +314 -0
  305. package/src/stateful/http-session-owner-registry.ts +306 -0
  306. package/src/stateful/index.ts +18 -0
  307. package/src/stateful/provider-event-delivery-failures.ts +80 -0
  308. package/src/stateful/provider-event-pipeline-metrics.ts +95 -0
  309. package/src/stateful/provider-event-pipeline.ts +61 -0
  310. package/src/stateful/provider-events.ts +462 -0
  311. package/src/stateful/session-key.ts +111 -0
  312. package/src/stateful/stateful-provider-adapter-context.ts +59 -0
  313. package/src/stateful/stateful-provider-adapter-metrics.ts +48 -0
  314. package/src/stateful/stateful-provider-adapter.ts +562 -0
  315. package/src/stateful/stateful-provider-observability.ts +261 -0
  316. package/src/stateful/stateful-provider-owner-forwarder.ts +287 -0
  317. package/src/stateful/stateful-provider-runtime-context.ts +92 -0
  318. package/src/stateful/stateful-provider-runtime-executor.ts +96 -0
  319. package/src/stateful/stateful-provider-session-routing.ts +546 -0
  320. package/src/stateful/stateful-provider-session-runtime.ts +403 -0
  321. package/src/stateful-signing.ts +46 -0
  322. package/src/stealth/profiles.ts +27 -33
  323. package/src/stream-evidence.ts +988 -0
  324. package/src/stream.ts +16 -20
  325. package/src/testing/index.ts +11 -2
  326. package/src/testing/run.ts +668 -74
  327. package/src/types.ts +665 -35
  328. package/src/user-input.ts +118 -0
  329. package/dist/cli/templates/provider/CLAUDE.md.tpl +0 -1
  330. package/src/cli/templates/provider/CLAUDE.md.tpl +0 -1
  331. /package/dist/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
  332. /package/dist/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
  333. /package/dist/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
  334. /package/dist/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
  335. /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
  336. /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
  337. /package/src/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
  338. /package/src/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
  339. /package/src/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
  340. /package/src/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
  341. /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
  342. /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
@@ -1,4 +1,4 @@
1
- import type { Span } from "./trace";
1
+ import type { Span } from "./trace.js";
2
2
  export type InsightSeverity = "info" | "warning" | "error";
3
3
  export type Insight = {
4
4
  id: string;
@@ -1,4 +1,4 @@
1
- import { computePercentile } from "./perf";
1
+ import { computePercentile } from "./perf.js";
2
2
  const LARGE_RESPONSE_BYTES = 100_000;
3
3
  const SLOW_TRANSFORM_MS = 10;
4
4
  const DNS_WARN_MS = 5;
@@ -188,8 +188,7 @@ function getDnsRepeatedCandidate(spans) {
188
188
  if (entry.totalCount < 2) {
189
189
  continue;
190
190
  }
191
- const avgDnsMs = entry.dnsDurations.reduce((sum, value) => sum + value, 0) /
192
- entry.dnsDurations.length;
191
+ const avgDnsMs = entry.dnsDurations.reduce((sum, value) => sum + value, 0) / entry.dnsDurations.length;
193
192
  const reuseRate = entry.reuseCount / entry.totalCount;
194
193
  if (avgDnsMs > DNS_WARN_MS && reuseRate < 0.2) {
195
194
  if (!candidate || avgDnsMs > candidate.avgDnsMs) {
@@ -218,9 +217,7 @@ function getDnsRepeatedInsight(spans) {
218
217
  }
219
218
  function getProxyOverheadInsight(spans) {
220
219
  const requestSpans = spans.filter(isRequestSpan);
221
- const proxiedDurations = requestSpans
222
- .filter(hasProxy)
223
- .map((span) => span.duration_ms);
220
+ const proxiedDurations = requestSpans.filter(hasProxy).map((span) => span.duration_ms);
224
221
  const directDurations = requestSpans
225
222
  .filter((span) => !hasProxy(span))
226
223
  .map((span) => span.duration_ms);
@@ -230,10 +227,8 @@ function getProxyOverheadInsight(spans) {
230
227
  message: "✓ Proxy overhead: insufficient proxy/direct samples",
231
228
  };
232
229
  }
233
- const proxyAvg = proxiedDurations.reduce((sum, value) => sum + value, 0) /
234
- proxiedDurations.length;
235
- const directAvg = directDurations.reduce((sum, value) => sum + value, 0) /
236
- directDurations.length;
230
+ const proxyAvg = proxiedDurations.reduce((sum, value) => sum + value, 0) / proxiedDurations.length;
231
+ const directAvg = directDurations.reduce((sum, value) => sum + value, 0) / directDurations.length;
237
232
  if (directAvg > 0 && proxyAvg >= directAvg * 2) {
238
233
  return {
239
234
  triggered: true,
@@ -254,9 +249,7 @@ function getBrowserIdleInsight(spans) {
254
249
  if (waitMs !== undefined) {
255
250
  return waitMs;
256
251
  }
257
- return span.name.toLowerCase().includes("wait")
258
- ? span.duration_ms
259
- : undefined;
252
+ return span.name.toLowerCase().includes("wait") ? span.duration_ms : undefined;
260
253
  })
261
254
  .filter((value) => value !== undefined);
262
255
  if (waits.length === 0) {
@@ -1,5 +1,5 @@
1
- import type { ProviderContext } from "../types";
2
- import { type CreateTraceContextOptions, type TraceContext } from "./trace";
1
+ import type { ProviderContext } from "../types.js";
2
+ import { type CreateTraceContextOptions, type TraceContext } from "./trace.js";
3
3
  export interface InstrumentationOptions extends CreateTraceContextOptions {
4
4
  }
5
5
  export type InstrumentedProviderContext<T extends ProviderContext> = Omit<T, "trace"> & {
@@ -1,11 +1,14 @@
1
- import { createTraceContext, getTraceRecorder, } from "./trace";
2
- const BROWSER_PAGE_METHODS = new Set([
3
- "goto",
4
- "fill",
5
- "click",
6
- "type",
7
- "waitForSelector",
8
- ]);
1
+ import { readableBytes, readableLines, readableTextChunks } from "../stream.js";
2
+ import { parseHttpRequestInvocation, isSensitiveKey, redactSensitiveError, redactSensitiveText, redactUrlQueryParams, requestOptionsFromHttpInvocation, serializeRequestUrl, } from "./request-options.js";
3
+ import { createTraceContext, getTraceRecorder, } from "./trace.js";
4
+ import { RESOLVER_INSTRUMENTATION_METADATA } from "./resolver-shared.js";
5
+ const BROWSER_PAGE_METHODS = new Set(["goto", "fill", "click", "type", "waitForSelector"]);
6
+ const DIAGNOSTIC_BASE_URL = "http://apifuse-instrumentation.invalid";
7
+ function isThenable(value) {
8
+ return ((typeof value === "object" || typeof value === "function") &&
9
+ value !== null &&
10
+ typeof value.then === "function");
11
+ }
9
12
  function getErrorStatus(error) {
10
13
  if (typeof error === "object" &&
11
14
  error !== null &&
@@ -52,8 +55,173 @@ function getUrl(namespace, args, result) {
52
55
  }
53
56
  return undefined;
54
57
  }
58
+ function requestOptionsForInvocation(namespace, methodName, args) {
59
+ if (namespace === "http") {
60
+ const invocation = parseHttpRequestInvocation(methodName, [...args]);
61
+ return invocation ? requestOptionsFromHttpInvocation(invocation) : undefined;
62
+ }
63
+ if (namespace !== "stealth" || methodName !== "fetch" || typeof args[0] !== "string") {
64
+ return undefined;
65
+ }
66
+ const options = args[1];
67
+ return options !== null && typeof options === "object" && !Array.isArray(options)
68
+ ? options
69
+ : undefined;
70
+ }
71
+ function fallbackSensitiveValues(options) {
72
+ const sensitiveParams = options?.sensitiveParams;
73
+ if (!sensitiveParams || typeof sensitiveParams !== "object")
74
+ return [];
75
+ return Object.values(sensitiveParams).map(String);
76
+ }
77
+ function stripDiagnosticBase(url) {
78
+ return url.startsWith(DIAGNOSTIC_BASE_URL) ? url.slice(DIAGNOSTIC_BASE_URL.length) || "/" : url;
79
+ }
80
+ function serializeDiagnosticUrl(url, options) {
81
+ try {
82
+ return {
83
+ degraded: false,
84
+ serializedUrl: serializeRequestUrl(url, options?.params, options?.sensitiveParams),
85
+ };
86
+ }
87
+ catch {
88
+ try {
89
+ const absoluteUrl = new URL(url, DIAGNOSTIC_BASE_URL).toString();
90
+ const serialized = serializeRequestUrl(absoluteUrl, options?.params, options?.sensitiveParams);
91
+ return {
92
+ degraded: false,
93
+ serializedUrl: {
94
+ requestUrl: stripDiagnosticBase(serialized.requestUrl),
95
+ redactedUrl: stripDiagnosticBase(serialized.redactedUrl),
96
+ sensitiveValues: serialized.sensitiveValues,
97
+ },
98
+ };
99
+ }
100
+ catch {
101
+ const sensitiveParamNames = Object.keys(options?.sensitiveParams ?? {});
102
+ const structural = redactUrlQueryParams(url, sensitiveParamNames);
103
+ return {
104
+ degraded: true,
105
+ serializedUrl: {
106
+ requestUrl: url,
107
+ redactedUrl: structural.redactedUrl,
108
+ sensitiveValues: [
109
+ ...new Set([...fallbackSensitiveValues(options), ...structural.sensitiveValues]),
110
+ ],
111
+ },
112
+ };
113
+ }
114
+ }
115
+ }
116
+ function snapshotRequestDiagnostics(namespace, methodName, args) {
117
+ const options = requestOptionsForInvocation(namespace, methodName, args);
118
+ const url = typeof args[0] === "string" ? args[0] : undefined;
119
+ const hasSensitiveParams = Boolean(options?.sensitiveParams && Object.keys(options.sensitiveParams).length > 0);
120
+ const sensitiveParamNames = Object.keys(options?.sensitiveParams ?? {});
121
+ const diagnosticUrl = hasSensitiveParams && url ? serializeDiagnosticUrl(url, options) : undefined;
122
+ const traceUrl = hasSensitiveParams && url
123
+ ? serializeDiagnosticUrl(url, { sensitiveParams: options?.sensitiveParams }).serializedUrl
124
+ .redactedUrl
125
+ : undefined;
126
+ return {
127
+ ...(diagnosticUrl?.degraded ? { diagnosticUrlDegraded: true } : {}),
128
+ ...(hasSensitiveParams ? { requestId: crypto.randomUUID() } : {}),
129
+ serializedUrl: diagnosticUrl?.serializedUrl,
130
+ sensitiveParamNames,
131
+ sensitiveValues: diagnosticUrl?.serializedUrl.sensitiveValues ?? fallbackSensitiveValues(options),
132
+ traceUrl,
133
+ };
134
+ }
135
+ function sanitizeRequestError(error, diagnostics) {
136
+ return redactSensitiveError(error, diagnostics.sensitiveValues, diagnostics.serializedUrl?.requestUrl, diagnostics.serializedUrl?.redactedUrl);
137
+ }
138
+ function isHttpStreamResponse(value) {
139
+ return (typeof value === "object" &&
140
+ value !== null &&
141
+ "body" in value &&
142
+ value.body instanceof ReadableStream);
143
+ }
144
+ function instrumentHttpStreamConsumption(value, recorder, args, diagnostics) {
145
+ const source = value.body;
146
+ let reader;
147
+ const body = new ReadableStream({
148
+ async pull(controller) {
149
+ try {
150
+ reader ??= source.getReader();
151
+ const chunk = await reader.read();
152
+ if (chunk.done) {
153
+ controller.close();
154
+ return;
155
+ }
156
+ controller.enqueue(chunk.value);
157
+ }
158
+ catch (error) {
159
+ const sanitizedError = sanitizeRequestError(error, diagnostics);
160
+ try {
161
+ await recorder.runSpan("http.stream.consume", () => {
162
+ throw sanitizedError;
163
+ }, {
164
+ onError: (spanError) => buildSpanAttributes("http", "stream", args, undefined, spanError, diagnostics),
165
+ });
166
+ }
167
+ catch (recordedError) {
168
+ controller.error(recordedError);
169
+ }
170
+ }
171
+ },
172
+ async cancel(reason) {
173
+ try {
174
+ await (reader ? reader.cancel(reason) : source.cancel(reason));
175
+ }
176
+ catch (error) {
177
+ throw sanitizeRequestError(error, diagnostics);
178
+ }
179
+ },
180
+ }, { highWaterMark: 0 });
181
+ const instrumented = {
182
+ ...value,
183
+ body,
184
+ bytes: () => readableBytes(body),
185
+ textChunks: () => readableTextChunks(body),
186
+ lines: () => readableLines(body),
187
+ };
188
+ try {
189
+ Object.assign(value, instrumented);
190
+ return value;
191
+ }
192
+ catch {
193
+ return instrumented;
194
+ }
195
+ }
196
+ function isAsyncIterable(value) {
197
+ return (typeof value === "object" &&
198
+ value !== null &&
199
+ Symbol.asyncIterator in value &&
200
+ typeof value[Symbol.asyncIterator] === "function");
201
+ }
202
+ function instrumentHttpSseConsumption(value, recorder, args, diagnostics) {
203
+ const source = value;
204
+ return {
205
+ async *[Symbol.asyncIterator]() {
206
+ try {
207
+ for await (const event of source)
208
+ yield event;
209
+ }
210
+ catch (error) {
211
+ const sanitizedError = sanitizeRequestError(error, diagnostics);
212
+ return await recorder.runSpan("http.sse.consume", () => {
213
+ throw sanitizedError;
214
+ }, {
215
+ onError: (spanError) => buildSpanAttributes("http", "sse", args, undefined, spanError, diagnostics),
216
+ });
217
+ }
218
+ },
219
+ };
220
+ }
55
221
  function getMethod(namespace, methodName, args) {
56
222
  if (namespace === "http") {
223
+ // Preserve the original instrumentation contract: generic entry points are
224
+ // reported as REQUEST/STREAM/SSE, independent of transport options.
57
225
  return methodName.toUpperCase();
58
226
  }
59
227
  if (namespace === "stealth") {
@@ -65,22 +233,27 @@ function getMethod(namespace, methodName, args) {
65
233
  }
66
234
  return undefined;
67
235
  }
68
- function buildSpanAttributes(namespace, methodName, args, result, error) {
236
+ function buildSpanAttributes(namespace, methodName, args, result, error, diagnostics = { sensitiveParamNames: [], sensitiveValues: [] }) {
69
237
  const attributes = {};
70
- const url = getUrl(namespace, args, result);
238
+ const rawUrl = getUrl(namespace, args, result);
239
+ const structuralUrl = diagnostics.traceUrl ?? rawUrl;
240
+ const url = structuralUrl
241
+ ? redactSensitiveText(structuralUrl, diagnostics.sensitiveValues, diagnostics.serializedUrl?.requestUrl, diagnostics.serializedUrl?.redactedUrl)
242
+ : undefined;
71
243
  const method = getMethod(namespace, methodName, args);
72
- const status = error
73
- ? getErrorStatus(error)
74
- : getResponseStatus(namespace, result);
244
+ const status = error ? getErrorStatus(error) : getResponseStatus(namespace, result);
75
245
  const duration = error ? undefined : getResponseDuration(result);
76
246
  if (url) {
77
247
  attributes.url = url;
78
248
  }
249
+ if (diagnostics.requestId)
250
+ attributes.request_id = diagnostics.requestId;
251
+ if (diagnostics.diagnosticUrlDegraded)
252
+ attributes.redaction_degraded = true;
79
253
  if (method) {
80
254
  attributes.method = method;
81
255
  }
82
- if (status !== undefined &&
83
- (namespace === "http" || namespace === "stealth")) {
256
+ if (status !== undefined && (namespace === "http" || namespace === "stealth")) {
84
257
  attributes.status = status;
85
258
  }
86
259
  if (duration !== undefined) {
@@ -95,6 +268,51 @@ function buildSpanAttributes(namespace, methodName, args, result, error) {
95
268
  }
96
269
  return attributes;
97
270
  }
271
+ function isStealthRedirectRunResult(value) {
272
+ return (typeof value === "object" &&
273
+ value !== null &&
274
+ "reason" in value &&
275
+ typeof value.reason === "string" &&
276
+ "hops" in value &&
277
+ Array.isArray(value.hops) &&
278
+ "final" in value &&
279
+ typeof value.final === "object" &&
280
+ value.final !== null);
281
+ }
282
+ function buildStealthRedirectAttributes(args, result, error, diagnostics) {
283
+ const attributes = buildSpanAttributes("stealth", "fetch", args, undefined, error, diagnostics);
284
+ if (!isStealthRedirectRunResult(result))
285
+ return attributes;
286
+ attributes.redirect_reason = result.reason;
287
+ attributes.redirect_hop_count = result.hops.length;
288
+ attributes.status = result.final.status;
289
+ if (result.hops.length > 0) {
290
+ const sensitiveValues = new Set(diagnostics.sensitiveValues);
291
+ const path = result.hops
292
+ .map((hop) => {
293
+ const hopUrl = hop.nextUrl ?? hop.url;
294
+ const responseSensitiveParamNames = [...queryParamNames(hopUrl)].filter(isSensitiveKey);
295
+ const structural = redactUrlQueryParams(hopUrl, [
296
+ ...new Set([...diagnostics.sensitiveParamNames, ...responseSensitiveParamNames]),
297
+ ]);
298
+ for (const value of structural.sensitiveValues)
299
+ sensitiveValues.add(value);
300
+ const safeUrl = redactSensitiveText(structural.redactedUrl, [...sensitiveValues]);
301
+ return `${hop.method} ${hop.status} ${safeUrl}`;
302
+ })
303
+ .join(" -> ");
304
+ attributes.redirect_path = redactSensitiveText(path, [...sensitiveValues], diagnostics.serializedUrl?.requestUrl, diagnostics.serializedUrl?.redactedUrl);
305
+ }
306
+ return attributes;
307
+ }
308
+ function queryParamNames(url) {
309
+ const queryStart = url.indexOf("?");
310
+ if (queryStart === -1)
311
+ return new Set();
312
+ const fragmentStart = url.indexOf("#", queryStart);
313
+ const query = url.slice(queryStart + 1, fragmentStart === -1 ? undefined : fragmentStart);
314
+ return new Set(new URLSearchParams(query).keys());
315
+ }
98
316
  function getBrowserPageAttributes(methodName, args, elapsedMs, error) {
99
317
  const attributes = {};
100
318
  if (methodName === "goto") {
@@ -155,18 +373,83 @@ function wrapPage(page, trace) {
155
373
  },
156
374
  });
157
375
  }
158
- function wrapNamespace(namespace, target, trace) {
376
+ function wrapStealthRedirects(redirects, trace) {
377
+ const recorder = getTraceRecorder(trace);
378
+ if (!recorder)
379
+ return redirects;
380
+ return {
381
+ run(...args) {
382
+ const diagnosticArgs = [args[0].url, args[0]];
383
+ const diagnostics = snapshotRequestDiagnostics("stealth", "fetch", diagnosticArgs);
384
+ let result;
385
+ try {
386
+ result = redirects.run(...args);
387
+ }
388
+ catch (error) {
389
+ const sanitizedError = sanitizeRequestError(error, diagnostics);
390
+ recorder
391
+ .runSpan("stealth.redirects.run", () => {
392
+ throw sanitizedError;
393
+ }, {
394
+ onError: (spanError) => buildStealthRedirectAttributes(diagnosticArgs, undefined, spanError, diagnostics),
395
+ })
396
+ .catch(() => undefined);
397
+ throw sanitizedError;
398
+ }
399
+ const sanitizedResult = Promise.resolve(result).catch((error) => {
400
+ throw sanitizeRequestError(error, diagnostics);
401
+ });
402
+ return recorder.runSpan("stealth.redirects.run", () => sanitizedResult, {
403
+ onSuccess: (spanResult) => buildStealthRedirectAttributes(diagnosticArgs, spanResult, undefined, diagnostics),
404
+ onError: (error) => buildStealthRedirectAttributes(diagnosticArgs, undefined, error, diagnostics),
405
+ });
406
+ },
407
+ };
408
+ }
409
+ function wrapStealthSession(session, trace) {
410
+ const wrappedSession = wrapNamespace("stealth", session, trace);
411
+ const redirects = wrapStealthRedirects(session.redirects, trace);
412
+ return new Proxy(wrappedSession, {
413
+ get(target, property, receiver) {
414
+ return property === "redirects" ? redirects : Reflect.get(target, property, receiver);
415
+ },
416
+ });
417
+ }
418
+ function wrapNamespace(namespace, target, trace, shouldInstrument) {
159
419
  const recorder = getTraceRecorder(trace);
160
420
  if (!recorder) {
161
421
  return target;
162
422
  }
163
423
  const wrappedMethods = new Map();
424
+ const resolverMetadata = namespace === "resolver" ? { target, traceRecorder: recorder } : undefined;
164
425
  return new Proxy(target, {
165
426
  get(namespaceTarget, property, receiver) {
427
+ if (property === RESOLVER_INSTRUMENTATION_METADATA && resolverMetadata) {
428
+ return resolverMetadata;
429
+ }
166
430
  const value = Reflect.get(namespaceTarget, property, receiver);
167
431
  if (typeof value !== "function" || property === "constructor") {
168
432
  return value;
169
433
  }
434
+ if (namespace === "resolver" && property === "solve") {
435
+ if (wrappedMethods.has(property)) {
436
+ return wrappedMethods.get(property);
437
+ }
438
+ const wrapped = (...args) => {
439
+ const challenge = args[0];
440
+ const challengeKind = typeof challenge === "object" &&
441
+ challenge !== null &&
442
+ "kind" in challenge &&
443
+ typeof challenge.kind === "string"
444
+ ? challenge.kind
445
+ : undefined;
446
+ return recorder.runSpan("resolver.solve", () => Reflect.apply(value, namespaceTarget, [args[0], args[1], recorder]), {
447
+ attributes: challengeKind ? { challenge_kind: challengeKind } : undefined,
448
+ });
449
+ };
450
+ wrappedMethods.set(property, wrapped);
451
+ return wrapped;
452
+ }
170
453
  if (namespace === "browser" && property === "newPage") {
171
454
  if (wrappedMethods.has(property)) {
172
455
  return wrappedMethods.get(property);
@@ -192,8 +475,7 @@ function wrapNamespace(namespace, target, trace) {
192
475
  if (namespaceTarget &&
193
476
  typeof namespaceTarget === "object" &&
194
477
  "engine" in namespaceTarget &&
195
- typeof namespaceTarget.engine ===
196
- "string") {
478
+ typeof namespaceTarget.engine === "string") {
197
479
  attributes.engine = namespaceTarget.engine;
198
480
  }
199
481
  return attributes;
@@ -224,10 +506,75 @@ function wrapNamespace(namespace, target, trace) {
224
506
  wrappedMethods.set(property, wrapped);
225
507
  return wrapped;
226
508
  }
227
- const wrapped = (...args) => recorder.runSpan(`${namespace}.${methodName}`, () => Reflect.apply(value, namespaceTarget, args), {
228
- onSuccess: (result) => buildSpanAttributes(namespace, methodName, args, result),
229
- onError: (error) => buildSpanAttributes(namespace, methodName, args, undefined, error),
230
- });
509
+ const wrapped = (...args) => {
510
+ if (shouldInstrument && !shouldInstrument(methodName, args)) {
511
+ return Reflect.apply(value, namespaceTarget, args);
512
+ }
513
+ const requestDiagnostics = snapshotRequestDiagnostics(namespace, methodName, args);
514
+ // Invoke first and decide by the RETURN VALUE. `runSpan` always
515
+ // returns a Promise, so unconditionally span-wrapping every member
516
+ // silently rewrote synchronous contracts: `ctx.state.namespace()`
517
+ // (a sync factory) came back as a Promise, and every method call on
518
+ // it threw a raw TypeError — surfaced in production as catchtable's
519
+ // deterministic CONFIRM_STATE_UNAVAILABLE on 2026-07-27 (and the
520
+ // 2026-07-22 reserve internal_error loop before it). Sync members
521
+ // keep their sync contract; only genuinely async operations are
522
+ // recorded as spans.
523
+ let result;
524
+ try {
525
+ result = Reflect.apply(value, namespaceTarget, args);
526
+ }
527
+ catch (error) {
528
+ const sanitizedError = sanitizeRequestError(error, requestDiagnostics);
529
+ // A promise-returning implementation may still throw
530
+ // SYNCHRONOUSLY during pre-flight validation. Preserve the
531
+ // synchronous throw contract, but keep recording the failure
532
+ // span (the pre-fidelity wrapper captured these).
533
+ recorder
534
+ .runSpan(`${namespace}.${methodName}`, () => {
535
+ throw sanitizedError;
536
+ }, {
537
+ onError: (spanError) => buildSpanAttributes(namespace, methodName, args, undefined, spanError, requestDiagnostics),
538
+ })
539
+ .catch(() => undefined);
540
+ throw sanitizedError;
541
+ }
542
+ if (!isThenable(result)) {
543
+ // The state namespace factory returns the object whose METHODS
544
+ // are the operations worth tracing — instrument that object so
545
+ // `state.get`/`state.compareAndSet`/… spans exist (they never
546
+ // could before: the factory's return value was destroyed).
547
+ if (namespace === "state" &&
548
+ methodName === "namespace" &&
549
+ typeof result === "object" &&
550
+ result !== null) {
551
+ return wrapNamespace(namespace, result, trace);
552
+ }
553
+ if (namespace === "stealth" &&
554
+ methodName === "createSession" &&
555
+ typeof result === "object" &&
556
+ result !== null) {
557
+ return wrapStealthSession(result, trace);
558
+ }
559
+ return result;
560
+ }
561
+ const sanitizedResult = Promise.resolve(result).catch((error) => {
562
+ throw sanitizeRequestError(error, requestDiagnostics);
563
+ });
564
+ const tracedResult = recorder.runSpan(`${namespace}.${methodName}`, () => sanitizedResult, {
565
+ onSuccess: (spanResult) => buildSpanAttributes(namespace, methodName, args, spanResult, undefined, requestDiagnostics),
566
+ onError: (error) => buildSpanAttributes(namespace, methodName, args, undefined, error, requestDiagnostics),
567
+ });
568
+ return namespace === "http" && methodName === "stream"
569
+ ? tracedResult.then((spanResult) => isHttpStreamResponse(spanResult)
570
+ ? instrumentHttpStreamConsumption(spanResult, recorder, args, requestDiagnostics)
571
+ : spanResult)
572
+ : namespace === "http" && methodName === "sse"
573
+ ? tracedResult.then((spanResult) => isAsyncIterable(spanResult)
574
+ ? instrumentHttpSseConsumption(spanResult, recorder, args, requestDiagnostics)
575
+ : spanResult)
576
+ : tracedResult;
577
+ };
231
578
  wrappedMethods.set(property, wrapped);
232
579
  return wrapped;
233
580
  },
@@ -250,7 +597,8 @@ export function wrapWithInstrumentation(ctx, options = {}) {
250
597
  property === "stealth" ||
251
598
  property === "browser" ||
252
599
  property === "session" ||
253
- property === "state") {
600
+ property === "state" ||
601
+ property === "resolver") {
254
602
  const namespace = property;
255
603
  if (wrappedTargets.has(namespace)) {
256
604
  return wrappedTargets.get(namespace);
@@ -1,4 +1,4 @@
1
- import { ConfigurationError, decodeMasterKey } from "./key-derivation";
1
+ import { ConfigurationError, decodeMasterKey } from "./key-derivation.js";
2
2
  const DEFAULT_KEY_PREFIX = "APIFUSE__KEYRING__MASTER_KEY_V";
3
3
  const DEFAULT_ACCEPT_LIST_VAR = "APIFUSE__KEYRING__MASTER_KEY_ACCEPT_LIST";
4
4
  const DEFAULT_WRITER_VERSION_VAR = "APIFUSE__KEYRING__MASTER_KEY_WRITER_VERSION";
@@ -1,5 +1,5 @@
1
1
  import { createHmac } from "node:crypto";
2
- import { deriveSubkey } from "./key-derivation";
2
+ import { deriveSubkey } from "./key-derivation.js";
3
3
  const HMAC_HEX_LENGTH = 16;
4
4
  /**
5
5
  * @internal Trusted loaders only; not re-exported to provider-importable paths.
@@ -0,0 +1,33 @@
1
+ import { TransportError } from "../errors.js";
2
+ export type NativeNetworkErrorCode = "native_connection_aborted" | "native_connection_closed" | "native_connection_failed" | "native_connection_idle_timeout" | "native_connection_timeout" | "native_egress_authorization_failed" | "native_egress_grant_expired" | "native_egress_grant_invalid" | "native_egress_grant_limit_exceeded" | "native_egress_input_invalid" | "native_egress_not_declared" | "native_egress_policy_invalid" | "native_dynamic_egress_unsupported" | "native_proxy_expired" | "native_proxy_invalid";
3
+ export declare class NativeNetworkError extends TransportError {
4
+ constructor(message: string, code: NativeNetworkErrorCode, cause?: Error);
5
+ get code(): NativeNetworkErrorCode;
6
+ }
7
+ export declare function safeDiagnosticEgressHost(value: unknown): string;
8
+ export declare class NativeProxyExpiredError extends NativeNetworkError {
9
+ readonly expiresAt: string;
10
+ constructor(expiresAt: string);
11
+ }
12
+ /** Raised before transport setup when a native destination is not authorized. */
13
+ export declare class NativeEgressNotDeclaredError extends NativeNetworkError {
14
+ readonly port: number;
15
+ readonly tls: "required" | "disabled";
16
+ readonly host: string;
17
+ constructor(host: string, port: number, tls: "required" | "disabled");
18
+ }
19
+ /**
20
+ * Raised when the destination was authorized by a grant whose TTL elapsed and
21
+ * its expiry remains in the client's bounded recent-expiry evidence window.
22
+ */
23
+ export declare class NativeEgressGrantExpiredError extends NativeNetworkError {
24
+ readonly port: number;
25
+ readonly tls: "required" | "disabled";
26
+ readonly expiresAt: string;
27
+ readonly host: string;
28
+ constructor(host: string, port: number, tls: "required" | "disabled", expiresAt: string);
29
+ }
30
+ /** Raised when an established connection exceeds its opt-in read-idle window. */
31
+ export declare class NativeIdleTimeoutError extends NativeNetworkError {
32
+ constructor();
33
+ }
@@ -0,0 +1,69 @@
1
+ import { TransportError } from "../errors.js";
2
+ import { canonicalizeEgressHost } from "../native-address.js";
3
+ export class NativeNetworkError extends TransportError {
4
+ constructor(message, code, cause) {
5
+ const isEgressPolicyFailure = code.startsWith("native_egress_") || code === "native_dynamic_egress_unsupported";
6
+ super(message, {
7
+ code,
8
+ status: 0,
9
+ ...(cause ? { cause } : {}),
10
+ ...(isEgressPolicyFailure ? { category: "provider_error", retryable: false } : {}),
11
+ });
12
+ this.name = "NativeNetworkError";
13
+ }
14
+ get code() {
15
+ return super.code;
16
+ }
17
+ }
18
+ export function safeDiagnosticEgressHost(value) {
19
+ const canonical = canonicalizeEgressHost(value);
20
+ return canonical.ok ? canonical.host : `<invalid-host:${canonical.reason}>`;
21
+ }
22
+ export class NativeProxyExpiredError extends NativeNetworkError {
23
+ expiresAt;
24
+ constructor(expiresAt) {
25
+ super("Native connection closed at sticky proxy expiry", "native_proxy_expired");
26
+ this.expiresAt = expiresAt;
27
+ this.name = "NativeProxyExpiredError";
28
+ }
29
+ }
30
+ /** Raised before transport setup when a native destination is not authorized. */
31
+ export class NativeEgressNotDeclaredError extends NativeNetworkError {
32
+ port;
33
+ tls;
34
+ host;
35
+ constructor(host, port, tls) {
36
+ const diagnosticHost = safeDiagnosticEgressHost(host);
37
+ super(`Native ${tls === "required" ? "TLS" : "TCP"} egress is not declared for ${diagnosticHost}:${port}`, "native_egress_not_declared");
38
+ this.port = port;
39
+ this.tls = tls;
40
+ this.host = diagnosticHost;
41
+ this.name = "NativeEgressNotDeclaredError";
42
+ }
43
+ }
44
+ /**
45
+ * Raised when the destination was authorized by a grant whose TTL elapsed and
46
+ * its expiry remains in the client's bounded recent-expiry evidence window.
47
+ */
48
+ export class NativeEgressGrantExpiredError extends NativeNetworkError {
49
+ port;
50
+ tls;
51
+ expiresAt;
52
+ host;
53
+ constructor(host, port, tls, expiresAt) {
54
+ const diagnosticHost = safeDiagnosticEgressHost(host);
55
+ super(`Native ${tls === "required" ? "TLS" : "TCP"} egress grant expired for ${diagnosticHost}:${port}`, "native_egress_grant_expired");
56
+ this.port = port;
57
+ this.tls = tls;
58
+ this.expiresAt = expiresAt;
59
+ this.host = diagnosticHost;
60
+ this.name = "NativeEgressGrantExpiredError";
61
+ }
62
+ }
63
+ /** Raised when an established connection exceeds its opt-in read-idle window. */
64
+ export class NativeIdleTimeoutError extends NativeNetworkError {
65
+ constructor() {
66
+ super("Native network socket timed out while reading.", "native_connection_idle_timeout");
67
+ this.name = "NativeIdleTimeoutError";
68
+ }
69
+ }