@apifuse/provider-sdk 2.2.0-beta.57 → 2.2.0-beta.59

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 (107) hide show
  1. package/AUTHORING.md +9 -0
  2. package/CHANGELOG.md +8 -0
  3. package/README.md +22 -5
  4. package/SUBMISSION.md +2 -1
  5. package/bin/apifuse-pack-types.ts +49 -0
  6. package/bin/apifuse-record.ts +6 -0
  7. package/dist/cli/templates/provider/README.md.tpl +19 -5
  8. package/dist/config/loader.d.ts +7 -0
  9. package/dist/config/loader.js +30 -6
  10. package/dist/declaration-validation.d.ts +2 -1
  11. package/dist/declaration-validation.js +39 -0
  12. package/dist/define.d.ts +5 -4
  13. package/dist/define.js +25 -1
  14. package/dist/engine.d.ts +16 -0
  15. package/dist/engine.js +58 -1
  16. package/dist/error-resolution.js +13 -0
  17. package/dist/index.d.ts +6 -4
  18. package/dist/index.js +4 -2
  19. package/dist/lint.js +3 -3
  20. package/dist/provider.d.ts +3 -3
  21. package/dist/provider.js +2 -2
  22. package/dist/runtime/bounded-expiring-map.d.ts +21 -0
  23. package/dist/runtime/bounded-expiring-map.js +64 -0
  24. package/dist/runtime/cache.d.ts +2 -0
  25. package/dist/runtime/cache.js +8 -1
  26. package/dist/runtime/egress-lease.d.ts +63 -0
  27. package/dist/runtime/egress-lease.js +233 -0
  28. package/dist/runtime/http.js +1 -0
  29. package/dist/runtime/proxy-retry-policy.d.ts +4 -1
  30. package/dist/runtime/proxy-retry-policy.js +11 -2
  31. package/dist/runtime/request-telemetry.d.ts +7 -9
  32. package/dist/runtime/resolver-config.d.ts +7 -0
  33. package/dist/runtime/resolver-config.js +8 -0
  34. package/dist/runtime/resolver-public.d.ts +3 -1
  35. package/dist/runtime/resolver-public.js +1 -1
  36. package/dist/runtime/resolver-shared.d.ts +9 -0
  37. package/dist/runtime/resolver-shared.js +57 -0
  38. package/dist/runtime/resolver-telemetry.d.ts +134 -0
  39. package/dist/runtime/resolver-telemetry.js +204 -0
  40. package/dist/runtime/resolver-usage.d.ts +24 -0
  41. package/dist/runtime/resolver-usage.js +60 -0
  42. package/dist/runtime/resolver-vendors/bindings.d.ts +5 -0
  43. package/dist/runtime/resolver-vendors/bindings.js +5 -0
  44. package/dist/runtime/resolver-vendors/capsolver.d.ts +2 -2
  45. package/dist/runtime/resolver-vendors/capsolver.js +21 -9
  46. package/dist/runtime/resolver-vendors/hypersolutions.d.ts +27 -0
  47. package/dist/runtime/resolver-vendors/hypersolutions.js +369 -0
  48. package/dist/runtime/resolver-vendors/twocaptcha.d.ts +2 -2
  49. package/dist/runtime/resolver-vendors/twocaptcha.js +26 -10
  50. package/dist/runtime/resolver-vendors/types.d.ts +35 -5
  51. package/dist/runtime/resolver-vendors/types.js +20 -10
  52. package/dist/runtime/resolver.d.ts +5 -1
  53. package/dist/runtime/resolver.js +397 -109
  54. package/dist/runtime/stealth-akamai-sbsd.d.ts +54 -0
  55. package/dist/runtime/stealth-akamai-sbsd.js +142 -0
  56. package/dist/runtime/stealth.js +547 -53
  57. package/dist/schema.d.ts +9 -0
  58. package/dist/schema.js +16 -0
  59. package/dist/server/index.d.ts +2 -0
  60. package/dist/server/index.js +1 -0
  61. package/dist/server/self-test.d.ts +4 -0
  62. package/dist/server/self-test.js +10 -1
  63. package/dist/server/serve-implementation.d.ts +7 -1
  64. package/dist/server/serve-implementation.js +181 -53
  65. package/dist/server/types.d.ts +6 -0
  66. package/dist/server/types.js +14 -0
  67. package/dist/stealth/profiles.d.ts +7 -1
  68. package/dist/stealth/profiles.js +9 -0
  69. package/dist/testing/run.js +6 -0
  70. package/dist/types.d.ts +115 -12
  71. package/package.json +1 -1
  72. package/src/cli/templates/provider/README.md.tpl +19 -5
  73. package/src/config/loader.ts +34 -6
  74. package/src/declaration-validation.ts +47 -1
  75. package/src/define.ts +46 -3
  76. package/src/engine.ts +76 -1
  77. package/src/error-resolution.ts +13 -0
  78. package/src/index.ts +32 -1
  79. package/src/lint.ts +3 -3
  80. package/src/provider.ts +9 -0
  81. package/src/runtime/bounded-expiring-map.ts +67 -0
  82. package/src/runtime/cache.ts +10 -1
  83. package/src/runtime/egress-lease.ts +336 -0
  84. package/src/runtime/http.ts +1 -0
  85. package/src/runtime/proxy-retry-policy.ts +12 -1
  86. package/src/runtime/request-telemetry.ts +5 -7
  87. package/src/runtime/resolver-config.ts +12 -0
  88. package/src/runtime/resolver-public.ts +21 -0
  89. package/src/runtime/resolver-shared.ts +75 -0
  90. package/src/runtime/resolver-telemetry.ts +362 -0
  91. package/src/runtime/resolver-usage.ts +96 -0
  92. package/src/runtime/resolver-vendors/bindings.ts +5 -0
  93. package/src/runtime/resolver-vendors/capsolver.ts +22 -3
  94. package/src/runtime/resolver-vendors/hypersolutions.ts +480 -0
  95. package/src/runtime/resolver-vendors/twocaptcha.ts +26 -12
  96. package/src/runtime/resolver-vendors/types.ts +60 -12
  97. package/src/runtime/resolver.ts +465 -124
  98. package/src/runtime/stealth-akamai-sbsd.ts +207 -0
  99. package/src/runtime/stealth.ts +727 -95
  100. package/src/schema.ts +17 -0
  101. package/src/server/index.ts +21 -0
  102. package/src/server/self-test.ts +13 -0
  103. package/src/server/serve-implementation.ts +268 -48
  104. package/src/server/types.ts +14 -0
  105. package/src/stealth/profiles.ts +10 -0
  106. package/src/testing/run.ts +6 -0
  107. package/src/types.ts +130 -22
@@ -7,21 +7,34 @@ import type {
7
7
  } from "../../types.js";
8
8
  import type { TraceRecorder } from "../trace.js";
9
9
 
10
+ const RESOLVER_VENDOR_POLL_OBSERVER = Symbol.for(
11
+ "@apifuse/provider-sdk/runtime/resolver-vendor-poll-observer",
12
+ );
13
+
14
+ /** Internal chain-runner hook; vendor adapters never receive the telemetry sink itself. */
15
+ export function recordResolverVendorPoll(traceRecorder: TraceRecorder | undefined): void {
16
+ (
17
+ traceRecorder as (TraceRecorder & { [RESOLVER_VENDOR_POLL_OBSERVER]?: () => void }) | undefined
18
+ )?.[RESOLVER_VENDOR_POLL_OBSERVER]?.();
19
+ }
20
+
21
+ export function attachResolverVendorPollObserver(
22
+ traceRecorder: TraceRecorder,
23
+ observer: () => void,
24
+ ): TraceRecorder {
25
+ Object.defineProperty(traceRecorder, RESOLVER_VENDOR_POLL_OBSERVER, { value: observer });
26
+ return traceRecorder;
27
+ }
28
+
10
29
  export const RESOLVER_VENDOR_CAPABILITIES = {
11
30
  browser: ["aws_waf", "cloudflare_interstitial"],
12
31
  // Every kind listed per vendor is implemented by that vendor's adapter; the
13
32
  // per-adapter "agrees with every declared capability" tests iterate this
14
33
  // table, so adding a kind here without an implementation fails the suite.
15
- // 2captcha omits `cloudflare_interstitial`, `akamai_sec_cpt`, and
16
- // `akamai_sensor`: their API offers no task type for them, so declaring them
34
+ // 2captcha omits `cloudflare_interstitial` and every Akamai kind: its API
35
+ // offers no measured task type for them, so declaring them
17
36
  // would route challenges to a vendor that can only refuse.
18
- "2captcha": [
19
- "turnstile",
20
- "recaptcha_v2",
21
- "recaptcha_v3",
22
- "hcaptcha",
23
- "aws_waf",
24
- ],
37
+ "2captcha": ["turnstile", "recaptcha_v2", "recaptcha_v3", "hcaptcha", "aws_waf"],
25
38
  capsolver: [
26
39
  "turnstile",
27
40
  "recaptcha_v2",
@@ -31,6 +44,9 @@ export const RESOLVER_VENDOR_CAPABILITIES = {
31
44
  "aws_waf",
32
45
  ],
33
46
  capmonster: ["turnstile", "recaptcha_v2", "recaptcha_v3", "hcaptcha"],
47
+ // Hyper's /sbsd envelope is measured. Its sensor endpoint is deliberately
48
+ // omitted until that separate protocol is implemented and verified.
49
+ hypersolutions: ["akamai_sbsd"],
34
50
  custom: [
35
51
  "turnstile",
36
52
  "recaptcha_v2",
@@ -40,6 +56,7 @@ export const RESOLVER_VENDOR_CAPABILITIES = {
40
56
  "aws_waf",
41
57
  "akamai_sec_cpt",
42
58
  "akamai_sensor",
59
+ "akamai_sbsd",
43
60
  ],
44
61
  } as const satisfies Readonly<Record<ProviderResolverVendor, readonly ProviderChallengeKind[]>>;
45
62
 
@@ -51,6 +68,7 @@ export const RESOLVER_VENDOR_CAPABILITIES = {
51
68
  export const DEFAULT_RESOLVER_VENDOR_PREFERENCE = [
52
69
  "capsolver",
53
70
  "2captcha",
71
+ "hypersolutions",
54
72
  ] as const satisfies readonly ProviderResolverVendor[];
55
73
 
56
74
  export function resolverVendorSupports(
@@ -83,9 +101,19 @@ export interface ResolverIssuingIdentity {
83
101
 
84
102
  export interface ResolverVendorTransport {
85
103
  /**
86
- * Bound to the resolved proxy lease and client profile.
87
- * Implementations MUST NOT follow redirects and MUST return the initial redirect response.
104
+ * Exact stable upstream headers owned by the proxy/profile-bound transport.
105
+ * This does not include dynamic Cookie headers; the transport injects those from its jar.
106
+ * Adapter requests do not receive these headers implicitly and must forward
107
+ * them when their measured protocol requires session-header continuity.
108
+ */
109
+ readonly sessionHeaders?: Readonly<Record<string, string>>;
110
+ /**
111
+ * Read a cookie from the transport's bound jar for the supplied URL. Responses
112
+ * returned by `fetch` MUST already have been applied to that jar before this
113
+ * method is called. Profile-bound adapters fail closed when this seam is absent.
88
114
  */
115
+ readonly getCookie?: (name: string, url: string) => string | undefined;
116
+ /** Implementations MUST NOT follow redirects and must return the initial response. */
89
117
  fetch(
90
118
  url: string,
91
119
  init: {
@@ -95,6 +123,8 @@ export interface ResolverVendorTransport {
95
123
  signal: AbortSignal;
96
124
  /** Implementations MUST honor manual redirect handling when the SDK guard sets it. */
97
125
  redirect?: "manual";
126
+ /** Maximum UTF-8 response body size; implementations must stop reading at this bound. */
127
+ maxBodyBytes?: number;
98
128
  },
99
129
  ): Promise<{
100
130
  readonly status: number;
@@ -115,9 +145,24 @@ export interface ResolverVendorTransport {
115
145
  }>;
116
146
  }
117
147
 
148
+ /** Metering context the resolver chain hands each vendor adapter for its paid calls. */
149
+ export type ResolverPaidUsageContext = {
150
+ /** 1-based position of the vendor in the provider's declared resolver chain. */
151
+ readonly vendorIndex: number;
152
+ /** SHA-256 scope digest; never the raw affinity, proxy URL, cookie, or IP. */
153
+ readonly resolverIdentityScope?: string;
154
+ };
155
+
118
156
  export interface ResolverVendorAdapter {
119
157
  readonly id: ProviderResolverVendor;
120
158
  readonly requiresTransport?: boolean | ((kind: ProviderChallengeKind) => boolean);
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.
164
+ */
165
+ readonly transportAllowedHosts?: readonly string[];
121
166
  supports(kind: ProviderChallengeKind): boolean;
122
167
  /** Identity the adapter actually used, reported after a successful solve. */
123
168
  getIssuingIdentity?(
@@ -131,6 +176,7 @@ export interface ResolverVendorAdapter {
131
176
  signal: AbortSignal,
132
177
  traceRecorder?: TraceRecorder,
133
178
  transport?: ResolverVendorTransport,
179
+ usage?: ResolverPaidUsageContext,
134
180
  ): Promise<ChallengeSolution>;
135
181
  }
136
182
 
@@ -176,7 +222,9 @@ export class ResolverVendorUnavailableError extends Error {
176
222
  ? options.missingFields?.filter((field) => /^[A-Za-z][A-Za-z0-9_]*$/u.test(field))
177
223
  : undefined;
178
224
  super(
179
- reason === "missing_challenge_input" && missingFields !== undefined && missingFields.length > 0
225
+ reason === "missing_challenge_input" &&
226
+ missingFields !== undefined &&
227
+ missingFields.length > 0
180
228
  ? `Resolver vendor ${vendor} cannot use incomplete challenge input; missing fields: ${missingFields.join(", ")}`
181
229
  : `Resolver vendor ${vendor} is unavailable: ${reason}`,
182
230
  );