@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
@@ -8,6 +8,7 @@ export const SDK_OWNED_PROVIDER_ERROR_CODES = new Set([
8
8
  "BROWSER_CDP_POOL_REQUIRED",
9
9
  "BROWSER_RUNTIME_UNSUPPORTED",
10
10
  "STEALTH_RUNTIME_UNSUPPORTED",
11
+ "STEALTH_HEADER_OVERRIDE_UNSUPPORTED",
11
12
  "SSE_EVENT_UNDECLARED",
12
13
  "STREAM_EVENT_TOO_LARGE",
13
14
  "STREAM_CHUNK_TOO_LARGE",
@@ -49,6 +50,13 @@ export const SDK_OWNED_PROVIDER_ERROR_CODES = new Set([
49
50
  "http_redirect_missing_location",
50
51
  "http_redirect_loop",
51
52
  "transport_invalid_url",
53
+ "EGRESS_LEASE_INVALID",
54
+ "EGRESS_LEASE_BINDING_INVALID",
55
+ "EGRESS_LEASE_KEY_MISSING",
56
+ "EGRESS_LEASE_KEY_WEAK",
57
+ "STEALTH_BODY_UNSUPPORTED",
58
+ "REPLAY_SESSION_MISMATCH",
59
+ "REPLAY_ALREADY_ATTEMPTED",
52
60
  "retry_exhausted",
53
61
  "auth_abort_unsafe_data",
54
62
  "credentials_auth_missing_credential_keys",
@@ -112,6 +120,11 @@ export const SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES = new Map([
112
120
  // contract): the upstream evaluated the request and said no under its
113
121
  // own rules — a conflict with upstream state, never a 5xx.
114
122
  ["UPSTREAM_REJECTED", 409],
123
+ // Only an unverifiable or foreign handle is the caller's: key and binding
124
+ // faults stay unmapped (500) because the engine host, not the caller, owns them.
125
+ ["EGRESS_LEASE_INVALID", 409],
126
+ ["REPLAY_SESSION_MISMATCH", 409],
127
+ ["REPLAY_ALREADY_ATTEMPTED", 409],
115
128
  ["UPSTREAM_ERROR", 502],
116
129
  ["BLOCKED", 502],
117
130
  ["OCR_UNAVAILABLE", 503],
package/dist/index.d.ts CHANGED
@@ -34,20 +34,22 @@ export type { PrevalidateResult } from "./runtime/prevalidate.js";
34
34
  export { getProviderBaseUrl } from "./runtime/provider.js";
35
35
  export type { ProxyTelemetryHeaderPayload, ProxyHash, ProxyTelemetryLogPayload, ProxyTelemetryResolvedPayload, ProxyTelemetryUnresolvedPayload, } from "./runtime/proxy-telemetry.js";
36
36
  export { RequestTelemetry, closedEnum, type ClosedEnum, type GatewayIngestible, type RequestTelemetryLogPayload, type SpanIndex, type TelemetryContributor, type TelemetryKey, type TenantNeutral, } from "./runtime/request-telemetry.js";
37
- export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, DEFAULT_RESOLVER_TIMEOUT_MS, } from "./runtime/resolver-config.js";
37
+ export { APIFUSE__ENGINE__CEREMONY_LEASE_KEY } from "./runtime/egress-lease.js";
38
+ export { ResolverTelemetryCollector, type ResolverCacheReadTelemetryEvent, type ResolverCacheWriteTelemetryEvent, type ResolverFailoverTelemetryEvent, type ResolverIdentityTelemetryEvent, type ResolverOutcomeTelemetryEvent, type ResolverTelemetryAttemptOutcome, type ResolverAttemptSample, type ResolverTelemetryCacheStatus, type ResolverTelemetryCacheWriteReason, type ResolverTelemetryErrorClass, type ResolverTelemetryHeaderPayload, type ResolverTelemetryIdentitySource, type ResolverTelemetryLogPayload, type ResolverTelemetryOutcome, type ResolverTelemetryPhase, type ResolverTelemetrySink, type ResolverVendorAttemptTelemetryEvent, } from "./runtime/resolver-telemetry.js";
39
+ export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__HYPERSOLUTIONS__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, DEFAULT_RESOLVER_TIMEOUT_MS, } from "./runtime/resolver-config.js";
38
40
  export { createUnsupportedResolverClient } from "./runtime/resolver-shared.js";
39
41
  export type { ResolverRuntimeOptions } from "./runtime/resolver.js";
40
- export type { ResolverVendorTransport } from "./runtime/resolver-vendors/types.js";
42
+ export type { ResolverPaidUsageContext, ResolverVendorTransport, ResolverVendorUnavailableReason, } from "./runtime/resolver-vendors/types.js";
41
43
  export { assertRequiredSecretsPresent, listMissingRequiredSecrets, MISSING_SECRET_CODE, } from "./runtime/secrets.js";
42
44
  export { createUnsupportedProviderRuntimeState, UnsupportedProviderStateError, } from "./runtime/state.js";
43
45
  export { APIFUSE__OCR__API_KEY_ENV, APIFUSE__OCR__BACKEND_ENV, APIFUSE__OCR__BASE_URL_ENV, APIFUSE__OCR__CLOUDFLARE_API_TOKEN_ENV, APIFUSE__OCR__MODEL_ENV, CLOUDFLARE_ACCOUNT_ID_ENV, CLOUDFLARE_WORKERS_AI_OCR_BACKEND, createCloudflareWorkersAiOcrClient, createOcrClientFromEnv, createOpenAiCompatibleOcrClient, createUnsupportedOcrClient, DEFAULT_CLOUDFLARE_WORKERS_AI_OCR_MODEL, extractCaptchaCandidates, OPENAI_COMPATIBLE_OCR_BACKEND, } from "./runtime/ocr.js";
44
46
  export { APIFUSE__STT__BACKEND_ENV, APIFUSE__STT__CLOUDFLARE_API_TOKEN_ENV, APIFUSE__STT__MODEL_ENV, createSttClientFromEnv, createUnsupportedSttClient, extractVerificationCode, resolveSttPrompt, } from "./runtime/stt.js";
45
47
  export { type CreateTraceContextOptions, createTraceContext, type Span, type TraceContext, } from "./runtime/trace.js";
46
- export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, type SensitiveFieldKind, type SensitiveFieldOptions, type SensitivePath, sensitive, z, } from "./schema.js";
48
+ export { APIFUSE_CONTENT_PROVENANCE_META_KEY, APIFUSE_CONTENT_TRUST_META_KEY, APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, type SensitiveFieldKind, type SensitiveFieldOptions, type SensitivePath, sensitive, untrustedContent, z, } from "./schema.js";
47
49
  export { createServerApp, createServerAppAsync, ERROR_OBSERVABILITY_HEADER, type ProviderErrorCauseFrame, type ServeOptions, serve, } from "./server/serve.js";
48
50
  export { DEFAULT_STEALTH_BROWSER, DEFAULT_STEALTH_OS, getStealthProfile, listStealthProfiles, } from "./stealth/profiles.js";
49
51
  export * from "./stream.js";
50
- export type { ApiFuseResponse, AuthConfig, AuthContext, AuthFlowDefinition, AuthFlowInputHandler, AuthFlowStartHandler, AuthMode, AuthTurn, Bcp47Locale, BrowserCookie, BrowserEngine, BrowserOptions, BrowserResourceBody, BrowserResourceDecision, BrowserResourceMethod, BrowserResourcePolicy, BrowserResourceRequest, BrowserResourceRoute, ChallengeSolution, ConnectionMode, ContextDeclaration, CookieJar, ContextScratchpad, CredentialContext, CredentialDeclaration, E164PhoneNumber, EnvContext, FlowContext, FlowContextStore, HealthCheckAssertionContext, HealthCheckCase, HealthCheckCaseResult, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyGatewayContext, HealthJourneyJournalContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthJourneySchedule, HealthScheduleRandomization, HealthJourneySmsContext, HealthJourneyStep, HttpClient, HttpMethod, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpResponse, HttpRetryOptions, HttpRetrySummary, HttpStreamResponse, IanaTimeZone, InferSchemaOutput, Iso3166Alpha2CountryCode, Iso4217CurrencyCode, Iso8601Duration, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OcrCaptchaCandidate, OcrCaptchaOptions, OcrCaptchaResult, OcrContext, OcrImageInput, OcrRecognizeRequest, OcrResult, OcrWarning, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDeprecationMetadata, OperationExample, OperationErrorCode, ProviderErrorStatus, OperationHandlerResult, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationTransport, OperationTransportKind, ProbeInterval, ProviderAccessConfig, ProviderAccessVisibility, ProviderCache, ProviderCacheGetOrSetOptions, ProviderCacheKeyOptions, ProviderCacheLookupMeta, ProviderCacheResponseMeta, ProviderCacheResult, ProviderChoiceBindingOptions, ProviderChoiceConsumeMode, ProviderChoiceConsumeResult, ProviderChoiceContext, ProviderChoiceExplicitParseResult, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderChallenge, ProviderChallengeKind, ProviderContext, ProviderContextFor, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderHealthMonitorConfig, ProviderHealthProbeConfig, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderLogoSource, ProviderMeta, ProviderOcrConfig, ProviderProxyConfig, ProviderProxyMode, ProviderProxyPolicy, ProxiedOAuthConfig, ProviderProxyProvider, ProviderProxySessionAffinity, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderReviewed, ProviderResolvedFile, ProviderResolverConfig, ProviderResolverVendor, ProviderRuntimeTarget, ProviderRuntimeState, ProviderSecretDeclaration, ProviderStateDurationString, ProviderStateNamespace, ProviderStreamEvent, ProviderSttConfig, ProviderSttMode, ProviderSupportLevel, RequestOptions, RedirectRunReason, ResolverContext, Rfc3339Instant, SchemaLike, SmsOrigin, SmsOtpExtractionPattern, SmsOtpMatcherDefinition, SseMessage, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateNamespaceScope, StateValue, StateWriteOptions, StealthClient, StealthBrowser, StealthCookieStore, StealthCookieStoreV1, StealthFetchOptions, StealthPlatform, StealthProfile, StealthProfileDescriptor, StealthProfileSelection, StealthOS, StealthRedirectHop, StealthRedirectRunOptions, StealthRedirectRunResult, StealthResponse, StealthSession, StealthSessionCookies, SttAudioInput, SttContext, SttPromptPolicy, SttSegment, SttTranscribeMode, SttTranscribeRequest, SttTranscript, SttUnsupportedOptionPolicy, SttUsage, SttVerificationCodeOptions, SttWarning, TraceConfig, TraceSpan, VerificationCodeCandidate, VerificationCodeCandidateSource, VerificationCodeExtractionResult, } from "./types.js";
52
+ export type { ApiFuseResponse, AuthConfig, AuthContext, AuthFlowDefinition, AuthFlowInputHandler, AuthFlowStartHandler, AuthMode, AuthTurn, Bcp47Locale, BrowserCookie, BrowserEngine, BrowserOptions, BrowserResourceBody, BrowserResourceDecision, BrowserResourceMethod, BrowserResourcePolicy, BrowserResourceRequest, BrowserResourceRoute, ChallengeSolution, ConnectionMode, ContextDeclaration, CookieJar, ContextScratchpad, CredentialContext, CredentialDeclaration, E164PhoneNumber, EnvContext, FlowContext, FlowContextStore, HealthCheckAssertionContext, HealthCheckCase, HealthCheckCaseResult, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyGatewayContext, HealthJourneyJournalContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthJourneySchedule, HealthScheduleRandomization, HealthJourneySmsContext, HealthJourneyStep, HttpClient, HttpMethod, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpResponse, HttpRetryOptions, HttpRetrySummary, HttpStreamResponse, IanaTimeZone, InferSchemaOutput, Iso3166Alpha2CountryCode, Iso4217CurrencyCode, Iso8601Duration, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OcrCaptchaCandidate, OcrCaptchaOptions, OcrCaptchaResult, OcrContext, OcrImageInput, OcrRecognizeRequest, OcrResult, OcrWarning, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDeprecationMetadata, OperationExample, OperationErrorCode, ProviderErrorStatus, OperationHandlerResult, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationTransport, OperationTransportKind, ProbeInterval, ProviderAccessConfig, ProviderAccessVisibility, ProviderCache, ProviderCacheGetOrSetOptions, ProviderCacheKeyOptions, ProviderCacheLookupMeta, ProviderCacheResponseMeta, ProviderCacheResult, ProviderChoiceBindingOptions, ProviderChoiceConsumeMode, ProviderChoiceConsumeResult, ProviderChoiceContext, ProviderChoiceExplicitParseResult, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderChallenge, ProviderChallengeKind, ProviderContext, ProviderContextFor, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderHealthMonitorConfig, ProviderHealthProbeConfig, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderLogoSource, ProviderMeta, ProviderOcrConfig, ProviderProxyConfig, ProviderProxyMode, ProviderProxyPolicy, ProxiedOAuthConfig, ProviderProxyProvider, ProviderProxySessionAffinity, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderReviewed, ProviderResolvedFile, ProviderResolverConfig, ProviderResolverVendor, ProviderRuntimeTarget, ProviderRuntimeState, ProviderSecretDeclaration, ProviderStealthConfig, ProviderStateDurationString, ProviderStateNamespace, ProviderStreamEvent, ProviderSttConfig, ProviderSttMode, ProviderSupportLevel, RequestOptions, RedirectRunReason, ResolverContext, Rfc3339Instant, SchemaLike, SmsOrigin, SmsOtpExtractionPattern, SmsOtpMatcherDefinition, SseMessage, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateNamespaceScope, StateValue, StateWriteOptions, StealthClient, StealthBrowser, StealthChallengeClassification, StealthCookieStore, StealthCookieStoreV1, StealthFetchOptions, StealthPlatform, StealthProfile, StealthProfileDescriptor, StealthProfileSelection, StealthOS, StealthRedirectHop, StealthRedirectRunOptions, StealthRedirectRunResult, StealthResponse, StealthSession, StealthSessionCookies, SttAudioInput, SttContext, SttPromptPolicy, SttSegment, SttTranscribeMode, SttTranscribeRequest, SttTranscript, SttUnsupportedOptionPolicy, SttUsage, SttVerificationCodeOptions, SttWarning, TraceConfig, TraceSpan, VerificationCodeCandidate, VerificationCodeCandidateSource, VerificationCodeExtractionResult, } from "./types.js";
51
53
  export { DEFAULT_OPERATION_TRANSPORT, HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, PROBE_INTERVALS, STREAM_CHUNK_BYTES_MAX, STREAM_CHUNK_BYTES_MIN, STREAM_HEARTBEAT_MS_MAX, STREAM_HEARTBEAT_MS_MIN, STREAM_IDLE_TIMEOUT_MS_MAX, STREAM_IDLE_TIMEOUT_MS_MIN, STREAM_MAX_DURATION_MS_MAX, STREAM_MAX_DURATION_MS_MIN, } from "./types.js";
52
54
  export * from "./utils/date.js";
53
55
  export * from "./utils/parse.js";
package/dist/index.js CHANGED
@@ -27,14 +27,16 @@ export { generateInsights } from "./runtime/insights.js";
27
27
  export { wrapWithInstrumentation, } from "./runtime/instrumentation.js";
28
28
  export { getProviderBaseUrl } from "./runtime/provider.js";
29
29
  export { RequestTelemetry, closedEnum, } from "./runtime/request-telemetry.js";
30
- export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, DEFAULT_RESOLVER_TIMEOUT_MS, } from "./runtime/resolver-config.js";
30
+ export { APIFUSE__ENGINE__CEREMONY_LEASE_KEY } from "./runtime/egress-lease.js";
31
+ export { ResolverTelemetryCollector, } from "./runtime/resolver-telemetry.js";
32
+ export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__HYPERSOLUTIONS__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, DEFAULT_RESOLVER_TIMEOUT_MS, } from "./runtime/resolver-config.js";
31
33
  export { createUnsupportedResolverClient } from "./runtime/resolver-shared.js";
32
34
  export { assertRequiredSecretsPresent, listMissingRequiredSecrets, MISSING_SECRET_CODE, } from "./runtime/secrets.js";
33
35
  export { createUnsupportedProviderRuntimeState, UnsupportedProviderStateError, } from "./runtime/state.js";
34
36
  export { APIFUSE__OCR__API_KEY_ENV, APIFUSE__OCR__BACKEND_ENV, APIFUSE__OCR__BASE_URL_ENV, APIFUSE__OCR__CLOUDFLARE_API_TOKEN_ENV, APIFUSE__OCR__MODEL_ENV, CLOUDFLARE_ACCOUNT_ID_ENV, CLOUDFLARE_WORKERS_AI_OCR_BACKEND, createCloudflareWorkersAiOcrClient, createOcrClientFromEnv, createOpenAiCompatibleOcrClient, createUnsupportedOcrClient, DEFAULT_CLOUDFLARE_WORKERS_AI_OCR_MODEL, extractCaptchaCandidates, OPENAI_COMPATIBLE_OCR_BACKEND, } from "./runtime/ocr.js";
35
37
  export { APIFUSE__STT__BACKEND_ENV, APIFUSE__STT__CLOUDFLARE_API_TOKEN_ENV, APIFUSE__STT__MODEL_ENV, createSttClientFromEnv, createUnsupportedSttClient, extractVerificationCode, resolveSttPrompt, } from "./runtime/stt.js";
36
38
  export { createTraceContext, } from "./runtime/trace.js";
37
- export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, sensitive, z, } from "./schema.js";
39
+ export { APIFUSE_CONTENT_PROVENANCE_META_KEY, APIFUSE_CONTENT_TRUST_META_KEY, APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, sensitive, untrustedContent, z, } from "./schema.js";
38
40
  export { createServerApp, createServerAppAsync, ERROR_OBSERVABILITY_HEADER, serve, } from "./server/serve.js";
39
41
  export { DEFAULT_STEALTH_BROWSER, DEFAULT_STEALTH_OS, getStealthProfile, listStealthProfiles, } from "./stealth/profiles.js";
40
42
  export * from "./stream.js";
package/dist/lint.js CHANGED
@@ -246,7 +246,7 @@ function lintAuthModel(provider) {
246
246
  rule: "platform-managed-no-credential-keys",
247
247
  level: "error",
248
248
  field: "credential.keys",
249
- message: `${providerLabel} must not declare credential.keys for platform-managed auth mode.`,
249
+ message: `${providerLabel} must not declare credential.keys because platform-managed auth mode already implies the unfiltered credential capability.`,
250
250
  });
251
251
  }
252
252
  const authFlowSource = getAuthFlowSource(provider);
@@ -757,9 +757,9 @@ function browserVersionLiteralMessage(finding) {
757
757
  case "profile":
758
758
  return `Hardcoded stealth profile "${finding.literal}" pins a browser version and will rot. Select the browser and OS structurally, for example stealth: { browser: "chrome", os: "macos" }.`;
759
759
  case "user-agent":
760
- return `Hardcoded User-Agent browser version "${finding.literal}" can disagree with the stealth TLS fingerprint. Remove the literal and derive it from the structured profile, for example getStealthProfile({ browser: "chrome", os: "macos" }).userAgent.`;
760
+ return `Hardcoded User-Agent browser version "${finding.literal}" can disagree with the stealth TLS fingerprint. Remove the literal. ctx.stealth owns User-Agent and rejects a caller value with STEALTH_HEADER_OVERRIDE_UNSUPPORTED, so omit the header there and select the profile with stealth: { browser: "chrome", os: "macos" }. For ctx.http only, derive it from getStealthProfile({ browser: "chrome", os: "macos" }).userAgent.`;
761
761
  case "sec-ch-ua":
762
- return 'Hardcoded sec-ch-ua versions can disagree with the stealth TLS fingerprint. Remove the literal and let ctx.stealth generate client hints from stealth: { browser: "chrome", os: "macos" }; derive any explicit User-Agent with getStealthProfile({ browser: "chrome", os: "macos" }).userAgent.';
762
+ return 'Hardcoded sec-ch-ua versions can disagree with the stealth TLS fingerprint. Remove the literal and let ctx.stealth generate client hints from stealth: { browser: "chrome", os: "macos" }. ctx.stealth also owns User-Agent, so omit that header there as well; for ctx.http only, derive it from getStealthProfile({ browser: "chrome", os: "macos" }).userAgent.';
763
763
  }
764
764
  }
765
765
  function lintBrowserVersionLiterals(provider) {
@@ -8,12 +8,12 @@ export type { JsonPrimitive, JsonValue } from "./contract-json.js";
8
8
  export { AssertionExpressionSchema, AssertionPredicateSchema, AssertStepSchema, BoundedJsonPathSchema, CandidateBlockSchema, CandidatePolicySchema, CredentialRefDeclarationSchema, defineHealthScenario, HealthScenarioSchema, HealthStepSchema, ExtractStepSchema, FindFirstSchema, GuardStepSchema, JournalPolicySchema, JsonTemplateSchema, ManualTriggerPolicySchema, OperandSchema, OperationStepSchema, QuantifierSchema, ReferenceSchema, RetryPolicySchema, SafeRegexSchema, ScopedAssertionExpressionSchema, ScopedAssertionPredicateSchema, ScopedItemReferenceSchema, ScopedOperandSchema, StepReferenceSchema, RelativeDateNodeSchema, ValueTypeSchema, } from "./health-scenario.js";
9
9
  export type { AssertionExpression, AssertionPredicate, AttemptReference, AssertResult, AssertStep, BoundedJsonPath, CandidateBlock, CandidatePolicy, CandidateReference, CredentialReference, CredentialRefDeclaration, EstablishedConnectionReference, ExtractStep, FindFirst, GuardAttribution, GuardReasonCode, GuardResult, GuardStep, HealthScenario, HealthStep, JsonTemplate, JournalPolicy, ManualTriggerPolicy, NonEmpty, OperationResult, OperationStep, Operand, Quantifier, ReferenceNode, Reference, RelativeDateNode, RetryPolicy, SafeRegex, ScopedAssertionExpression, ScopedAssertionPredicate, ScopedItemReference, ScopedOperand, StepBase, StepReference, ExtractResult, ValueType, } from "./health-scenario.js";
10
10
  export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, type ProviderErrorObservability, SessionExpiredError, TransportError, ValidationError, } from "./errors.js";
11
- export { createProviderEnvironment, createInProcessProviderEngine, ENGINE_OWNED_PROXY_CREDENTIAL_ENV_NAMES, ENGINE_OWNED_TELEMETRY_ENV_NAMES, isEngineOwnedEnvName, isEngineOwnedProxyCredentialName, isEngineOwnedTelemetryEnvName, PROVIDER_CAPABILITY_KEYS, PROVIDER_ENGINE_PROTOCOL_VERSION, readEngineProxyCredentials, } from "./engine.js";
11
+ export { createProviderEnvironment, createInProcessProviderEngine, ENGINE_OWNED_PROXY_CREDENTIAL_ENV_NAMES, ENGINE_OWNED_RESOLVER_CREDENTIAL_ENV_NAMES, ENGINE_OWNED_RUNTIME_ENV_NAMES, ENGINE_OWNED_TELEMETRY_ENV_NAMES, isEngineOwnedEnvName, isEngineOwnedProxyCredentialName, isEngineOwnedResolverCredentialName, isEngineOwnedRuntimeEnvName, isEngineOwnedTelemetryEnvName, PROVIDER_CAPABILITY_KEYS, PROVIDER_ENGINE_PROTOCOL_VERSION, readEngineProxyCredentials, } from "./engine.js";
12
12
  export type { ProviderCapabilityKey, ProviderEngine, ProviderEngineAttachmentInput, ProviderEngineBindingCandidates, ProviderEngineCapabilitySurface, ProviderEngineRequest, ProviderEngineResidentSurface, ProviderEngineSession, ProviderEngineTransport, } from "./engine.js";
13
13
  export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n/index.js";
14
14
  export { type CreateProviderChoiceContextOptions, createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice.js";
15
- export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, type SensitiveFieldKind, type SensitiveFieldOptions, type SensitivePath, sensitive, z, } from "./schema.js";
16
- export type { AuthAbortData, AuthAbortRetry, AuthFlowTerminalContext, AuthMode, AuthSafeData, AuthSafeJson, FlowContext, HealthCheckAssertionContext, HealthCheckCase, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthScheduleRandomization, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpRetryOptions, HttpRetrySummary, InferSchemaOutput, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationExample, OperationErrorCode, ProviderErrorStatus, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationTransport, ProviderAccessVisibility, ProviderChoiceBindingOptions, ProviderChoiceConsumeMode, ProviderChoiceConsumeResult, ProviderChoiceContext, ProviderChoiceExplicitParseResult, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderContextFor, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderProxyPolicy, ProxiedOAuthConfig, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderResolvedFile, ProviderRuntimeTarget, ProviderRuntimeState, ProviderStateDurationString, ProviderStateNamespace, ProviderSupportLevel, RedirectRunReason, SchemaLike, SmsOtpMatcherDefinition, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateNamespaceScope, StateValue, StateWriteOptions, } from "./types.js";
15
+ export { APIFUSE_CONTENT_PROVENANCE_META_KEY, APIFUSE_CONTENT_TRUST_META_KEY, APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, type SensitiveFieldKind, type SensitiveFieldOptions, type SensitivePath, sensitive, untrustedContent, z, } from "./schema.js";
16
+ export type { AuthAbortData, AuthAbortRetry, AuthFlowTerminalContext, AuthMode, AuthSafeData, AuthSafeJson, FlowContext, HealthCheckAssertionContext, HealthCheckCase, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthScheduleRandomization, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpRetryOptions, HttpRetrySummary, InferSchemaOutput, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationExample, OperationErrorCode, ProviderErrorStatus, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationTransport, ProviderAccessVisibility, ProviderChoiceBindingOptions, ProviderChoiceConsumeMode, ProviderChoiceConsumeResult, ProviderChoiceContext, ProviderChoiceExplicitParseResult, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderContextFor, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderProxyPolicy, ProxiedOAuthConfig, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderResolvedFile, ProviderRuntimeTarget, ProviderRuntimeState, ProviderStealthConfig, ProviderStateDurationString, ProviderStateNamespace, ProviderSupportLevel, RedirectRunReason, SchemaLike, SmsOtpMatcherDefinition, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateNamespaceScope, StateValue, StateWriteOptions, StealthChallengeClassification, } from "./types.js";
17
17
  export { NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, } from "./runtime/native-network-errors.js";
18
18
  export type { NativeGatewayProxy, NativeGatewayProxyResolutionInput, NativeGatewayProxySkipReason, NativeGatewayProxySynthesizer, NativeGatewayProxySynthesisResult, NativeGatewayProxySynthesisInput, NativeNetworkClientOptions, NativeNetworkErrorCode, VendorCredentialLookup, VendorCredentialResolver, } from "./runtime/native-network.js";
19
19
  export { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "./types.js";
package/dist/provider.js CHANGED
@@ -4,9 +4,9 @@ export { assertFreshProviderChoiceIssuedAt, createProviderChoiceToken, ProviderC
4
4
  export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, every, } from "./define.js";
5
5
  export { AssertionExpressionSchema, AssertionPredicateSchema, AssertStepSchema, BoundedJsonPathSchema, CandidateBlockSchema, CandidatePolicySchema, CredentialRefDeclarationSchema, defineHealthScenario, HealthScenarioSchema, HealthStepSchema, ExtractStepSchema, FindFirstSchema, GuardStepSchema, JournalPolicySchema, JsonTemplateSchema, ManualTriggerPolicySchema, OperandSchema, OperationStepSchema, QuantifierSchema, ReferenceSchema, RetryPolicySchema, SafeRegexSchema, ScopedAssertionExpressionSchema, ScopedAssertionPredicateSchema, ScopedItemReferenceSchema, ScopedOperandSchema, StepReferenceSchema, RelativeDateNodeSchema, ValueTypeSchema, } from "./health-scenario.js";
6
6
  export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors.js";
7
- export { createProviderEnvironment, createInProcessProviderEngine, ENGINE_OWNED_PROXY_CREDENTIAL_ENV_NAMES, ENGINE_OWNED_TELEMETRY_ENV_NAMES, isEngineOwnedEnvName, isEngineOwnedProxyCredentialName, isEngineOwnedTelemetryEnvName, PROVIDER_CAPABILITY_KEYS, PROVIDER_ENGINE_PROTOCOL_VERSION, readEngineProxyCredentials, } from "./engine.js";
7
+ export { createProviderEnvironment, createInProcessProviderEngine, ENGINE_OWNED_PROXY_CREDENTIAL_ENV_NAMES, ENGINE_OWNED_RESOLVER_CREDENTIAL_ENV_NAMES, ENGINE_OWNED_RUNTIME_ENV_NAMES, ENGINE_OWNED_TELEMETRY_ENV_NAMES, isEngineOwnedEnvName, isEngineOwnedProxyCredentialName, isEngineOwnedResolverCredentialName, isEngineOwnedRuntimeEnvName, isEngineOwnedTelemetryEnvName, PROVIDER_CAPABILITY_KEYS, PROVIDER_ENGINE_PROTOCOL_VERSION, readEngineProxyCredentials, } from "./engine.js";
8
8
  export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n/index.js";
9
9
  export { createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice.js";
10
- export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, sensitive, z, } from "./schema.js";
10
+ export { APIFUSE_CONTENT_PROVENANCE_META_KEY, APIFUSE_CONTENT_TRUST_META_KEY, APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, sensitive, untrustedContent, z, } from "./schema.js";
11
11
  export { NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, } from "./runtime/native-network-errors.js";
12
12
  export { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "./types.js";
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Map whose entries carry an expiry and whose size is capped.
3
+ *
4
+ * Expired entries are dropped when read and swept on every insert, so a
5
+ * process that keeps minting new keys does not retain dead values. When the
6
+ * cap is still exceeded after the sweep, the least recently used entry is
7
+ * evicted and counted in `capacityEvictions` so callers can tell the two
8
+ * kinds of removal apart. Callers pass `now` explicitly so a single timestamp
9
+ * is used across a lookup-then-store sequence.
10
+ */
11
+ export declare class BoundedExpiringMap<K, V> {
12
+ #private;
13
+ constructor(maxEntries: number, expiresAt: (value: V) => number);
14
+ get size(): number;
15
+ /** Entries removed to satisfy `maxEntries`; expiry removals are not counted. */
16
+ get capacityEvictions(): number;
17
+ get(key: K, now: number): V | undefined;
18
+ set(key: K, value: V, now: number): void;
19
+ delete(key: K): boolean;
20
+ clear(): void;
21
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Map whose entries carry an expiry and whose size is capped.
3
+ *
4
+ * Expired entries are dropped when read and swept on every insert, so a
5
+ * process that keeps minting new keys does not retain dead values. When the
6
+ * cap is still exceeded after the sweep, the least recently used entry is
7
+ * evicted and counted in `capacityEvictions` so callers can tell the two
8
+ * kinds of removal apart. Callers pass `now` explicitly so a single timestamp
9
+ * is used across a lookup-then-store sequence.
10
+ */
11
+ export class BoundedExpiringMap {
12
+ #entries = new Map();
13
+ #maxEntries;
14
+ #expiresAt;
15
+ #capacityEvictions = 0;
16
+ constructor(maxEntries, expiresAt) {
17
+ if (!Number.isInteger(maxEntries) || maxEntries <= 0) {
18
+ throw new RangeError("maxEntries must be a positive integer");
19
+ }
20
+ this.#maxEntries = maxEntries;
21
+ this.#expiresAt = expiresAt;
22
+ }
23
+ get size() {
24
+ return this.#entries.size;
25
+ }
26
+ /** Entries removed to satisfy `maxEntries`; expiry removals are not counted. */
27
+ get capacityEvictions() {
28
+ return this.#capacityEvictions;
29
+ }
30
+ get(key, now) {
31
+ if (!this.#entries.has(key))
32
+ return undefined;
33
+ const value = this.#entries.get(key);
34
+ this.#entries.delete(key);
35
+ if (this.#expiresAt(value) <= now)
36
+ return undefined;
37
+ // Re-insert so Map iteration order doubles as the LRU order.
38
+ this.#entries.set(key, value);
39
+ return value;
40
+ }
41
+ set(key, value, now) {
42
+ for (const [existingKey, existing] of this.#entries) {
43
+ if (this.#expiresAt(existing) <= now)
44
+ this.#entries.delete(existingKey);
45
+ }
46
+ this.#entries.delete(key);
47
+ if (this.#expiresAt(value) <= now)
48
+ return;
49
+ this.#entries.set(key, value);
50
+ if (this.#entries.size > this.#maxEntries) {
51
+ const oldest = this.#entries.keys().next();
52
+ if (!oldest.done) {
53
+ this.#entries.delete(oldest.value);
54
+ this.#capacityEvictions += 1;
55
+ }
56
+ }
57
+ }
58
+ delete(key) {
59
+ return this.#entries.delete(key);
60
+ }
61
+ clear() {
62
+ this.#entries.clear();
63
+ }
64
+ }
@@ -7,5 +7,7 @@ export type ProviderCacheOptions = {
7
7
  };
8
8
  export declare const APIFUSE__CACHE__KEY_PEPPER_ENV = "APIFUSE__CACHE__KEY_PEPPER";
9
9
  export declare function createProviderCache(options: ProviderCacheOptions): ProviderCache;
10
+ /** Internal cache capability, separate from hit/miss metadata. */
11
+ export declare function isProviderCacheBypassed(cache: ProviderCache): boolean;
10
12
  export declare function createBypassProviderCache(options: Pick<ProviderCacheOptions, "providerId">): ProviderCache;
11
13
  export declare function resetProviderCacheForTests(): void;
@@ -465,12 +465,17 @@ export function createProviderCache(options) {
465
465
  },
466
466
  };
467
467
  }
468
+ const bypassCaches = new WeakSet();
469
+ /** Internal cache capability, separate from hit/miss metadata. */
470
+ export function isProviderCacheBypassed(cache) {
471
+ return bypassCaches.has(cache);
472
+ }
468
473
  export function createBypassProviderCache(options) {
469
474
  const configuredPepper = process.env[APIFUSE__CACHE__KEY_PEPPER_ENV];
470
475
  const pepper = configuredPepper && configuredPepper.length > 0 ? configuredPepper : undefined;
471
476
  const events = [];
472
477
  const secretScopedKeys = new Set();
473
- return {
478
+ const cache = {
474
479
  key(namespace, parts, keyOptions) {
475
480
  const extra = new Set((keyOptions?.redactFields ?? []).map((field) => field.toLowerCase()));
476
481
  const normalized = normalizeKeyPart(parts, extra, pepper);
@@ -510,6 +515,8 @@ export function createBypassProviderCache(options) {
510
515
  };
511
516
  },
512
517
  };
518
+ bypassCaches.add(cache);
519
+ return cache;
513
520
  }
514
521
  export function resetProviderCacheForTests() {
515
522
  for (const backend of sharedBackends.values()) {
@@ -0,0 +1,63 @@
1
+ import type { ProxyVendorName } from "../config/loader.js";
2
+ /**
3
+ * AES-256-GCM key for the engine ceremony egress lease handle (ADR-0010 v1.1).
4
+ * Engine host only: the `APIFUSE__ENGINE__` family is rejected from provider
5
+ * secrets and filtered from provider env projections. Supply at least 32 random
6
+ * bytes (for example `openssl rand -base64 32`). Rotating the key fails
7
+ * verification of every outstanding handle (`EGRESS_LEASE_INVALID`, 409): the
8
+ * affected ceremonies restart; they do not expire.
9
+ */
10
+ export declare const APIFUSE__ENGINE__CEREMONY_LEASE_KEY = "APIFUSE__ENGINE__CEREMONY_LEASE_KEY";
11
+ /** Internal option key shared only by the server assembler and stealth runtime. */
12
+ export declare const ENGINE_CEREMONY_EGRESS_LEASE: unique symbol;
13
+ export type CeremonyEgressBinding = {
14
+ readonly vendor: ProxyVendorName;
15
+ readonly proxyUrl: string;
16
+ readonly poolIndex: number;
17
+ readonly affinityKey: string;
18
+ readonly refreshEpoch: number;
19
+ /**
20
+ * Vendor session lifetime the endpoint was allocated for (`proxy.session.lifetimeMinutes`,
21
+ * Smartproxy `life`, NodeMaven SID window). It is the upper bound of the lease, counted
22
+ * from the mint (the first successful attempt), so a Smartproxy lease can outlive the
23
+ * vendor session by the extraction-cache reuse window; expiry then drops and rebinds.
24
+ * The bound is not a vendor guarantee (ADR-0010: a raw Smartproxy endpoint is not a hard
25
+ * lease): the stealth runtime releases the binding as soon as the endpoint fails at the
26
+ * transport, so a dead endpoint is left before the lifetime elapses.
27
+ */
28
+ readonly lifetimeMinutes: number;
29
+ };
30
+ export type CeremonyEgressLeaseRuntime = {
31
+ /** Exact egress bound to this ceremony; undefined until the first successful attempt binds one. */
32
+ readonly binding: CeremonyEgressBinding | undefined;
33
+ /**
34
+ * Drops the binding once its vendor session lifetime has elapsed so the next attempt
35
+ * selects and binds a fresh endpoint. Returns true when a binding was dropped: the
36
+ * caller must also discard challenge state that was only valid for that endpoint.
37
+ */
38
+ dropExpiredBinding(): boolean;
39
+ /**
40
+ * Drops the binding unconditionally; the stealth runtime calls this when the bound
41
+ * endpoint fails at the transport. Same return and caller obligation as
42
+ * `dropExpiredBinding`.
43
+ */
44
+ dropBinding(): boolean;
45
+ /**
46
+ * Number of bindings dropped so far (expiry or release). Every stealth session created
47
+ * from one client shares the lease; a session compares this to what it last observed to
48
+ * retire endpoint-bound challenge state and replay records after another session moved
49
+ * the ceremony.
50
+ */
51
+ readonly generation: number;
52
+ bind(binding: CeremonyEgressBinding): void;
53
+ handle(): string | undefined;
54
+ };
55
+ export declare function createCeremonyEgressLeaseRuntime(options: {
56
+ readonly tenantId?: string;
57
+ readonly providerId: string;
58
+ readonly flowId: string;
59
+ readonly affinityKey: string;
60
+ readonly handle?: string;
61
+ readonly environment?: Readonly<Record<string, string | undefined>>;
62
+ readonly now?: () => number;
63
+ }): CeremonyEgressLeaseRuntime;
@@ -0,0 +1,233 @@
1
+ import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
2
+ import { SDKError } from "../errors.js";
3
+ /**
4
+ * AES-256-GCM key for the engine ceremony egress lease handle (ADR-0010 v1.1).
5
+ * Engine host only: the `APIFUSE__ENGINE__` family is rejected from provider
6
+ * secrets and filtered from provider env projections. Supply at least 32 random
7
+ * bytes (for example `openssl rand -base64 32`). Rotating the key fails
8
+ * verification of every outstanding handle (`EGRESS_LEASE_INVALID`, 409): the
9
+ * affected ceremonies restart; they do not expire.
10
+ */
11
+ export const APIFUSE__ENGINE__CEREMONY_LEASE_KEY = "APIFUSE__ENGINE__CEREMONY_LEASE_KEY";
12
+ /** Internal option key shared only by the server assembler and stealth runtime. */
13
+ export const ENGINE_CEREMONY_EGRESS_LEASE = Symbol.for("@apifuse/provider-sdk/engine-ceremony-egress-lease");
14
+ const HANDLE_VERSION = 1;
15
+ const HANDLE_MAX_BYTES = 16_384;
16
+ const AEAD_NONCE_BYTES = 12;
17
+ const AEAD_TAG_BYTES = 16;
18
+ const AEAD_ALGORITHM = "aes-256-gcm";
19
+ const AEAD_KEY_DOMAIN = "apifuse:ceremony-egress-lease:v1\0";
20
+ const LEASE_KEY_MIN_BYTES = 32;
21
+ /** The caller presented a handle this engine cannot verify for this ceremony (409). */
22
+ function invalidLease() {
23
+ throw new SDKError("The engine ceremony egress lease is invalid", {
24
+ code: "EGRESS_LEASE_INVALID",
25
+ fix: "Restart the authentication ceremony to obtain a new engine-owned egress lease.",
26
+ });
27
+ }
28
+ /** The engine violated its own binding invariant (500); never attributable to the caller. */
29
+ function bindingFault(message) {
30
+ throw new SDKError(message, {
31
+ code: "EGRESS_LEASE_BINDING_INVALID",
32
+ fix: "This is an SDK or provider-runtime fault; the ceremony lease cannot bind the selected egress.",
33
+ });
34
+ }
35
+ function encryptionKey(key) {
36
+ return createHash("sha256").update(AEAD_KEY_DOMAIN, "utf8").update(key, "utf8").digest();
37
+ }
38
+ /** Fixed field order and JSON.stringify's compact form are the canonical AAD encoding. */
39
+ function scopeAad(scope) {
40
+ return Buffer.from(JSON.stringify({
41
+ version: HANDLE_VERSION,
42
+ tenantId: scope.tenantId,
43
+ providerId: scope.providerId,
44
+ flowId: scope.flowId,
45
+ affinityKey: scope.affinityKey,
46
+ }), "utf8");
47
+ }
48
+ function encodeHandle(payload, key, scope) {
49
+ const nonce = randomBytes(AEAD_NONCE_BYTES);
50
+ const cipher = createCipheriv(AEAD_ALGORITHM, encryptionKey(key), nonce, {
51
+ authTagLength: AEAD_TAG_BYTES,
52
+ });
53
+ cipher.setAAD(scopeAad(scope));
54
+ const ciphertext = Buffer.concat([
55
+ cipher.update(JSON.stringify(payload), "utf8"),
56
+ cipher.final(),
57
+ ]);
58
+ return [
59
+ `v${HANDLE_VERSION}`,
60
+ nonce.toString("base64url"),
61
+ ciphertext.toString("base64url"),
62
+ cipher.getAuthTag().toString("base64url"),
63
+ ].join(".");
64
+ }
65
+ function isFiniteInteger(value) {
66
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
67
+ }
68
+ function isPositiveFinite(value) {
69
+ return typeof value === "number" && Number.isFinite(value) && value > 0;
70
+ }
71
+ function decodeHandle(handle, key, scope) {
72
+ if (Buffer.byteLength(handle, "utf8") > HANDLE_MAX_BYTES)
73
+ return invalidLease();
74
+ const parts = handle.split(".");
75
+ if (parts.length !== 4 ||
76
+ parts[0] !== `v${HANDLE_VERSION}` ||
77
+ parts.slice(1).some((part) => !/^[A-Za-z0-9_-]+$/u.test(part))) {
78
+ return invalidLease();
79
+ }
80
+ let parsed;
81
+ try {
82
+ const nonce = Buffer.from(parts[1], "base64url");
83
+ const ciphertext = Buffer.from(parts[2], "base64url");
84
+ const tag = Buffer.from(parts[3], "base64url");
85
+ if (nonce.byteLength !== AEAD_NONCE_BYTES ||
86
+ tag.byteLength !== AEAD_TAG_BYTES ||
87
+ ciphertext.byteLength === 0) {
88
+ return invalidLease();
89
+ }
90
+ const decipher = createDecipheriv(AEAD_ALGORITHM, encryptionKey(key), nonce, {
91
+ authTagLength: AEAD_TAG_BYTES,
92
+ });
93
+ decipher.setAAD(scopeAad(scope));
94
+ decipher.setAuthTag(tag);
95
+ const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
96
+ parsed = JSON.parse(plaintext.toString("utf8"));
97
+ }
98
+ catch {
99
+ return invalidLease();
100
+ }
101
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
102
+ return invalidLease();
103
+ const candidate = parsed;
104
+ if (candidate.version !== HANDLE_VERSION ||
105
+ (candidate.vendor !== "smartproxy" && candidate.vendor !== "nodemaven") ||
106
+ typeof candidate.proxyUrl !== "string" ||
107
+ !candidate.proxyUrl ||
108
+ !isFiniteInteger(candidate.poolIndex) ||
109
+ typeof candidate.affinityKey !== "string" ||
110
+ !candidate.affinityKey ||
111
+ !isFiniteInteger(candidate.refreshEpoch) ||
112
+ typeof candidate.tenantId !== "string" ||
113
+ !candidate.tenantId ||
114
+ typeof candidate.providerId !== "string" ||
115
+ !candidate.providerId ||
116
+ typeof candidate.flowId !== "string" ||
117
+ !candidate.flowId ||
118
+ !isFiniteInteger(candidate.mintedAtMs) ||
119
+ !isFiniteInteger(candidate.expiresAtMs) ||
120
+ candidate.expiresAtMs <= candidate.mintedAtMs ||
121
+ !isPositiveFinite(candidate.lifetimeMinutes)) {
122
+ return invalidLease();
123
+ }
124
+ try {
125
+ const proxy = new URL(candidate.proxyUrl);
126
+ if (proxy.protocol !== "http:" && proxy.protocol !== "socks5:")
127
+ return invalidLease();
128
+ }
129
+ catch {
130
+ return invalidLease();
131
+ }
132
+ return candidate;
133
+ }
134
+ function bindingOf(payload) {
135
+ return {
136
+ vendor: payload.vendor,
137
+ proxyUrl: payload.proxyUrl,
138
+ poolIndex: payload.poolIndex,
139
+ affinityKey: payload.affinityKey,
140
+ refreshEpoch: payload.refreshEpoch,
141
+ lifetimeMinutes: payload.lifetimeMinutes,
142
+ };
143
+ }
144
+ export function createCeremonyEgressLeaseRuntime(options) {
145
+ const environment = options.environment ?? process.env;
146
+ const now = options.now ?? Date.now;
147
+ if (typeof options.tenantId !== "string" || !options.tenantId.trim()) {
148
+ throw new SDKError("A tenant is required for an engine ceremony egress lease", {
149
+ code: "EGRESS_LEASE_INVALID",
150
+ fix: "Restart the authentication ceremony with its tenant identity.",
151
+ });
152
+ }
153
+ const scope = {
154
+ tenantId: options.tenantId,
155
+ providerId: options.providerId,
156
+ flowId: options.flowId,
157
+ affinityKey: options.affinityKey,
158
+ };
159
+ const key = environment[APIFUSE__ENGINE__CEREMONY_LEASE_KEY]?.trim();
160
+ if (!key) {
161
+ throw new SDKError("The engine ceremony egress lease key is not configured", {
162
+ code: "EGRESS_LEASE_KEY_MISSING",
163
+ fix: `Configure ${APIFUSE__ENGINE__CEREMONY_LEASE_KEY} in the engine host.`,
164
+ });
165
+ }
166
+ // The key is the whole authenticity boundary of a handle (a verified handle's proxyUrl
167
+ // becomes the ceremony egress), so the documented minimum is enforced, not advisory.
168
+ if (Buffer.byteLength(key, "utf8") < LEASE_KEY_MIN_BYTES) {
169
+ throw new SDKError(`The engine ceremony egress lease key is shorter than ${LEASE_KEY_MIN_BYTES} bytes`, {
170
+ code: "EGRESS_LEASE_KEY_WEAK",
171
+ fix: `Set ${APIFUSE__ENGINE__CEREMONY_LEASE_KEY} to at least ${LEASE_KEY_MIN_BYTES} random bytes (for example \`openssl rand -base64 32\`).`,
172
+ });
173
+ }
174
+ let payload;
175
+ let currentHandle;
176
+ let generation = 0;
177
+ const dropBinding = () => {
178
+ if (!payload)
179
+ return false;
180
+ payload = undefined;
181
+ currentHandle = undefined;
182
+ generation += 1;
183
+ return true;
184
+ };
185
+ const dropExpiredBinding = () => payload !== undefined && now() >= payload.expiresAtMs ? dropBinding() : false;
186
+ if (options.handle !== undefined) {
187
+ // Scope mismatch fails GCM authentication because scope is AAD; there is
188
+ // deliberately no post-decrypt scope comparison fallback.
189
+ payload = decodeHandle(options.handle, key, scope);
190
+ currentHandle = options.handle;
191
+ // An expired but authentic handle is not a fault: the ceremony continues on a
192
+ // freshly selected endpoint and the next turn receives the new handle.
193
+ dropExpiredBinding();
194
+ }
195
+ return {
196
+ get binding() {
197
+ return payload ? bindingOf(payload) : undefined;
198
+ },
199
+ dropExpiredBinding,
200
+ dropBinding,
201
+ get generation() {
202
+ return generation;
203
+ },
204
+ bind(binding) {
205
+ if (payload) {
206
+ // The stealth runtime reuses the bound endpoint while a binding exists and
207
+ // never rebinds it; a second bind is an engine invariant break.
208
+ return bindingFault("The ceremony egress lease is already bound");
209
+ }
210
+ if (binding.affinityKey !== options.affinityKey ||
211
+ !binding.proxyUrl ||
212
+ (binding.vendor !== "smartproxy" && binding.vendor !== "nodemaven") ||
213
+ !isFiniteInteger(binding.poolIndex) ||
214
+ !isPositiveFinite(binding.lifetimeMinutes)) {
215
+ return bindingFault("The selected egress cannot be bound to the ceremony lease");
216
+ }
217
+ const mintedAtMs = now();
218
+ payload = {
219
+ version: HANDLE_VERSION,
220
+ tenantId: scope.tenantId,
221
+ providerId: options.providerId,
222
+ flowId: options.flowId,
223
+ ...binding,
224
+ mintedAtMs,
225
+ expiresAtMs: mintedAtMs + binding.lifetimeMinutes * 60_000,
226
+ };
227
+ currentHandle = encodeHandle(payload, key, scope);
228
+ },
229
+ handle() {
230
+ return currentHandle;
231
+ },
232
+ };
233
+ }
@@ -498,6 +498,7 @@ async function resolveNativeProxy(options, clientOptions, warn, proxyAttemptOffs
498
498
  // supported here, so a socks5 policy fails loudly rather than downgrading.
499
499
  transportProtocols: ["http"],
500
500
  telemetry: clientOptions.telemetry,
501
+ engineCredentials: clientOptions.engineCredentials,
501
502
  });
502
503
  if (resolvedProxy.shouldWarn) {
503
504
  warn("[provider-sdk] Provider requested proxy routing, but no proxy URL was configured. Continuing without proxy.");
@@ -21,7 +21,10 @@ export declare function normalizeProxyTransportRetryOptions(retry: RequestOption
21
21
  label?: RetryPolicyLabel;
22
22
  }): NormalizedProxyTransportRetryOptions | undefined;
23
23
  export declare function validateUnsafeProxyTransportRetryMethods(options: NormalizedProxyTransportRetryOptions, label?: RetryPolicyLabel): void;
24
- export declare function isProxyTransportRetryMethod(method: HttpMethod | string, options: NormalizedProxyTransportRetryOptions): boolean;
24
+ export declare function isProxyTransportRetryMethod(method: HttpMethod | string, options: NormalizedProxyTransportRetryOptions, request?: {
25
+ readonly body?: unknown;
26
+ readonly headers?: Readonly<Record<string, string | readonly string[] | undefined>>;
27
+ }): boolean;
25
28
  export declare function shouldRetryProxyTransportError(error: unknown, options: NormalizedProxyTransportRetryOptions): boolean;
26
29
  export declare function shouldRetryProxyTransportAttempt(input: {
27
30
  error: unknown;