@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,100 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
const requireModule = createRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
/** The TypeScript compiler API surface the source-level lint rules parse with. */
|
|
6
|
+
export type TypeScriptModule = typeof import("typescript");
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* What a caller hands over as a compiler module. Typed structurally so the
|
|
10
|
+
* option does not depend on which `typescript` package the caller's own type
|
|
11
|
+
* resolution lands on: under a `typescript@7` pin `typeof import("typescript")`
|
|
12
|
+
* is the native shell's version module, not the compiler API. The members are
|
|
13
|
+
* optional for the same reason — the shell has none of them — and
|
|
14
|
+
* `isTypeScriptCompilerModule` decides at runtime whether the module can parse.
|
|
15
|
+
*/
|
|
16
|
+
export type TypeScriptCompilerModuleLike = {
|
|
17
|
+
readonly createSourceFile?: (...parameters: never[]) => unknown;
|
|
18
|
+
readonly ScriptTarget?: object;
|
|
19
|
+
readonly version?: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Package specifiers that may carry the compiler API, in resolution order.
|
|
24
|
+
*
|
|
25
|
+
* `typescript@7` (the Go-native toolchain) resolves but its JavaScript entry
|
|
26
|
+
* exports only `version`/`getExePath` — no `createSourceFile`, so the lint
|
|
27
|
+
* rules cannot parse with it. The compiler API of that generation is published
|
|
28
|
+
* as `@typescript/typescript6`, which is what a `typescript@7` dependency tree
|
|
29
|
+
* (for example the APIFuse monorepo root) installs alongside the shell.
|
|
30
|
+
*/
|
|
31
|
+
export const TYPESCRIPT_COMPILER_MODULE_SPECIFIERS = [
|
|
32
|
+
"typescript",
|
|
33
|
+
"@typescript/typescript6",
|
|
34
|
+
] as const;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* True when `candidate` is a loaded module that exposes the parser the lint
|
|
38
|
+
* rules need. Internal (narrows to the `typescript` module type, which is not
|
|
39
|
+
* part of the package surface); `lintRuntimeBoundarySources` applies it to the
|
|
40
|
+
* caller-supplied option.
|
|
41
|
+
*/
|
|
42
|
+
export function isTypeScriptCompilerModule(candidate: unknown): candidate is TypeScriptModule {
|
|
43
|
+
return (
|
|
44
|
+
typeof candidate === "object" &&
|
|
45
|
+
candidate !== null &&
|
|
46
|
+
typeof (candidate as { createSourceFile?: unknown }).createSourceFile === "function" &&
|
|
47
|
+
typeof (candidate as { ScriptTarget?: unknown }).ScriptTarget === "object"
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function describeCandidate(candidate: unknown): string {
|
|
52
|
+
if (typeof candidate === "object" && candidate !== null) {
|
|
53
|
+
const version = (candidate as { version?: unknown }).version;
|
|
54
|
+
if (typeof version === "string") return `resolved ${version} without a compiler API`;
|
|
55
|
+
}
|
|
56
|
+
return "resolved without a compiler API";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Resolve the compiler API through `load`, trying each specifier in order and
|
|
61
|
+
* accepting the first module that exposes `createSourceFile`. Exposed for the
|
|
62
|
+
* tests; production code uses `getTypeScript()`.
|
|
63
|
+
*/
|
|
64
|
+
export function loadTypeScriptModule(
|
|
65
|
+
load: (specifier: string) => unknown,
|
|
66
|
+
specifiers: readonly string[] = TYPESCRIPT_COMPILER_MODULE_SPECIFIERS,
|
|
67
|
+
): TypeScriptModule {
|
|
68
|
+
const attempts: string[] = [];
|
|
69
|
+
for (const specifier of specifiers) {
|
|
70
|
+
let candidate: unknown;
|
|
71
|
+
try {
|
|
72
|
+
candidate = load(specifier);
|
|
73
|
+
} catch {
|
|
74
|
+
attempts.push(`${specifier}: not resolvable`);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (isTypeScriptCompilerModule(candidate)) return candidate;
|
|
78
|
+
attempts.push(`${specifier}: ${describeCandidate(candidate)}`);
|
|
79
|
+
}
|
|
80
|
+
throw new Error(
|
|
81
|
+
`The provider source lint needs the TypeScript compiler API (createSourceFile) and none of the resolvable packages provide it — ${attempts.join("; ")}. Install typescript 6.x as a devDependency, or @typescript/typescript6 next to a typescript 7 toolchain, in the dependency tree that installs @apifuse/provider-sdk.`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Lazily loaded TypeScript compiler API shared by the source-level lint rules.
|
|
87
|
+
*
|
|
88
|
+
* `typeof import(...)` keeps the type without emitting a static import: the
|
|
89
|
+
* typescript package is a devDependency of the SDK and only the CLI and the
|
|
90
|
+
* lint rules need it at runtime, which the typescript-import-boundary test
|
|
91
|
+
* enforces for production sources. Resolution starts at the installed SDK, so
|
|
92
|
+
* the caller's dependency tree must provide one of
|
|
93
|
+
* `TYPESCRIPT_COMPILER_MODULE_SPECIFIERS`.
|
|
94
|
+
*/
|
|
95
|
+
let typeScriptModule: TypeScriptModule | undefined;
|
|
96
|
+
|
|
97
|
+
export function getTypeScript(): TypeScriptModule {
|
|
98
|
+
typeScriptModule ??= loadTypeScriptModule(requireModule);
|
|
99
|
+
return typeScriptModule;
|
|
100
|
+
}
|
package/dist/choice-token.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export type ProviderChoiceTokenPayload = Record<string, unknown>;
|
|
2
|
-
export type ProviderChoiceTokenErrorReason = "invalid_shape" | "invalid_signature" | "invalid_payload" | "invalid_binding" | "stale";
|
|
3
|
-
export declare class ProviderChoiceTokenError extends Error {
|
|
4
|
-
readonly reason: ProviderChoiceTokenErrorReason;
|
|
5
|
-
constructor(reason: ProviderChoiceTokenErrorReason, message: string);
|
|
6
|
-
}
|
|
7
|
-
export interface CreateProviderChoiceTokenOptions<TPayload extends ProviderChoiceTokenPayload> {
|
|
8
|
-
prefix: string;
|
|
9
|
-
payload: TPayload;
|
|
10
|
-
secret: string;
|
|
11
|
-
}
|
|
12
|
-
export interface ParseProviderChoiceTokenOptions {
|
|
13
|
-
token: string;
|
|
14
|
-
prefix: string;
|
|
15
|
-
secret: string;
|
|
16
|
-
}
|
|
17
|
-
export interface FreshProviderChoiceIssuedAtOptions {
|
|
18
|
-
ttlMs: number;
|
|
19
|
-
nowMs?: number;
|
|
20
|
-
futureToleranceMs?: number;
|
|
21
|
-
}
|
|
22
|
-
export declare function createProviderChoiceToken<TPayload extends ProviderChoiceTokenPayload>(options: CreateProviderChoiceTokenOptions<TPayload>): string;
|
|
23
|
-
export declare function parseProviderChoiceToken(options: ParseProviderChoiceTokenOptions): ProviderChoiceTokenPayload;
|
|
24
|
-
export declare function assertFreshProviderChoiceIssuedAt(issuedAtMs: unknown, options: FreshProviderChoiceIssuedAtOptions): number;
|
package/dist/choice-token.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes, timingSafeEqual, } from "node:crypto";
|
|
2
|
-
export class ProviderChoiceTokenError extends Error {
|
|
3
|
-
reason;
|
|
4
|
-
constructor(reason, message) {
|
|
5
|
-
super(message);
|
|
6
|
-
this.name = "ProviderChoiceTokenError";
|
|
7
|
-
this.reason = reason;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
export function createProviderChoiceToken(options) {
|
|
11
|
-
const iv = randomBytes(12);
|
|
12
|
-
const cipher = createCipheriv("aes-256-gcm", choiceEncryptionKey(options.secret), iv);
|
|
13
|
-
const encryptedPayload = Buffer.concat([
|
|
14
|
-
cipher.update(JSON.stringify(options.payload), "utf8"),
|
|
15
|
-
cipher.final(),
|
|
16
|
-
]).toString("base64url");
|
|
17
|
-
const authTag = cipher.getAuthTag().toString("base64url");
|
|
18
|
-
const encodedIv = iv.toString("base64url");
|
|
19
|
-
const signature = signProviderChoiceTokenBody(`${options.prefix}.${encodedIv}.${encryptedPayload}.${authTag}`, options.secret);
|
|
20
|
-
return `${options.prefix}.${encodedIv}.${encryptedPayload}.${authTag}.${signature}`;
|
|
21
|
-
}
|
|
22
|
-
export function parseProviderChoiceToken(options) {
|
|
23
|
-
const [actualPrefix, encodedIv, encryptedPayload, authTag, signature, ...extra] = options.token.split(".");
|
|
24
|
-
if (actualPrefix !== options.prefix ||
|
|
25
|
-
!encodedIv ||
|
|
26
|
-
!encryptedPayload ||
|
|
27
|
-
!authTag ||
|
|
28
|
-
!signature ||
|
|
29
|
-
extra.length > 0) {
|
|
30
|
-
throw new ProviderChoiceTokenError("invalid_shape", "Provider choice token shape is invalid.");
|
|
31
|
-
}
|
|
32
|
-
const signedBody = `${options.prefix}.${encodedIv}.${encryptedPayload}.${authTag}`;
|
|
33
|
-
const expectedSignature = signProviderChoiceTokenBody(signedBody, options.secret);
|
|
34
|
-
const actualBuffer = Buffer.from(signature);
|
|
35
|
-
const expectedBuffer = Buffer.from(expectedSignature);
|
|
36
|
-
if (actualBuffer.length !== expectedBuffer.length ||
|
|
37
|
-
!timingSafeEqual(actualBuffer, expectedBuffer)) {
|
|
38
|
-
throw new ProviderChoiceTokenError("invalid_signature", "Provider choice token signature is invalid.");
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
const decipher = createDecipheriv("aes-256-gcm", choiceEncryptionKey(options.secret), Buffer.from(encodedIv, "base64url"));
|
|
42
|
-
decipher.setAuthTag(Buffer.from(authTag, "base64url"));
|
|
43
|
-
const decrypted = Buffer.concat([
|
|
44
|
-
decipher.update(Buffer.from(encryptedPayload, "base64url")),
|
|
45
|
-
decipher.final(),
|
|
46
|
-
]).toString("utf8");
|
|
47
|
-
const parsed = JSON.parse(decrypted);
|
|
48
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
49
|
-
throw new Error("payload is not an object");
|
|
50
|
-
}
|
|
51
|
-
return Object.fromEntries(Object.entries(parsed));
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
throw new ProviderChoiceTokenError("invalid_payload", "Provider choice token payload is invalid.");
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
export function assertFreshProviderChoiceIssuedAt(issuedAtMs, options) {
|
|
58
|
-
const parsed = typeof issuedAtMs === "number" ? issuedAtMs : Number(issuedAtMs);
|
|
59
|
-
const nowMs = options.nowMs ?? Date.now();
|
|
60
|
-
const futureToleranceMs = options.futureToleranceMs ?? 30_000;
|
|
61
|
-
if (!Number.isFinite(parsed) ||
|
|
62
|
-
parsed <= 0 ||
|
|
63
|
-
nowMs - parsed > options.ttlMs ||
|
|
64
|
-
parsed - nowMs > futureToleranceMs) {
|
|
65
|
-
throw new ProviderChoiceTokenError("stale", "Provider choice token is stale.");
|
|
66
|
-
}
|
|
67
|
-
return parsed;
|
|
68
|
-
}
|
|
69
|
-
function choiceEncryptionKey(secret) {
|
|
70
|
-
return createHash("sha256").update(secret).digest();
|
|
71
|
-
}
|
|
72
|
-
function signProviderChoiceTokenBody(body, secret) {
|
|
73
|
-
return createHmac("sha256", secret).update(body).digest("base64url");
|
|
74
|
-
}
|
package/dist/runtime/choice.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { CredentialContext, EnvContext, ProviderChoiceContext, ProviderRequestContext, ProviderRuntimeState } from "../types.js";
|
|
2
|
-
export declare const PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV = "APIFUSE__PROVIDER_RUNTIME__CHOICE_TOKEN_MASTER_SECRET";
|
|
3
|
-
export type CreateProviderChoiceContextOptions = {
|
|
4
|
-
readonly providerId: string;
|
|
5
|
-
readonly env?: EnvContext;
|
|
6
|
-
readonly request?: ProviderRequestContext;
|
|
7
|
-
readonly credential?: CredentialContext;
|
|
8
|
-
readonly state?: ProviderRuntimeState;
|
|
9
|
-
readonly masterSecret?: string;
|
|
10
|
-
readonly kid?: string;
|
|
11
|
-
};
|
|
12
|
-
export declare function createProviderChoiceContext(options: CreateProviderChoiceContextOptions): ProviderChoiceContext;
|
|
13
|
-
export declare function createTestProviderChoiceContext(options: Omit<CreateProviderChoiceContextOptions, "masterSecret"> & {
|
|
14
|
-
readonly masterSecret?: string;
|
|
15
|
-
}): ProviderChoiceContext;
|
package/dist/runtime/choice.js
DELETED
|
@@ -1,413 +0,0 @@
|
|
|
1
|
-
import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes, timingSafeEqual, } from "node:crypto";
|
|
2
|
-
import { assertFreshProviderChoiceIssuedAt, ProviderChoiceTokenError, } from "../choice-token.js";
|
|
3
|
-
import { ProviderError } from "../errors.js";
|
|
4
|
-
export const PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV = "APIFUSE__PROVIDER_RUNTIME__CHOICE_TOKEN_MASTER_SECRET";
|
|
5
|
-
const PRIMARY_CHOICE_TOKEN_KID = "v1";
|
|
6
|
-
const MANAGED_CHOICE_TOKEN_VERSION = 1;
|
|
7
|
-
export function createProviderChoiceContext(options) {
|
|
8
|
-
const kid = options.kid ?? PRIMARY_CHOICE_TOKEN_KID;
|
|
9
|
-
const resolveMasterSecret = () => resolveChoiceMasterSecret(options);
|
|
10
|
-
function issue(issueOptions) {
|
|
11
|
-
const issuedAtMs = issueOptions.nowMs ?? Date.now();
|
|
12
|
-
const keys = deriveManagedChoiceKeys({
|
|
13
|
-
masterSecret: resolveMasterSecret(),
|
|
14
|
-
providerId: options.providerId,
|
|
15
|
-
purpose: issueOptions.purpose,
|
|
16
|
-
kid,
|
|
17
|
-
});
|
|
18
|
-
const baseEnvelope = {
|
|
19
|
-
v: MANAGED_CHOICE_TOKEN_VERSION,
|
|
20
|
-
provider_id: options.providerId,
|
|
21
|
-
purpose: issueOptions.purpose,
|
|
22
|
-
issued_at_ms: issuedAtMs,
|
|
23
|
-
ttl_ms: issueOptions.ttlMs,
|
|
24
|
-
binding: createChoiceBinding({
|
|
25
|
-
keys,
|
|
26
|
-
options: issueOptions.bind,
|
|
27
|
-
request: options.request,
|
|
28
|
-
credential: options.credential,
|
|
29
|
-
required: true,
|
|
30
|
-
}),
|
|
31
|
-
};
|
|
32
|
-
const resolvedStorage = resolveIssueStorage(issueOptions.storage, issueOptions.payload);
|
|
33
|
-
if (resolvedStorage.mode === "server") {
|
|
34
|
-
return issueServerStoredChoice({
|
|
35
|
-
baseEnvelope,
|
|
36
|
-
issueOptions,
|
|
37
|
-
storage: resolvedStorage.storage,
|
|
38
|
-
contextState: options.state,
|
|
39
|
-
kid,
|
|
40
|
-
keys,
|
|
41
|
-
issuedAtMs,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
const envelope = {
|
|
45
|
-
...baseEnvelope,
|
|
46
|
-
payload: issueOptions.payload,
|
|
47
|
-
};
|
|
48
|
-
return encryptManagedChoiceToken({
|
|
49
|
-
prefix: issueOptions.prefix,
|
|
50
|
-
kid,
|
|
51
|
-
envelope,
|
|
52
|
-
keys,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
function parse(parseOptions) {
|
|
56
|
-
const [actualPrefix, tokenKid, encodedIv, encryptedPayload, authTag, signature] = parseManagedChoiceTokenParts(parseOptions.token);
|
|
57
|
-
if (actualPrefix !== parseOptions.prefix ||
|
|
58
|
-
tokenKid !== kid ||
|
|
59
|
-
!encodedIv ||
|
|
60
|
-
!encryptedPayload ||
|
|
61
|
-
!authTag ||
|
|
62
|
-
!signature) {
|
|
63
|
-
throw new ProviderChoiceTokenError("invalid_shape", "Provider choice token shape is invalid.");
|
|
64
|
-
}
|
|
65
|
-
const keys = deriveManagedChoiceKeys({
|
|
66
|
-
masterSecret: resolveMasterSecret(),
|
|
67
|
-
providerId: options.providerId,
|
|
68
|
-
purpose: parseOptions.purpose,
|
|
69
|
-
kid: tokenKid,
|
|
70
|
-
});
|
|
71
|
-
const signedBody = [parseOptions.prefix, tokenKid, encodedIv, encryptedPayload, authTag].join(".");
|
|
72
|
-
assertManagedChoiceSignature({
|
|
73
|
-
signedBody,
|
|
74
|
-
signature,
|
|
75
|
-
signingKey: keys.signing,
|
|
76
|
-
});
|
|
77
|
-
const envelope = decryptManagedChoiceToken({
|
|
78
|
-
encodedIv,
|
|
79
|
-
encryptedPayload,
|
|
80
|
-
authTag,
|
|
81
|
-
encryptionKey: keys.encryption,
|
|
82
|
-
});
|
|
83
|
-
assertManagedChoiceEnvelope(envelope, {
|
|
84
|
-
providerId: options.providerId,
|
|
85
|
-
purpose: parseOptions.purpose,
|
|
86
|
-
ttlMs: parseOptions.ttlMs,
|
|
87
|
-
nowMs: parseOptions.nowMs,
|
|
88
|
-
futureToleranceMs: parseOptions.futureToleranceMs,
|
|
89
|
-
});
|
|
90
|
-
assertChoiceBindingMatches({
|
|
91
|
-
actual: envelope.binding,
|
|
92
|
-
expected: createChoiceBinding({
|
|
93
|
-
keys,
|
|
94
|
-
options: parseOptions.bind,
|
|
95
|
-
request: options.request,
|
|
96
|
-
credential: options.credential,
|
|
97
|
-
required: true,
|
|
98
|
-
}),
|
|
99
|
-
});
|
|
100
|
-
if (isServerChoiceHandlePayload(envelope.payload)) {
|
|
101
|
-
return parseServerStoredChoice({
|
|
102
|
-
handle: envelope.payload,
|
|
103
|
-
storage: parseOptions.storage,
|
|
104
|
-
contextState: options.state,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
return envelope.payload;
|
|
108
|
-
}
|
|
109
|
-
return { issue, parse };
|
|
110
|
-
}
|
|
111
|
-
export function createTestProviderChoiceContext(options) {
|
|
112
|
-
return createProviderChoiceContext({
|
|
113
|
-
...options,
|
|
114
|
-
masterSecret: options.masterSecret ?? "apifuse-test-provider-runtime-choice-token-master-secret",
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
function resolveChoiceMasterSecret(options) {
|
|
118
|
-
const configured = options.masterSecret ?? options.env?.get(PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV);
|
|
119
|
-
const trimmed = configured?.trim();
|
|
120
|
-
if (trimmed)
|
|
121
|
-
return trimmed;
|
|
122
|
-
throw new ProviderError("Provider runtime choice-token master secret is not configured.", {
|
|
123
|
-
code: "CHOICE_TOKEN_MASTER_SECRET_NOT_CONFIGURED",
|
|
124
|
-
category: "internal_error",
|
|
125
|
-
retryable: false,
|
|
126
|
-
details: {
|
|
127
|
-
secret: PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV,
|
|
128
|
-
},
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
function deriveManagedChoiceKeys(input) {
|
|
132
|
-
return {
|
|
133
|
-
encryption: deriveManagedChoiceKey(input, "encryption"),
|
|
134
|
-
signing: deriveManagedChoiceKey(input, "signing"),
|
|
135
|
-
binding: deriveManagedChoiceKey(input, "binding"),
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
function deriveManagedChoiceKey(input, usage) {
|
|
139
|
-
return createHmac("sha256", input.masterSecret)
|
|
140
|
-
.update("apifuse-provider-choice-token")
|
|
141
|
-
.update("\0")
|
|
142
|
-
.update(input.providerId)
|
|
143
|
-
.update("\0")
|
|
144
|
-
.update(input.purpose)
|
|
145
|
-
.update("\0")
|
|
146
|
-
.update(input.kid)
|
|
147
|
-
.update("\0")
|
|
148
|
-
.update(usage)
|
|
149
|
-
.digest();
|
|
150
|
-
}
|
|
151
|
-
function encryptManagedChoiceToken(options) {
|
|
152
|
-
const iv = randomBytes(12);
|
|
153
|
-
const cipher = createCipheriv("aes-256-gcm", options.keys.encryption, iv);
|
|
154
|
-
const encryptedPayload = Buffer.concat([
|
|
155
|
-
cipher.update(JSON.stringify(options.envelope), "utf8"),
|
|
156
|
-
cipher.final(),
|
|
157
|
-
]).toString("base64url");
|
|
158
|
-
const authTag = cipher.getAuthTag().toString("base64url");
|
|
159
|
-
const encodedIv = iv.toString("base64url");
|
|
160
|
-
const signedBody = [options.prefix, options.kid, encodedIv, encryptedPayload, authTag].join(".");
|
|
161
|
-
const signature = createHmac("sha256", options.keys.signing)
|
|
162
|
-
.update(signedBody)
|
|
163
|
-
.digest("base64url");
|
|
164
|
-
return `${signedBody}.${signature}`;
|
|
165
|
-
}
|
|
166
|
-
async function issueServerStoredChoice(options) {
|
|
167
|
-
const serializedPayload = serializeChoicePayload(options.issueOptions.payload);
|
|
168
|
-
const payloadBytes = Buffer.byteLength(serializedPayload, "utf8");
|
|
169
|
-
if (payloadBytes > options.storage.maxValueBytes) {
|
|
170
|
-
throw new ProviderError("Provider choice payload exceeds state storage policy.", {
|
|
171
|
-
code: "CHOICE_STATE_PAYLOAD_TOO_LARGE",
|
|
172
|
-
category: "input_validation",
|
|
173
|
-
retryable: false,
|
|
174
|
-
details: {
|
|
175
|
-
maxValueBytes: options.storage.maxValueBytes,
|
|
176
|
-
payloadBytes,
|
|
177
|
-
},
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
const stateId = `choice_${randomBytes(16).toString("base64url")}`;
|
|
181
|
-
const digest = digestChoicePayload(serializedPayload);
|
|
182
|
-
const namespace = resolveChoiceStateNamespace({
|
|
183
|
-
storage: options.storage,
|
|
184
|
-
contextState: options.contextState,
|
|
185
|
-
ttlMs: options.issueOptions.ttlMs,
|
|
186
|
-
});
|
|
187
|
-
await namespace.set(optionsStateKey(stateId), options.issueOptions.payload, {
|
|
188
|
-
ttl: stateTtl(options.storage, options.issueOptions.ttlMs),
|
|
189
|
-
});
|
|
190
|
-
const envelope = {
|
|
191
|
-
...options.baseEnvelope,
|
|
192
|
-
payload: {
|
|
193
|
-
storage: "server",
|
|
194
|
-
state_id: stateId,
|
|
195
|
-
payload_digest: digest,
|
|
196
|
-
created_at_ms: options.issuedAtMs,
|
|
197
|
-
},
|
|
198
|
-
};
|
|
199
|
-
return encryptManagedChoiceToken({
|
|
200
|
-
prefix: options.issueOptions.prefix,
|
|
201
|
-
kid: options.kid,
|
|
202
|
-
envelope,
|
|
203
|
-
keys: options.keys,
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
async function parseServerStoredChoice(options) {
|
|
207
|
-
const storage = resolveParseStorage(options.storage);
|
|
208
|
-
const namespace = resolveChoiceStateNamespace({
|
|
209
|
-
storage,
|
|
210
|
-
contextState: options.contextState,
|
|
211
|
-
});
|
|
212
|
-
const record = await namespace.get(optionsStateKey(options.handle.state_id));
|
|
213
|
-
if (!record) {
|
|
214
|
-
throw new ProviderChoiceTokenError("invalid_payload", "Provider choice token state payload is missing.");
|
|
215
|
-
}
|
|
216
|
-
const serializedPayload = serializeChoicePayload(record.value);
|
|
217
|
-
assertPayloadDigestMatches({
|
|
218
|
-
actual: digestChoicePayload(serializedPayload),
|
|
219
|
-
expected: options.handle.payload_digest,
|
|
220
|
-
});
|
|
221
|
-
return record.value;
|
|
222
|
-
}
|
|
223
|
-
function resolveIssueStorage(storage, payload) {
|
|
224
|
-
if (!storage || storage.mode === "inline")
|
|
225
|
-
return { mode: "inline" };
|
|
226
|
-
if (storage.mode === "server")
|
|
227
|
-
return { mode: "server", storage };
|
|
228
|
-
const payloadBytes = Buffer.byteLength(serializeChoicePayload(payload), "utf8");
|
|
229
|
-
if (payloadBytes <= storage.maxInlineBytes)
|
|
230
|
-
return { mode: "inline" };
|
|
231
|
-
return { mode: "server", storage };
|
|
232
|
-
}
|
|
233
|
-
function resolveParseStorage(storage) {
|
|
234
|
-
if (!storage || storage.mode === "inline") {
|
|
235
|
-
throw new ProviderChoiceTokenError("invalid_payload", "Provider choice token requires server-side choice storage.");
|
|
236
|
-
}
|
|
237
|
-
return storage;
|
|
238
|
-
}
|
|
239
|
-
function resolveChoiceStateNamespace(options) {
|
|
240
|
-
const state = options.storage.state ?? options.contextState;
|
|
241
|
-
if (!state) {
|
|
242
|
-
throw new ProviderError("Provider choice state storage is not available.", {
|
|
243
|
-
code: "CHOICE_STATE_UNAVAILABLE",
|
|
244
|
-
category: "internal_error",
|
|
245
|
-
retryable: false,
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
return state.namespace(options.storage.namespace, {
|
|
249
|
-
defaultTtl: stateTtl(options.storage, options.ttlMs),
|
|
250
|
-
maxTtl: stateTtl(options.storage, options.ttlMs),
|
|
251
|
-
maxEntries: options.storage.maxEntries,
|
|
252
|
-
maxValueBytes: options.storage.maxValueBytes,
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
function stateTtl(storage, ttlMs) {
|
|
256
|
-
return storage.ttl ?? `${ttlMs ?? 1}ms`;
|
|
257
|
-
}
|
|
258
|
-
function optionsStateKey(stateId) {
|
|
259
|
-
return stateId;
|
|
260
|
-
}
|
|
261
|
-
function serializeChoicePayload(payload) {
|
|
262
|
-
return JSON.stringify(payload);
|
|
263
|
-
}
|
|
264
|
-
function digestChoicePayload(serializedPayload) {
|
|
265
|
-
return createHash("sha256").update(serializedPayload).digest("base64url");
|
|
266
|
-
}
|
|
267
|
-
function isServerChoiceHandlePayload(value) {
|
|
268
|
-
return (value.storage === "server" &&
|
|
269
|
-
typeof value.state_id === "string" &&
|
|
270
|
-
typeof value.payload_digest === "string" &&
|
|
271
|
-
typeof value.created_at_ms === "number");
|
|
272
|
-
}
|
|
273
|
-
function assertPayloadDigestMatches(options) {
|
|
274
|
-
const actual = Buffer.from(options.actual);
|
|
275
|
-
const expected = Buffer.from(options.expected);
|
|
276
|
-
if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) {
|
|
277
|
-
throw new ProviderChoiceTokenError("invalid_payload", "Provider choice token state payload digest is invalid.");
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
function parseManagedChoiceTokenParts(token) {
|
|
281
|
-
const parts = token.split(".");
|
|
282
|
-
if (parts.length !== 6) {
|
|
283
|
-
throw new ProviderChoiceTokenError("invalid_shape", "Provider choice token shape is invalid.");
|
|
284
|
-
}
|
|
285
|
-
return [parts[0], parts[1], parts[2], parts[3], parts[4], parts[5]];
|
|
286
|
-
}
|
|
287
|
-
function assertManagedChoiceSignature(options) {
|
|
288
|
-
const expected = createHmac("sha256", options.signingKey)
|
|
289
|
-
.update(options.signedBody)
|
|
290
|
-
.digest("base64url");
|
|
291
|
-
const actualBuffer = Buffer.from(options.signature);
|
|
292
|
-
const expectedBuffer = Buffer.from(expected);
|
|
293
|
-
if (actualBuffer.length !== expectedBuffer.length ||
|
|
294
|
-
!timingSafeEqual(actualBuffer, expectedBuffer)) {
|
|
295
|
-
throw new ProviderChoiceTokenError("invalid_signature", "Provider choice token signature is invalid.");
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
function decryptManagedChoiceToken(options) {
|
|
299
|
-
try {
|
|
300
|
-
const decipher = createDecipheriv("aes-256-gcm", options.encryptionKey, Buffer.from(options.encodedIv, "base64url"));
|
|
301
|
-
decipher.setAuthTag(Buffer.from(options.authTag, "base64url"));
|
|
302
|
-
const decrypted = Buffer.concat([
|
|
303
|
-
decipher.update(Buffer.from(options.encryptedPayload, "base64url")),
|
|
304
|
-
decipher.final(),
|
|
305
|
-
]).toString("utf8");
|
|
306
|
-
const parsed = JSON.parse(decrypted);
|
|
307
|
-
if (!isManagedChoiceEnvelope(parsed)) {
|
|
308
|
-
throw new ProviderChoiceTokenError("invalid_payload", "Provider choice token payload is invalid.");
|
|
309
|
-
}
|
|
310
|
-
return parsed;
|
|
311
|
-
}
|
|
312
|
-
catch (error) {
|
|
313
|
-
if (error instanceof ProviderChoiceTokenError) {
|
|
314
|
-
throw error;
|
|
315
|
-
}
|
|
316
|
-
throw new ProviderChoiceTokenError("invalid_payload", "Provider choice token payload is invalid.");
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
function isManagedChoiceEnvelope(value) {
|
|
320
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
321
|
-
return false;
|
|
322
|
-
if (!("payload" in value) || !isChoicePayload(value.payload))
|
|
323
|
-
return false;
|
|
324
|
-
return ("v" in value &&
|
|
325
|
-
value.v === MANAGED_CHOICE_TOKEN_VERSION &&
|
|
326
|
-
"provider_id" in value &&
|
|
327
|
-
typeof value.provider_id === "string" &&
|
|
328
|
-
"purpose" in value &&
|
|
329
|
-
typeof value.purpose === "string" &&
|
|
330
|
-
"issued_at_ms" in value &&
|
|
331
|
-
typeof value.issued_at_ms === "number" &&
|
|
332
|
-
"ttl_ms" in value &&
|
|
333
|
-
typeof value.ttl_ms === "number" &&
|
|
334
|
-
(!("binding" in value) || value.binding === undefined || isChoiceBinding(value.binding)));
|
|
335
|
-
}
|
|
336
|
-
function isChoicePayload(value) {
|
|
337
|
-
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
338
|
-
}
|
|
339
|
-
function isChoiceBinding(value) {
|
|
340
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
341
|
-
return false;
|
|
342
|
-
return ((!("connection_hash" in value) || typeof value.connection_hash === "string") &&
|
|
343
|
-
(!("credential_hash" in value) || typeof value.credential_hash === "string"));
|
|
344
|
-
}
|
|
345
|
-
function assertManagedChoiceEnvelope(envelope, options) {
|
|
346
|
-
if (envelope.provider_id !== options.providerId || envelope.purpose !== options.purpose) {
|
|
347
|
-
throw new ProviderChoiceTokenError("invalid_payload", "Provider choice token payload is invalid.");
|
|
348
|
-
}
|
|
349
|
-
assertFreshProviderChoiceIssuedAt(envelope.issued_at_ms, {
|
|
350
|
-
// Clamp to the issuer's embedded TTL so a caller-supplied value cannot
|
|
351
|
-
// silently extend token validity past the deadline the issuer intended.
|
|
352
|
-
ttlMs: options.ttlMs != null ? Math.min(options.ttlMs, envelope.ttl_ms) : envelope.ttl_ms,
|
|
353
|
-
nowMs: options.nowMs,
|
|
354
|
-
futureToleranceMs: options.futureToleranceMs,
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
function createChoiceBinding(options) {
|
|
358
|
-
const connectionHash = options.options?.connection ? hashRequiredConnection(options) : undefined;
|
|
359
|
-
const credentialHash = options.options?.credentialKeys?.length
|
|
360
|
-
? hashCredentialKeys(options)
|
|
361
|
-
: undefined;
|
|
362
|
-
if (!connectionHash && !credentialHash)
|
|
363
|
-
return undefined;
|
|
364
|
-
return {
|
|
365
|
-
...(connectionHash ? { connection_hash: connectionHash } : {}),
|
|
366
|
-
...(credentialHash ? { credential_hash: credentialHash } : {}),
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
function hashRequiredConnection(options) {
|
|
370
|
-
const connectionId = options.request?.connectionId;
|
|
371
|
-
if (!connectionId) {
|
|
372
|
-
if (!options.required)
|
|
373
|
-
return undefined;
|
|
374
|
-
throw new ProviderError("Provider choice tokens require connection context.", {
|
|
375
|
-
code: "CHOICE_CONTEXT_REQUIRED",
|
|
376
|
-
category: "input_validation",
|
|
377
|
-
retryable: false,
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
return createHmac("sha256", options.keys.binding)
|
|
381
|
-
.update("connection")
|
|
382
|
-
.update("\0")
|
|
383
|
-
.update(connectionId)
|
|
384
|
-
.digest("base64url");
|
|
385
|
-
}
|
|
386
|
-
function hashCredentialKeys(options) {
|
|
387
|
-
const credentialKeys = options.options?.credentialKeys ?? [];
|
|
388
|
-
const material = credentialKeys.map((key) => {
|
|
389
|
-
const value = options.credential?.get(key);
|
|
390
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
391
|
-
throw new ProviderError("Provider choice tokens require configured credential binding.", {
|
|
392
|
-
code: "CHOICE_CONTEXT_REQUIRED",
|
|
393
|
-
category: "input_validation",
|
|
394
|
-
retryable: false,
|
|
395
|
-
details: { credentialKey: key },
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
return [key, value];
|
|
399
|
-
});
|
|
400
|
-
return createHmac("sha256", options.keys.binding)
|
|
401
|
-
.update("credential")
|
|
402
|
-
.update("\0")
|
|
403
|
-
.update(JSON.stringify(material))
|
|
404
|
-
.digest("base64url");
|
|
405
|
-
}
|
|
406
|
-
function assertChoiceBindingMatches(options) {
|
|
407
|
-
if (options.actual?.connection_hash !== options.expected?.connection_hash) {
|
|
408
|
-
throw new ProviderChoiceTokenError("invalid_binding", "Provider choice token connection binding is invalid.");
|
|
409
|
-
}
|
|
410
|
-
if (options.actual?.credential_hash !== options.expected?.credential_hash) {
|
|
411
|
-
throw new ProviderChoiceTokenError("invalid_binding", "Provider choice token credential binding is invalid.");
|
|
412
|
-
}
|
|
413
|
-
}
|