@apifuse/provider-sdk 2.2.0-beta.7 → 2.2.0-beta.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTHORING.md +943 -51
- package/CHANGELOG.md +273 -1
- package/LICENSE +21 -0
- package/README.md +117 -29
- package/SUBMISSION.md +3 -2
- package/bin/apifuse-check.ts +293 -13
- package/bin/apifuse-dev.ts +42 -19
- package/bin/apifuse-migrate-deployment.ts +200 -0
- package/bin/apifuse-migrate-operation-declaration.ts +55 -0
- package/bin/apifuse-migrate-shape.ts +202 -0
- package/bin/apifuse-pack-check.ts +19 -6
- package/bin/apifuse-pack-smoke.ts +57 -2
- package/bin/apifuse-pack-types.ts +736 -38
- package/bin/apifuse-perf.ts +59 -23
- package/bin/apifuse-record.ts +923 -94
- package/bin/apifuse-submit-check.ts +2313 -281
- package/bin/apifuse-test.ts +3 -1
- package/bin/submit-check-delimited-text.ts +50 -0
- package/dist/auth-turn/index.d.ts +3 -3
- package/dist/auth-turn/index.js +1 -1
- package/dist/auth.d.ts +14 -0
- package/dist/auth.js +67 -0
- package/dist/ceremonies/index.d.ts +16 -0
- package/dist/ceremonies/index.js +141 -36
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +30 -0
- package/dist/cli/create.d.ts +1 -1
- package/dist/cli/create.js +8 -2
- package/dist/cli/deployment-intent.d.ts +178 -0
- package/dist/cli/deployment-intent.js +277 -0
- package/dist/cli/local-connection.d.ts +111 -0
- package/dist/cli/local-connection.js +151 -0
- package/dist/cli/migrate-deployment-intent.d.ts +132 -0
- package/dist/cli/migrate-deployment-intent.js +1552 -0
- package/dist/cli/migrate-operation-declaration.d.ts +70 -0
- package/dist/cli/migrate-operation-declaration.js +2206 -0
- package/dist/cli/migrate-operation-shape.d.ts +44 -0
- package/dist/cli/migrate-operation-shape.js +113 -0
- package/dist/cli/migrate-provider-shape.d.ts +56 -0
- package/dist/cli/migrate-provider-shape.js +580 -0
- package/dist/cli/resolver-runtime.d.ts +21 -0
- package/dist/cli/resolver-runtime.js +31 -0
- package/dist/cli/templates/provider/.agents/skills/health-checks-and-fail-closed/SKILL.md.tpl +141 -23
- package/dist/cli/templates/provider/Dockerfile.tpl +1 -1
- package/dist/cli/templates/provider/README.md.tpl +41 -19
- package/dist/cli/templates/provider/index.ts.tpl +6 -3
- package/dist/cli/templates/provider/operations/ping.ts.tpl +4 -1
- package/dist/cli/templates/provider/provider.json.tpl +6 -0
- package/dist/config/loader.d.ts +202 -16
- package/dist/config/loader.js +491 -141
- package/dist/contract-serialization.js +4 -8
- package/dist/contract-types.d.ts +12 -5
- package/dist/contract.js +24 -10
- package/dist/declaration-validation.d.ts +34 -0
- package/dist/declaration-validation.js +305 -0
- package/dist/define.d.ts +71 -29
- package/dist/define.js +807 -69
- package/dist/dev.d.ts +5 -0
- package/dist/dev.js +8 -1
- package/dist/engine.d.ts +129 -0
- package/dist/engine.js +209 -0
- package/dist/error-observability.d.ts +7 -0
- package/dist/error-observability.js +61 -0
- package/dist/error-resolution.d.ts +18 -0
- package/dist/error-resolution.js +243 -0
- package/dist/errors.d.ts +74 -0
- package/dist/errors.js +99 -0
- package/dist/fixture-sanitization.d.ts +28 -0
- package/dist/fixture-sanitization.js +371 -0
- package/dist/handle-meta.d.ts +90 -0
- package/dist/handle-meta.js +73 -0
- package/dist/handle.d.ts +226 -0
- package/dist/handle.js +345 -0
- package/dist/health-scenario.d.ts +1901 -0
- package/dist/health-scenario.js +653 -0
- package/dist/i18n/catalog.js +21 -1
- package/dist/i18n/error-messages.d.ts +86 -0
- package/dist/i18n/error-messages.js +192 -0
- package/dist/i18n/index.d.ts +1 -0
- package/dist/i18n/index.js +1 -0
- package/dist/i18n/keys.d.ts +12 -0
- package/dist/i18n/keys.js +76 -5
- package/dist/i18n/operation-locale-namespace.d.ts +2 -0
- package/dist/i18n/operation-locale-namespace.js +7 -0
- package/dist/index.d.ts +40 -15
- package/dist/index.js +29 -11
- package/dist/lint.d.ts +43 -11
- package/dist/lint.js +2512 -177
- package/dist/native-address.d.ts +43 -0
- package/dist/native-address.js +281 -0
- package/dist/native-egress-policy.d.ts +31 -0
- package/dist/native-egress-policy.js +288 -0
- package/dist/observability.d.ts +5 -2
- package/dist/observability.js +48 -1
- package/dist/provider.d.ts +18 -8
- package/dist/provider.js +11 -6
- package/dist/runtime/auth-flow.d.ts +6 -1
- package/dist/runtime/auth-flow.js +8 -0
- package/dist/runtime/bounded-expiring-map.d.ts +21 -0
- package/dist/runtime/bounded-expiring-map.js +64 -0
- package/dist/runtime/browser-telemetry-binding.d.ts +5 -0
- package/dist/runtime/browser-telemetry-binding.js +83 -0
- package/dist/runtime/browser-telemetry.d.ts +76 -0
- package/dist/runtime/browser-telemetry.js +165 -0
- package/dist/runtime/browser.d.ts +4 -0
- package/dist/runtime/browser.js +688 -83
- package/dist/runtime/cache-telemetry.d.ts +71 -0
- package/dist/runtime/cache-telemetry.js +177 -0
- package/dist/runtime/cache.d.ts +3 -0
- package/dist/runtime/cache.js +245 -23
- package/dist/runtime/capability-response.d.ts +3 -0
- package/dist/runtime/capability-response.js +56 -0
- package/dist/runtime/capability-telemetry.d.ts +46 -0
- package/dist/runtime/capability-telemetry.js +68 -0
- package/dist/runtime/chrome149-header-order.d.ts +58 -0
- package/dist/runtime/chrome149-header-order.js +289 -0
- package/dist/runtime/diagnostic-env-values.d.ts +5 -0
- package/dist/runtime/diagnostic-env-values.js +57 -0
- package/dist/runtime/diagnostic-env.d.ts +14 -0
- package/dist/runtime/diagnostic-env.js +44 -0
- package/dist/runtime/diagnostic-redactor.d.ts +54 -0
- package/dist/runtime/diagnostic-redactor.js +571 -0
- package/dist/runtime/egress-lease.d.ts +65 -0
- package/dist/runtime/egress-lease.js +236 -0
- package/dist/runtime/engine-mode.d.ts +74 -0
- package/dist/runtime/engine-mode.js +152 -0
- package/dist/runtime/env.js +14 -1
- package/dist/runtime/executor.d.ts +3 -2
- package/dist/runtime/executor.js +23 -26
- package/dist/runtime/handle-wordlist.d.ts +43 -0
- package/dist/runtime/handle-wordlist.js +256 -0
- package/dist/runtime/handle.d.ts +71 -0
- package/dist/runtime/handle.js +908 -0
- package/dist/runtime/http-telemetry-binding.d.ts +10 -0
- package/dist/runtime/http-telemetry-binding.js +152 -0
- package/dist/runtime/http-telemetry-guard.d.ts +16 -0
- package/dist/runtime/http-telemetry-guard.js +202 -0
- package/dist/runtime/http-telemetry.d.ts +104 -0
- package/dist/runtime/http-telemetry.js +190 -0
- package/dist/runtime/http.d.ts +34 -0
- package/dist/runtime/http.js +680 -121
- package/dist/runtime/insights.js +2 -2
- package/dist/runtime/instrumentation.d.ts +2 -2
- package/dist/runtime/instrumentation.js +462 -19
- package/dist/runtime/native-network-errors.d.ts +33 -0
- package/dist/runtime/native-network-errors.js +69 -0
- package/dist/runtime/native-network.d.ts +105 -0
- package/dist/runtime/native-network.js +1433 -0
- package/dist/runtime/native-telemetry.d.ts +142 -0
- package/dist/runtime/native-telemetry.js +231 -0
- package/dist/runtime/ocr-telemetry.d.ts +82 -0
- package/dist/runtime/ocr-telemetry.js +192 -0
- package/dist/runtime/ocr.d.ts +29 -0
- package/dist/runtime/ocr.js +468 -0
- package/dist/runtime/otlp.d.ts +71 -2
- package/dist/runtime/otlp.js +398 -16
- package/dist/runtime/provider.d.ts +7 -0
- package/dist/runtime/provider.js +14 -0
- package/dist/runtime/proxy-errors.js +6 -2
- package/dist/runtime/proxy-nodemaven.d.ts +56 -0
- package/dist/runtime/proxy-nodemaven.js +147 -0
- package/dist/runtime/proxy-retry-policy.d.ts +4 -1
- package/dist/runtime/proxy-retry-policy.js +11 -2
- package/dist/runtime/proxy-telemetry.d.ts +133 -3
- package/dist/runtime/proxy-telemetry.js +218 -70
- package/dist/runtime/redirect-hop-headers.d.ts +19 -0
- package/dist/runtime/redirect-hop-headers.js +58 -0
- package/dist/runtime/redirects.d.ts +61 -0
- package/dist/runtime/redirects.js +149 -0
- package/dist/runtime/redis.d.ts +1 -1
- package/dist/runtime/redis.js +4 -2
- package/dist/runtime/request-options.d.ts +75 -1
- package/dist/runtime/request-options.js +588 -0
- package/dist/runtime/request-telemetry.d.ts +70 -0
- package/dist/runtime/request-telemetry.js +229 -0
- package/dist/runtime/resolver-config.d.ts +13 -0
- package/dist/runtime/resolver-config.js +14 -0
- package/dist/runtime/resolver-public.d.ts +3 -0
- package/dist/runtime/resolver-public.js +1 -0
- package/dist/runtime/resolver-runtime-options.d.ts +14 -0
- package/dist/runtime/resolver-runtime-options.js +33 -0
- package/dist/runtime/resolver-shared.d.ts +24 -0
- package/dist/runtime/resolver-shared.js +69 -0
- package/dist/runtime/resolver-span-attributes.d.ts +34 -0
- package/dist/runtime/resolver-span-attributes.js +93 -0
- package/dist/runtime/resolver-telemetry.d.ts +135 -0
- package/dist/runtime/resolver-telemetry.js +204 -0
- package/dist/runtime/resolver-usage.d.ts +32 -0
- package/dist/runtime/resolver-usage.js +54 -0
- package/dist/runtime/resolver-vendors/bindings.d.ts +53 -0
- package/dist/runtime/resolver-vendors/bindings.js +45 -0
- package/dist/runtime/resolver-vendors/browser.d.ts +24 -0
- package/dist/runtime/resolver-vendors/browser.js +423 -0
- package/dist/runtime/resolver-vendors/capsolver.d.ts +22 -0
- package/dist/runtime/resolver-vendors/capsolver.js +544 -0
- package/dist/runtime/resolver-vendors/hosts.d.ts +23 -0
- package/dist/runtime/resolver-vendors/hosts.js +68 -0
- package/dist/runtime/resolver-vendors/hypersolutions.d.ts +27 -0
- package/dist/runtime/resolver-vendors/hypersolutions.js +369 -0
- package/dist/runtime/resolver-vendors/twocaptcha.d.ts +24 -0
- package/dist/runtime/resolver-vendors/twocaptcha.js +425 -0
- package/dist/runtime/resolver-vendors/types.d.ts +125 -0
- package/dist/runtime/resolver-vendors/types.js +106 -0
- package/dist/runtime/resolver.d.ts +79 -0
- package/dist/runtime/resolver.js +1094 -0
- package/dist/runtime/state-telemetry.d.ts +79 -0
- package/dist/runtime/state-telemetry.js +194 -0
- package/dist/runtime/state.d.ts +10 -1
- package/dist/runtime/state.js +322 -82
- package/dist/runtime/stealth-akamai-sbsd.d.ts +54 -0
- package/dist/runtime/stealth-akamai-sbsd.js +142 -0
- package/dist/runtime/stealth-cookies.d.ts +24 -0
- package/dist/runtime/stealth-cookies.js +131 -0
- package/dist/runtime/stealth-owned-headers.d.ts +39 -0
- package/dist/runtime/stealth-owned-headers.js +57 -0
- package/dist/runtime/stealth-telemetry.d.ts +92 -0
- package/dist/runtime/stealth-telemetry.js +179 -0
- package/dist/runtime/stealth.d.ts +45 -6
- package/dist/runtime/stealth.js +1775 -320
- package/dist/runtime/stt-telemetry.d.ts +77 -0
- package/dist/runtime/stt-telemetry.js +176 -0
- package/dist/runtime/stt.js +18 -19
- package/dist/runtime/timeout.d.ts +5 -0
- package/dist/runtime/timeout.js +12 -0
- package/dist/runtime/trace-config.d.ts +12 -0
- package/dist/runtime/trace-config.js +62 -0
- package/dist/runtime/trace.d.ts +17 -0
- package/dist/runtime/trace.js +176 -25
- package/dist/runtime-boundary-lint.d.ts +137 -0
- package/dist/runtime-boundary-lint.js +590 -0
- package/dist/schema.d.ts +20 -0
- package/dist/schema.js +72 -2
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +1 -1
- package/dist/server/error-observability.d.ts +1 -0
- package/dist/server/error-observability.js +1 -0
- package/dist/server/error-stack-frames.d.ts +35 -0
- package/dist/server/error-stack-frames.js +219 -0
- package/dist/server/index.d.ts +21 -2
- package/dist/server/index.js +11 -2
- package/dist/server/runtime-diagnostics.d.ts +165 -0
- package/dist/server/runtime-diagnostics.js +360 -0
- package/dist/server/sdk-version.d.ts +3 -0
- package/dist/server/sdk-version.js +19 -0
- package/dist/server/self-test-input-tokens.d.ts +2 -1
- package/dist/server/self-test-input-tokens.js +18 -14
- package/dist/server/self-test-redaction.js +8 -33
- package/dist/server/self-test.d.ts +18 -3
- package/dist/server/self-test.js +139 -76
- package/dist/server/sensitive-values.d.ts +26 -0
- package/dist/server/sensitive-values.js +137 -0
- package/dist/server/serve-implementation.d.ts +285 -0
- package/dist/server/serve-implementation.js +3172 -0
- package/dist/server/serve.d.ts +1 -75
- package/dist/server/serve.js +1 -1170
- package/dist/server/state-backend-report.d.ts +70 -0
- package/dist/server/state-backend-report.js +113 -0
- package/dist/server/trace-output.d.ts +7 -0
- package/dist/server/trace-output.js +111 -0
- package/dist/server/types.d.ts +37 -5
- package/dist/server/types.js +34 -1
- package/dist/stateful/errors.d.ts +19 -0
- package/dist/stateful/errors.js +24 -0
- package/dist/stateful/http-provider-event-emitter.d.ts +40 -0
- package/dist/stateful/http-provider-event-emitter.js +237 -0
- package/dist/stateful/http-session-owner-registry.d.ts +44 -0
- package/dist/stateful/http-session-owner-registry.js +210 -0
- package/dist/stateful/index.d.ts +18 -0
- package/dist/stateful/index.js +18 -0
- package/dist/stateful/provider-event-delivery-failures.d.ts +32 -0
- package/dist/stateful/provider-event-delivery-failures.js +43 -0
- package/dist/stateful/provider-event-pipeline-metrics.d.ts +46 -0
- package/dist/stateful/provider-event-pipeline-metrics.js +48 -0
- package/dist/stateful/provider-event-pipeline.d.ts +50 -0
- package/dist/stateful/provider-event-pipeline.js +1 -0
- package/dist/stateful/provider-events.d.ts +101 -0
- package/dist/stateful/provider-events.js +289 -0
- package/dist/stateful/session-key.d.ts +15 -0
- package/dist/stateful/session-key.js +86 -0
- package/dist/stateful/stateful-provider-adapter-context.d.ts +5 -0
- package/dist/stateful/stateful-provider-adapter-context.js +42 -0
- package/dist/stateful/stateful-provider-adapter-metrics.d.ts +15 -0
- package/dist/stateful/stateful-provider-adapter-metrics.js +21 -0
- package/dist/stateful/stateful-provider-adapter.d.ts +98 -0
- package/dist/stateful/stateful-provider-adapter.js +287 -0
- package/dist/stateful/stateful-provider-observability.d.ts +62 -0
- package/dist/stateful/stateful-provider-observability.js +161 -0
- package/dist/stateful/stateful-provider-owner-forwarder.d.ts +41 -0
- package/dist/stateful/stateful-provider-owner-forwarder.js +237 -0
- package/dist/stateful/stateful-provider-runtime-context.d.ts +35 -0
- package/dist/stateful/stateful-provider-runtime-context.js +61 -0
- package/dist/stateful/stateful-provider-runtime-executor.d.ts +34 -0
- package/dist/stateful/stateful-provider-runtime-executor.js +52 -0
- package/dist/stateful/stateful-provider-session-routing.d.ts +67 -0
- package/dist/stateful/stateful-provider-session-routing.js +345 -0
- package/dist/stateful/stateful-provider-session-runtime.d.ts +98 -0
- package/dist/stateful/stateful-provider-session-runtime.js +245 -0
- package/dist/stateful-signing.d.ts +18 -0
- package/dist/stateful-signing.js +27 -0
- package/dist/stealth/profiles.d.ts +15 -4
- package/dist/stealth/profiles.js +169 -211
- package/dist/stream-evidence.d.ts +74 -0
- package/dist/stream-evidence.js +785 -0
- package/dist/stream.js +7 -1
- package/dist/testing/index.d.ts +2 -1
- package/dist/testing/index.js +2 -1
- package/dist/testing/run.d.ts +32 -2
- package/dist/testing/run.js +509 -25
- package/dist/trace-sanitization.d.ts +6 -0
- package/dist/trace-sanitization.js +68 -0
- package/dist/types.d.ts +899 -210
- package/dist/types.js +1 -0
- package/dist/typescript-module.d.ts +39 -0
- package/dist/typescript-module.js +72 -0
- package/package.json +52 -6
- package/src/auth-turn/index.ts +1 -1
- package/src/auth.ts +118 -0
- package/src/ceremonies/index.ts +189 -46
- package/src/cli/commands.ts +37 -0
- package/src/cli/create.ts +8 -2
- package/src/cli/deployment-intent.ts +364 -0
- package/src/cli/local-connection.ts +221 -0
- package/src/cli/migrate-deployment-intent.ts +1908 -0
- package/src/cli/migrate-operation-declaration.ts +3026 -0
- package/src/cli/migrate-operation-shape.ts +184 -0
- package/src/cli/migrate-provider-shape.ts +778 -0
- package/src/cli/resolver-runtime.ts +72 -0
- package/src/cli/templates/provider/.agents/skills/health-checks-and-fail-closed/SKILL.md.tpl +141 -23
- package/src/cli/templates/provider/Dockerfile.tpl +1 -1
- package/src/cli/templates/provider/README.md.tpl +41 -19
- package/src/cli/templates/provider/index.ts.tpl +6 -3
- package/src/cli/templates/provider/operations/ping.ts.tpl +4 -1
- package/src/cli/templates/provider/provider.json.tpl +6 -0
- package/src/config/loader.ts +774 -181
- package/src/contract-serialization.ts +5 -7
- package/src/contract-types.ts +12 -5
- package/src/contract.ts +24 -10
- package/src/declaration-validation.ts +376 -0
- package/src/define.ts +1105 -131
- package/src/dev.ts +13 -1
- package/src/engine.ts +390 -0
- package/src/error-observability.ts +64 -0
- package/src/error-resolution.ts +269 -0
- package/src/errors.ts +157 -0
- package/src/fixture-sanitization.ts +422 -0
- package/src/handle-meta.ts +143 -0
- package/src/handle.ts +694 -0
- package/src/health-scenario.ts +960 -0
- package/src/i18n/catalog.ts +23 -1
- package/src/i18n/error-messages.ts +255 -0
- package/src/i18n/index.ts +1 -0
- package/src/i18n/keys.ts +80 -6
- package/src/i18n/operation-locale-namespace.ts +10 -0
- package/src/index.ts +390 -23
- package/src/lint.ts +2975 -234
- package/src/native-address.ts +340 -0
- package/src/native-egress-policy.ts +358 -0
- package/src/observability.ts +51 -1
- package/src/provider.ts +207 -27
- package/src/runtime/auth-flow.ts +15 -0
- package/src/runtime/bounded-expiring-map.ts +67 -0
- package/src/runtime/browser-telemetry-binding.ts +92 -0
- package/src/runtime/browser-telemetry.ts +289 -0
- package/src/runtime/browser.ts +882 -99
- package/src/runtime/cache-telemetry.ts +247 -0
- package/src/runtime/cache.ts +258 -22
- package/src/runtime/capability-response.ts +53 -0
- package/src/runtime/capability-telemetry.ts +101 -0
- package/src/runtime/chrome149-header-order.ts +330 -0
- package/src/runtime/diagnostic-env-values.ts +56 -0
- package/src/runtime/diagnostic-env.ts +65 -0
- package/src/runtime/diagnostic-redactor.ts +668 -0
- package/src/runtime/egress-lease.ts +341 -0
- package/src/runtime/engine-mode.ts +233 -0
- package/src/runtime/env.ts +15 -1
- package/src/runtime/executor.ts +39 -32
- package/src/runtime/handle-wordlist.ts +266 -0
- package/src/runtime/handle.ts +1180 -0
- package/src/runtime/http-telemetry-binding.ts +162 -0
- package/src/runtime/http-telemetry-guard.ts +208 -0
- package/src/runtime/http-telemetry.ts +292 -0
- package/src/runtime/http.ts +896 -150
- package/src/runtime/insights.ts +2 -2
- package/src/runtime/instrumentation.ts +628 -28
- package/src/runtime/native-network-errors.ts +99 -0
- package/src/runtime/native-network.ts +1853 -0
- package/src/runtime/native-telemetry.ts +366 -0
- package/src/runtime/ocr-telemetry.ts +308 -0
- package/src/runtime/ocr.ts +564 -0
- package/src/runtime/otlp.ts +468 -21
- package/src/runtime/provider.ts +15 -0
- package/src/runtime/proxy-errors.ts +12 -4
- package/src/runtime/proxy-nodemaven.ts +222 -0
- package/src/runtime/proxy-retry-policy.ts +12 -1
- package/src/runtime/proxy-telemetry.ts +358 -103
- package/src/runtime/redirect-hop-headers.ts +71 -0
- package/src/runtime/redirects.ts +215 -0
- package/src/runtime/redis.ts +7 -2
- package/src/runtime/request-options.ts +728 -1
- package/src/runtime/request-telemetry.ts +375 -0
- package/src/runtime/resolver-config.ts +18 -0
- package/src/runtime/resolver-public.ts +44 -0
- package/src/runtime/resolver-runtime-options.ts +50 -0
- package/src/runtime/resolver-shared.ts +113 -0
- package/src/runtime/resolver-span-attributes.ts +139 -0
- package/src/runtime/resolver-telemetry.ts +362 -0
- package/src/runtime/resolver-usage.ts +99 -0
- package/src/runtime/resolver-vendors/bindings.ts +61 -0
- package/src/runtime/resolver-vendors/browser.ts +591 -0
- package/src/runtime/resolver-vendors/capsolver.ts +727 -0
- package/src/runtime/resolver-vendors/hosts.ts +81 -0
- package/src/runtime/resolver-vendors/hypersolutions.ts +480 -0
- package/src/runtime/resolver-vendors/twocaptcha.ts +555 -0
- package/src/runtime/resolver-vendors/types.ts +261 -0
- package/src/runtime/resolver.ts +1543 -0
- package/src/runtime/state-telemetry.ts +298 -0
- package/src/runtime/state.ts +435 -89
- package/src/runtime/stealth-akamai-sbsd.ts +207 -0
- package/src/runtime/stealth-cookies.ts +155 -0
- package/src/runtime/stealth-owned-headers.ts +67 -0
- package/src/runtime/stealth-telemetry.ts +309 -0
- package/src/runtime/stealth.ts +2275 -372
- package/src/runtime/stt-telemetry.ts +282 -0
- package/src/runtime/stt.ts +96 -91
- package/src/runtime/timeout.ts +18 -0
- package/src/runtime/trace-config.ts +78 -0
- package/src/runtime/trace.ts +257 -35
- package/src/runtime-boundary-lint.ts +707 -0
- package/src/schema.ts +80 -2
- package/src/serve.ts +6 -1
- package/src/server/error-observability.ts +1 -0
- package/src/server/error-stack-frames.ts +214 -0
- package/src/server/index.ts +184 -2
- package/src/server/runtime-diagnostics.ts +522 -0
- package/src/server/sdk-version.ts +22 -0
- package/src/server/self-test-input-tokens.ts +29 -14
- package/src/server/self-test-redaction.ts +10 -40
- package/src/server/self-test.ts +205 -89
- package/src/server/sensitive-values.ts +211 -0
- package/src/server/serve-implementation.ts +4596 -0
- package/src/server/serve.ts +1 -1685
- package/src/server/state-backend-report.ts +185 -0
- package/src/server/trace-output.ts +189 -0
- package/src/server/types.ts +34 -1
- package/src/stateful/README.md +146 -0
- package/src/stateful/errors.ts +35 -0
- package/src/stateful/http-provider-event-emitter.ts +314 -0
- package/src/stateful/http-session-owner-registry.ts +306 -0
- package/src/stateful/index.ts +18 -0
- package/src/stateful/provider-event-delivery-failures.ts +80 -0
- package/src/stateful/provider-event-pipeline-metrics.ts +95 -0
- package/src/stateful/provider-event-pipeline.ts +61 -0
- package/src/stateful/provider-events.ts +462 -0
- package/src/stateful/session-key.ts +111 -0
- package/src/stateful/stateful-provider-adapter-context.ts +59 -0
- package/src/stateful/stateful-provider-adapter-metrics.ts +48 -0
- package/src/stateful/stateful-provider-adapter.ts +562 -0
- package/src/stateful/stateful-provider-observability.ts +261 -0
- package/src/stateful/stateful-provider-owner-forwarder.ts +310 -0
- package/src/stateful/stateful-provider-runtime-context.ts +96 -0
- package/src/stateful/stateful-provider-runtime-executor.ts +96 -0
- package/src/stateful/stateful-provider-session-routing.ts +546 -0
- package/src/stateful/stateful-provider-session-runtime.ts +403 -0
- package/src/stateful-signing.ts +46 -0
- package/src/stealth/profiles.ts +212 -231
- package/src/stream-evidence.ts +988 -0
- package/src/stream.ts +8 -1
- package/src/testing/index.ts +10 -1
- package/src/testing/run.ts +685 -19
- package/src/trace-sanitization.ts +110 -0
- package/src/types.ts +1014 -273
- package/src/typescript-module.ts +100 -0
- package/dist/choice-token.d.ts +0 -24
- package/dist/choice-token.js +0 -74
- package/dist/runtime/choice.d.ts +0 -15
- package/dist/runtime/choice.js +0 -413
- package/src/choice-token.ts +0 -165
- package/src/runtime/choice.ts +0 -686
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
import { isProviderError } from "../../errors.js";
|
|
2
|
+
import type {
|
|
3
|
+
BrowserClient,
|
|
4
|
+
BrowserCookie,
|
|
5
|
+
BrowserPage,
|
|
6
|
+
ChallengeSolution,
|
|
7
|
+
ProviderChallenge,
|
|
8
|
+
} from "../../types.js";
|
|
9
|
+
import { type BrowserClientOptions, createBrowserClient } from "../browser.js";
|
|
10
|
+
import type { TraceRecorder } from "../trace.js";
|
|
11
|
+
import { resolverSpanAttributes } from "../resolver-span-attributes.js";
|
|
12
|
+
import type { BrowserTelemetrySink } from "../browser-telemetry.js";
|
|
13
|
+
import { resolverChallengeIssuingIdentity } from "./bindings.js";
|
|
14
|
+
import { assertResolverHostAllowed, normalizedResolverHostname } from "./hosts.js";
|
|
15
|
+
import {
|
|
16
|
+
type ResolverIdentity,
|
|
17
|
+
type ResolverVendorAdapter,
|
|
18
|
+
ResolverVendorUnavailableError,
|
|
19
|
+
} from "./types.js";
|
|
20
|
+
|
|
21
|
+
const BROWSER_VENDOR_ID = "browser" as const;
|
|
22
|
+
const DEFAULT_COOKIE_POLL_INTERVAL_MS = 100;
|
|
23
|
+
const NAVIGATION_BLOCKED_ERROR_TEXT = "net::ERR_BLOCKED_BY_CLIENT";
|
|
24
|
+
const AWS_WAF_CHALLENGE_INFRASTRUCTURE_HOST_SUFFIX = ".awswaf.com";
|
|
25
|
+
const RESOLVER_DOCUMENT_CONTENT_SECURITY_POLICY = "connect-src http: https:; worker-src 'none'";
|
|
26
|
+
|
|
27
|
+
const SUCCESS_COOKIE_NAMES = {
|
|
28
|
+
aws_waf: "aws-waf-token",
|
|
29
|
+
cloudflare_interstitial: "cf_clearance",
|
|
30
|
+
} as const;
|
|
31
|
+
|
|
32
|
+
type SupportedBrowserChallengeKind = keyof typeof SUCCESS_COOKIE_NAMES;
|
|
33
|
+
|
|
34
|
+
type BrowserClientFactory = (options: BrowserClientOptions) => BrowserClient;
|
|
35
|
+
|
|
36
|
+
const RESOLVER_PAGE_METHODS = new Set([
|
|
37
|
+
"goto",
|
|
38
|
+
"evaluate",
|
|
39
|
+
"fill",
|
|
40
|
+
"click",
|
|
41
|
+
"type",
|
|
42
|
+
"waitForSelector",
|
|
43
|
+
"content",
|
|
44
|
+
"screenshot",
|
|
45
|
+
"cookies",
|
|
46
|
+
"url",
|
|
47
|
+
"title",
|
|
48
|
+
"userAgent",
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
function instrumentResolverBrowser(client: BrowserClient, recorder: TraceRecorder): BrowserClient {
|
|
52
|
+
const wrapPage = (page: BrowserPage): BrowserPage =>
|
|
53
|
+
new Proxy(page, {
|
|
54
|
+
get(target, property, receiver) {
|
|
55
|
+
const value = Reflect.get(target, property, receiver);
|
|
56
|
+
if (
|
|
57
|
+
typeof property !== "string" ||
|
|
58
|
+
!RESOLVER_PAGE_METHODS.has(property) ||
|
|
59
|
+
typeof value !== "function"
|
|
60
|
+
)
|
|
61
|
+
return value;
|
|
62
|
+
return (...args: unknown[]) =>
|
|
63
|
+
recorder.runSpan(`browser.page.${property}`, () => Reflect.apply(value, target, args));
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
return new Proxy(client, {
|
|
67
|
+
get(target, property, receiver) {
|
|
68
|
+
const value = Reflect.get(target, property, receiver);
|
|
69
|
+
if (property === "newPage" && typeof value === "function")
|
|
70
|
+
return () =>
|
|
71
|
+
recorder.runSpan("browser.newPage", async () =>
|
|
72
|
+
wrapPage(await Reflect.apply(value, target, [])),
|
|
73
|
+
);
|
|
74
|
+
if (property === "rawPage" && typeof value === "function")
|
|
75
|
+
return () =>
|
|
76
|
+
recorder.runSpan("browser.rawPage", async () =>
|
|
77
|
+
wrapPage(await Reflect.apply(value, target, [])),
|
|
78
|
+
);
|
|
79
|
+
if (property === "withIsolatedContext" && typeof value === "function")
|
|
80
|
+
return (handler: (page: BrowserPage) => Promise<unknown>) =>
|
|
81
|
+
recorder.runSpan("browser.withIsolatedContext", () =>
|
|
82
|
+
Reflect.apply(value, target, [(page: BrowserPage) => handler(wrapPage(page))]),
|
|
83
|
+
);
|
|
84
|
+
return value;
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let createResolverBrowserClient: BrowserClientFactory = createBrowserClient;
|
|
90
|
+
|
|
91
|
+
/** Internal test seam; deliberately not re-exported from the package root. */
|
|
92
|
+
export function swapBrowserResolverClientFactoryForTests(
|
|
93
|
+
factory: BrowserClientFactory | undefined,
|
|
94
|
+
): () => void {
|
|
95
|
+
const original = createResolverBrowserClient;
|
|
96
|
+
createResolverBrowserClient = factory ?? createBrowserClient;
|
|
97
|
+
let restored = false;
|
|
98
|
+
return () => {
|
|
99
|
+
if (restored) return;
|
|
100
|
+
restored = true;
|
|
101
|
+
createResolverBrowserClient = original;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface BrowserResolverVendorOptions {
|
|
106
|
+
readonly cdpUrl?: string;
|
|
107
|
+
readonly timeoutMs: number;
|
|
108
|
+
readonly pollIntervalMs?: number;
|
|
109
|
+
readonly allowedHosts: readonly string[];
|
|
110
|
+
readonly createClient?: BrowserClientFactory;
|
|
111
|
+
readonly telemetry?: BrowserTelemetrySink;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface BrowserResolverVendorAdapter extends ResolverVendorAdapter {
|
|
115
|
+
readonly id: "browser";
|
|
116
|
+
solve(
|
|
117
|
+
challenge: ProviderChallenge,
|
|
118
|
+
identity: ResolverIdentity | undefined,
|
|
119
|
+
signal: AbortSignal,
|
|
120
|
+
traceRecorder?: TraceRecorder,
|
|
121
|
+
): Promise<Extract<ChallengeSolution, { readonly form: "cookies" }>>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
class BrowserSolveTimeoutError extends Error {
|
|
125
|
+
constructor(blockedRequests: readonly string[]) {
|
|
126
|
+
super(`Browser resolver solve budget elapsed${formatBlockedRequests(blockedRequests)}`);
|
|
127
|
+
this.name = "BrowserSolveTimeoutError";
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
class BrowserNavigationBlockedError extends Error {
|
|
132
|
+
readonly code = "RESOLVER_BROWSER_NAVIGATION_BLOCKED";
|
|
133
|
+
|
|
134
|
+
constructor(
|
|
135
|
+
readonly navigationUrl: string,
|
|
136
|
+
readonly blockedUrls: readonly string[],
|
|
137
|
+
options: ErrorOptions,
|
|
138
|
+
) {
|
|
139
|
+
super(
|
|
140
|
+
`Browser resolver navigation was blocked for ${navigationUrl}${formatBlockedRequests(blockedUrls)}`,
|
|
141
|
+
options,
|
|
142
|
+
);
|
|
143
|
+
this.name = "BrowserNavigationBlockedError";
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function formatBlockedRequests(blockedRequests: readonly string[]): string {
|
|
148
|
+
if (blockedRequests.length === 0) return "";
|
|
149
|
+
const displayed = blockedRequests.slice(0, 5);
|
|
150
|
+
const remainder = blockedRequests.length - displayed.length;
|
|
151
|
+
return `; blocked ${blockedRequests.length} requests: [${displayed.join(", ")}]${remainder > 0 ? ` (+${remainder} more)` : ""}`;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function isNavigationBlockedError(error: unknown): error is Error {
|
|
155
|
+
return error instanceof Error && error.message.includes(NAVIGATION_BLOCKED_ERROR_TEXT);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
class BrowserCleanupTimeoutError extends Error {
|
|
159
|
+
constructor(timeoutMs: number) {
|
|
160
|
+
super(`Browser resolver cleanup exceeded ${timeoutMs}ms`);
|
|
161
|
+
this.name = "BrowserCleanupTimeoutError";
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function abortReason(signal: AbortSignal): unknown {
|
|
166
|
+
return signal.reason ?? new DOMException("The operation was aborted", "AbortError");
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function raceWithAbort<T>(operation: () => Promise<T>, signal: AbortSignal): Promise<T> {
|
|
170
|
+
if (signal.aborted) {
|
|
171
|
+
return Promise.reject(abortReason(signal));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return new Promise<T>((resolve, reject) => {
|
|
175
|
+
const cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
176
|
+
const onAbort = () => {
|
|
177
|
+
cleanup();
|
|
178
|
+
reject(abortReason(signal));
|
|
179
|
+
};
|
|
180
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
181
|
+
operation().then(
|
|
182
|
+
(value) => {
|
|
183
|
+
cleanup();
|
|
184
|
+
resolve(value);
|
|
185
|
+
},
|
|
186
|
+
(error: unknown) => {
|
|
187
|
+
cleanup();
|
|
188
|
+
reject(error);
|
|
189
|
+
},
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async function runBoundedCleanup(
|
|
195
|
+
cleanup: () => Promise<unknown>,
|
|
196
|
+
timeoutMs: number,
|
|
197
|
+
challengeKind: ProviderChallenge["kind"],
|
|
198
|
+
operation: "client.close" | "context.close",
|
|
199
|
+
traceRecorder: TraceRecorder | undefined,
|
|
200
|
+
): Promise<void> {
|
|
201
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
202
|
+
const boundedCleanup = async () => {
|
|
203
|
+
try {
|
|
204
|
+
await Promise.race([
|
|
205
|
+
cleanup(),
|
|
206
|
+
new Promise<never>((_resolve, reject) => {
|
|
207
|
+
timeout = setTimeout(() => reject(new BrowserCleanupTimeoutError(timeoutMs)), timeoutMs);
|
|
208
|
+
}),
|
|
209
|
+
]);
|
|
210
|
+
} finally {
|
|
211
|
+
if (timeout !== undefined) clearTimeout(timeout);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
if (!traceRecorder) {
|
|
216
|
+
await boundedCleanup().catch(() => undefined);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
await traceRecorder
|
|
221
|
+
.runSpan("resolver.vendor.cleanup", boundedCleanup, {
|
|
222
|
+
attributes: resolverSpanAttributes({
|
|
223
|
+
vendor: BROWSER_VENDOR_ID,
|
|
224
|
+
challenge_kind: challengeKind,
|
|
225
|
+
operation,
|
|
226
|
+
}),
|
|
227
|
+
onError(error) {
|
|
228
|
+
return resolverSpanAttributes({
|
|
229
|
+
error_message: error instanceof Error ? error.message : String(error),
|
|
230
|
+
});
|
|
231
|
+
},
|
|
232
|
+
})
|
|
233
|
+
.catch(() => undefined);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
async function abortableDelay(ms: number, signal: AbortSignal): Promise<void> {
|
|
237
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
238
|
+
try {
|
|
239
|
+
await raceWithAbort(
|
|
240
|
+
() =>
|
|
241
|
+
new Promise<void>((resolve) => {
|
|
242
|
+
timer = setTimeout(resolve, ms);
|
|
243
|
+
}),
|
|
244
|
+
signal,
|
|
245
|
+
);
|
|
246
|
+
} finally {
|
|
247
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function isSupportedKind(kind: string): kind is SupportedBrowserChallengeKind {
|
|
252
|
+
return Object.hasOwn(SUCCESS_COOKIE_NAMES, kind);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function cookieDomainSpecificity(cookie: BrowserCookie): number {
|
|
256
|
+
return normalizedResolverHostname(cookie.domain.replace(/^\./, "")).length;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function isHostOnlyCookieFor(cookie: BrowserCookie, hostname: string): boolean {
|
|
260
|
+
return (
|
|
261
|
+
!cookie.domain.startsWith(".") &&
|
|
262
|
+
normalizedResolverHostname(cookie.domain) === normalizedResolverHostname(hostname)
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function cookieAppliesToUrl(cookie: BrowserCookie, url: URL): boolean {
|
|
267
|
+
const cookieDomain = normalizedResolverHostname(cookie.domain.replace(/^\./, ""));
|
|
268
|
+
const requestHostname = normalizedResolverHostname(url.hostname);
|
|
269
|
+
const domainMatches =
|
|
270
|
+
cookieDomain.length > 0 &&
|
|
271
|
+
(requestHostname === cookieDomain ||
|
|
272
|
+
(cookie.domain.startsWith(".") && requestHostname.endsWith(`.${cookieDomain}`)));
|
|
273
|
+
if (!domainMatches || (cookie.secure && url.protocol !== "https:")) return false;
|
|
274
|
+
|
|
275
|
+
const requestPath = url.pathname || "/";
|
|
276
|
+
const cookiePath = cookie.path;
|
|
277
|
+
return (
|
|
278
|
+
cookiePath.startsWith("/") &&
|
|
279
|
+
(requestPath === cookiePath ||
|
|
280
|
+
(requestPath.startsWith(cookiePath) &&
|
|
281
|
+
(cookiePath.endsWith("/") || requestPath[cookiePath.length] === "/")))
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function selectSuccessCookie(
|
|
286
|
+
cookies: readonly BrowserCookie[],
|
|
287
|
+
successCookieName: string,
|
|
288
|
+
pageUrl: string,
|
|
289
|
+
): BrowserCookie | undefined {
|
|
290
|
+
const url = new URL(pageUrl);
|
|
291
|
+
return cookies
|
|
292
|
+
.filter((cookie) => cookie.name === successCookieName && cookieAppliesToUrl(cookie, url))
|
|
293
|
+
.sort(
|
|
294
|
+
(left, right) =>
|
|
295
|
+
Number(isHostOnlyCookieFor(right, url.hostname)) -
|
|
296
|
+
Number(isHostOnlyCookieFor(left, url.hostname)) ||
|
|
297
|
+
cookieDomainSpecificity(right) - cookieDomainSpecificity(left) ||
|
|
298
|
+
right.path.length - left.path.length,
|
|
299
|
+
)[0];
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async function solveInPage(
|
|
303
|
+
page: BrowserPage,
|
|
304
|
+
challengeKind: SupportedBrowserChallengeKind,
|
|
305
|
+
pageUrl: string,
|
|
306
|
+
allowedHosts: readonly string[],
|
|
307
|
+
successCookieName: string,
|
|
308
|
+
pollIntervalMs: number,
|
|
309
|
+
gotoTimeoutMs: number,
|
|
310
|
+
blockedRequests: Set<string>,
|
|
311
|
+
signal: AbortSignal,
|
|
312
|
+
): Promise<Extract<ChallengeSolution, { readonly form: "cookies" }>> {
|
|
313
|
+
return await page.withResourcePolicy(
|
|
314
|
+
{
|
|
315
|
+
allowedMethods: ["GET", "HEAD", "POST"],
|
|
316
|
+
documentContentSecurityPolicy: RESOLVER_DOCUMENT_CONTENT_SECURITY_POLICY,
|
|
317
|
+
routes: [
|
|
318
|
+
{
|
|
319
|
+
match: () => true,
|
|
320
|
+
handle: (request) => {
|
|
321
|
+
if (isResolverBrowserRequestAllowed(request.url, challengeKind, allowedHosts)) {
|
|
322
|
+
return { action: "continue" };
|
|
323
|
+
}
|
|
324
|
+
blockedRequests.add(request.url);
|
|
325
|
+
return { action: "block" };
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
],
|
|
329
|
+
},
|
|
330
|
+
async () => {
|
|
331
|
+
const userAgent = await raceWithAbort(() => page.userAgent(), signal);
|
|
332
|
+
try {
|
|
333
|
+
await raceWithAbort(
|
|
334
|
+
() =>
|
|
335
|
+
page.goto(pageUrl, {
|
|
336
|
+
timeout: gotoTimeoutMs,
|
|
337
|
+
waitUntil: "domcontentloaded",
|
|
338
|
+
}),
|
|
339
|
+
signal,
|
|
340
|
+
);
|
|
341
|
+
} catch (error) {
|
|
342
|
+
if (!isNavigationBlockedError(error)) throw error;
|
|
343
|
+
throw new BrowserNavigationBlockedError(pageUrl, [...blockedRequests], { cause: error });
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
while (true) {
|
|
347
|
+
const cookies = await raceWithAbort(() => page.cookies(), signal);
|
|
348
|
+
const successCookie = selectSuccessCookie(cookies, successCookieName, pageUrl);
|
|
349
|
+
if (successCookie) {
|
|
350
|
+
return {
|
|
351
|
+
form: "cookies",
|
|
352
|
+
cookies: { [successCookieName]: successCookie.value },
|
|
353
|
+
userAgent,
|
|
354
|
+
...(successCookie.expires === undefined ? {} : { expires: successCookie.expires }),
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
await abortableDelay(pollIntervalMs, signal);
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function isResolverBrowserRequestAllowed(
|
|
365
|
+
targetUrl: string,
|
|
366
|
+
challengeKind: SupportedBrowserChallengeKind,
|
|
367
|
+
allowedHosts: readonly string[],
|
|
368
|
+
): boolean {
|
|
369
|
+
try {
|
|
370
|
+
assertResolverHostAllowed(targetUrl, allowedHosts);
|
|
371
|
+
return true;
|
|
372
|
+
} catch {
|
|
373
|
+
if (challengeKind !== "aws_waf") return false;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
let target: URL;
|
|
377
|
+
try {
|
|
378
|
+
target = new URL(targetUrl);
|
|
379
|
+
} catch {
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
const hostname = normalizedResolverHostname(target.hostname);
|
|
383
|
+
return (
|
|
384
|
+
target.protocol === "https:" &&
|
|
385
|
+
hostname.length > AWS_WAF_CHALLENGE_INFRASTRUCTURE_HOST_SUFFIX.length &&
|
|
386
|
+
hostname.endsWith(AWS_WAF_CHALLENGE_INFRASTRUCTURE_HOST_SUFFIX)
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const POOL_ALLOCATION_EXHAUSTED_CODES = new Set([
|
|
391
|
+
-32_001, // queue full
|
|
392
|
+
-32_002, // acquire timed out
|
|
393
|
+
-32_003, // shutting down
|
|
394
|
+
]);
|
|
395
|
+
|
|
396
|
+
function poolErrorCode(error: Error): number | undefined {
|
|
397
|
+
const code = (error as Error & { readonly code?: unknown }).code;
|
|
398
|
+
return typeof code === "number" ? code : undefined;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function knownUnavailableReason(
|
|
402
|
+
error: unknown,
|
|
403
|
+
beforePageSolve = false,
|
|
404
|
+
): "allocation_exhausted" | "missing_credentials" | "transport_failure" | undefined {
|
|
405
|
+
// Source-grounded mappings:
|
|
406
|
+
// - apps/cdp-pool/src/index.ts: the JSON-RPC codes and messages below.
|
|
407
|
+
// - src/runtime/browser.ts: BROWSER_CDP_POOL_REQUIRED and the two WebSocket messages.
|
|
408
|
+
// The pool's numeric JSON-RPC code is authoritative and is preferred whenever present.
|
|
409
|
+
// The message substrings remain as a fallback for pool builds predating code
|
|
410
|
+
// propagation; they are exact strings verified against the pool source. -32004 (unknown
|
|
411
|
+
// lease) and -32006 (missing allowedHosts) are deliberately unmapped: both are caller
|
|
412
|
+
// bugs, and the next vendor would fail identically, so they propagate unchanged.
|
|
413
|
+
if (isProviderError(error)) {
|
|
414
|
+
return error.code === "BROWSER_CDP_POOL_REQUIRED" ? "missing_credentials" : undefined;
|
|
415
|
+
}
|
|
416
|
+
if (!(error instanceof Error)) return undefined;
|
|
417
|
+
|
|
418
|
+
const code = poolErrorCode(error);
|
|
419
|
+
if (code !== undefined) {
|
|
420
|
+
return POOL_ALLOCATION_EXHAUSTED_CODES.has(code) ? "allocation_exhausted" : undefined;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (
|
|
424
|
+
error.message.includes("CDP pool acquire queue is full") ||
|
|
425
|
+
error.message.includes("CDP pool acquire timed out") ||
|
|
426
|
+
error.message.includes("CDP pool is shutting down")
|
|
427
|
+
) {
|
|
428
|
+
return "allocation_exhausted";
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (
|
|
432
|
+
error.message.includes("Unable to connect to WebSocket endpoint") ||
|
|
433
|
+
error.message.includes("WebSocket closed")
|
|
434
|
+
) {
|
|
435
|
+
return "transport_failure";
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Browser creation, Playwright launch, and CDP connection all happen before the
|
|
439
|
+
// isolated-page handler is entered. Errors after that boundary belong to the
|
|
440
|
+
// challenge solve and must retain their existing classification.
|
|
441
|
+
return beforePageSolve ? "transport_failure" : undefined;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
async function closeBrowserClient(
|
|
445
|
+
client: BrowserClient | undefined,
|
|
446
|
+
timeoutMs: number,
|
|
447
|
+
challengeKind: ProviderChallenge["kind"],
|
|
448
|
+
traceRecorder: TraceRecorder | undefined,
|
|
449
|
+
): Promise<void> {
|
|
450
|
+
const close = client?.close;
|
|
451
|
+
if (!close) return;
|
|
452
|
+
await runBoundedCleanup(
|
|
453
|
+
() => close.call(client),
|
|
454
|
+
timeoutMs,
|
|
455
|
+
challengeKind,
|
|
456
|
+
"client.close",
|
|
457
|
+
traceRecorder,
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export function createBrowserResolverVendorAdapter(
|
|
462
|
+
options: BrowserResolverVendorOptions,
|
|
463
|
+
): BrowserResolverVendorAdapter {
|
|
464
|
+
const createClient = options.createClient ?? createResolverBrowserClient;
|
|
465
|
+
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_COOKIE_POLL_INTERVAL_MS;
|
|
466
|
+
|
|
467
|
+
return {
|
|
468
|
+
id: BROWSER_VENDOR_ID,
|
|
469
|
+
|
|
470
|
+
supports(kind) {
|
|
471
|
+
return isSupportedKind(kind);
|
|
472
|
+
},
|
|
473
|
+
|
|
474
|
+
getIssuingIdentity(solution, requestedIdentity, challenge) {
|
|
475
|
+
if (solution.form !== "cookies" || !isSupportedKind(challenge.kind)) return undefined;
|
|
476
|
+
return resolverChallengeIssuingIdentity(challenge, {
|
|
477
|
+
...(requestedIdentity ? { proxyUrl: requestedIdentity.proxyUrl } : {}),
|
|
478
|
+
userAgent: solution.userAgent,
|
|
479
|
+
});
|
|
480
|
+
},
|
|
481
|
+
|
|
482
|
+
async solve(challenge, identity, callerSignal, traceRecorder) {
|
|
483
|
+
const cdpUrl = options.cdpUrl?.trim();
|
|
484
|
+
const proxyUrl = identity?.proxyUrl;
|
|
485
|
+
if (!cdpUrl && proxyUrl === undefined) {
|
|
486
|
+
throw new ResolverVendorUnavailableError(BROWSER_VENDOR_ID, "missing_credentials");
|
|
487
|
+
}
|
|
488
|
+
if (!isSupportedKind(challenge.kind)) {
|
|
489
|
+
throw new TypeError(`Browser resolver does not support ${challenge.kind}`);
|
|
490
|
+
}
|
|
491
|
+
assertResolverHostAllowed(challenge.pageUrl, options.allowedHosts);
|
|
492
|
+
const challengeKind = challenge.kind;
|
|
493
|
+
callerSignal.throwIfAborted();
|
|
494
|
+
if (proxyUrl !== undefined && proxyUrl.length === 0) {
|
|
495
|
+
throw new ResolverVendorUnavailableError(BROWSER_VENDOR_ID, "missing_proxy_identity");
|
|
496
|
+
}
|
|
497
|
+
if (cdpUrl && proxyUrl !== undefined) {
|
|
498
|
+
// The current pool acquire protocol cannot bind a proxy to its browser context.
|
|
499
|
+
// Refuse so the chain can choose a vendor that can honor the resolved identity.
|
|
500
|
+
throw new ResolverVendorUnavailableError(BROWSER_VENDOR_ID, "not_implemented");
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const blockedRequests = new Set<string>();
|
|
504
|
+
const solveController = new AbortController();
|
|
505
|
+
const onCallerAbort = () => solveController.abort(abortReason(callerSignal));
|
|
506
|
+
callerSignal.addEventListener("abort", onCallerAbort, { once: true });
|
|
507
|
+
const timeout = setTimeout(
|
|
508
|
+
() => solveController.abort(new BrowserSolveTimeoutError([...blockedRequests])),
|
|
509
|
+
options.timeoutMs,
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
let client: BrowserClient | undefined;
|
|
513
|
+
let handlerEntered = false;
|
|
514
|
+
try {
|
|
515
|
+
client = createClient({
|
|
516
|
+
allowedHosts: [...options.allowedHosts],
|
|
517
|
+
cdpUrl: cdpUrl ?? "",
|
|
518
|
+
...(proxyUrl === undefined ? {} : { proxy: proxyUrl }),
|
|
519
|
+
requireCdpPool: cdpUrl !== undefined,
|
|
520
|
+
serviceWorkers: "block",
|
|
521
|
+
telemetry: options.telemetry,
|
|
522
|
+
});
|
|
523
|
+
/**
|
|
524
|
+
* Direct vendor callers without a telemetry sink keep the historical trace shape.
|
|
525
|
+
* Bound server requests record browser page spans under resolver.vendor.attempt,
|
|
526
|
+
* with resolver.vendor.cleanup as a sibling of the browser context span.
|
|
527
|
+
*/
|
|
528
|
+
if (traceRecorder && options.telemetry)
|
|
529
|
+
client = instrumentResolverBrowser(client, traceRecorder);
|
|
530
|
+
const contextOperation = client.withIsolatedContext(async (page) => {
|
|
531
|
+
handlerEntered = true;
|
|
532
|
+
return await solveInPage(
|
|
533
|
+
page,
|
|
534
|
+
challengeKind,
|
|
535
|
+
challenge.pageUrl,
|
|
536
|
+
options.allowedHosts,
|
|
537
|
+
SUCCESS_COOKIE_NAMES[challengeKind],
|
|
538
|
+
pollIntervalMs,
|
|
539
|
+
options.timeoutMs,
|
|
540
|
+
blockedRequests,
|
|
541
|
+
solveController.signal,
|
|
542
|
+
);
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
try {
|
|
546
|
+
return await raceWithAbort(() => contextOperation, solveController.signal);
|
|
547
|
+
} catch (error) {
|
|
548
|
+
if (solveController.signal.aborted) {
|
|
549
|
+
if (handlerEntered) {
|
|
550
|
+
await runBoundedCleanup(
|
|
551
|
+
() => contextOperation,
|
|
552
|
+
options.timeoutMs,
|
|
553
|
+
challengeKind,
|
|
554
|
+
"context.close",
|
|
555
|
+
traceRecorder,
|
|
556
|
+
);
|
|
557
|
+
throw error;
|
|
558
|
+
}
|
|
559
|
+
await closeBrowserClient(client, options.timeoutMs, challengeKind, traceRecorder);
|
|
560
|
+
void contextOperation.catch(() => undefined);
|
|
561
|
+
}
|
|
562
|
+
throw error;
|
|
563
|
+
}
|
|
564
|
+
} catch (error) {
|
|
565
|
+
if (callerSignal.aborted) throw abortReason(callerSignal);
|
|
566
|
+
if (error instanceof BrowserSolveTimeoutError) {
|
|
567
|
+
throw new ResolverVendorUnavailableError(BROWSER_VENDOR_ID, "timeout", {
|
|
568
|
+
cause: error,
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
if (error instanceof BrowserNavigationBlockedError) {
|
|
572
|
+
throw new ResolverVendorUnavailableError(BROWSER_VENDOR_ID, "transport_failure", {
|
|
573
|
+
cause: error,
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
if (error instanceof ResolverVendorUnavailableError) {
|
|
577
|
+
throw error;
|
|
578
|
+
}
|
|
579
|
+
const reason = knownUnavailableReason(error, !handlerEntered);
|
|
580
|
+
if (reason) {
|
|
581
|
+
throw new ResolverVendorUnavailableError(BROWSER_VENDOR_ID, reason, { cause: error });
|
|
582
|
+
}
|
|
583
|
+
throw error;
|
|
584
|
+
} finally {
|
|
585
|
+
clearTimeout(timeout);
|
|
586
|
+
callerSignal.removeEventListener("abort", onCallerAbort);
|
|
587
|
+
await closeBrowserClient(client, options.timeoutMs, challengeKind, traceRecorder);
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
};
|
|
591
|
+
}
|