@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,522 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, readlinkSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { performance } from "node:perf_hooks";
|
|
4
|
+
|
|
5
|
+
import { SDK_VERSION } from "./sdk-version.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal runtime diagnostics route on the provider's primary listener, next
|
|
9
|
+
* to `/health` and `/readyz`. It answers one JSON report that tells an idle
|
|
10
|
+
* process that still burns CPU apart from a busy one without `exec`: process
|
|
11
|
+
* CPU sampled over a short window, memory, the Node event-loop and
|
|
12
|
+
* active-resource APIs, and on Linux the per-thread CPU and file-descriptor
|
|
13
|
+
* picture from `/proc/self`.
|
|
14
|
+
*
|
|
15
|
+
* Read-only and secret-free. It shares the boundary of `/health` and `/readyz`:
|
|
16
|
+
* the generated provider NetworkPolicy admits only the gateway on this port and
|
|
17
|
+
* the gateway dials canonical operation paths only, so a tenant cannot reach
|
|
18
|
+
* it; operators use `kubectl port-forward`.
|
|
19
|
+
*/
|
|
20
|
+
export const RUNTIME_DIAGNOSTICS_ROUTE = "/__apifuse/diagnostics/runtime";
|
|
21
|
+
export const RUNTIME_DIAGNOSTICS_SCHEMA_VERSION = 1 as const;
|
|
22
|
+
/** Query parameter naming the sampling window; clamped, never rejected. */
|
|
23
|
+
export const RUNTIME_DIAGNOSTICS_WINDOW_QUERY = "windowMs";
|
|
24
|
+
export const DEFAULT_RUNTIME_DIAGNOSTICS_WINDOW_MS = 250;
|
|
25
|
+
export const MIN_RUNTIME_DIAGNOSTICS_WINDOW_MS = 50;
|
|
26
|
+
export const MAX_RUNTIME_DIAGNOSTICS_WINDOW_MS = 5_000;
|
|
27
|
+
/**
|
|
28
|
+
* Linux USER_HZ. The unit of `utime`/`stime` in `/proc` stat files is an ABI
|
|
29
|
+
* constant (100 Hz) independent of the kernel's CONFIG_HZ.
|
|
30
|
+
*/
|
|
31
|
+
export const PROCFS_CLOCK_TICKS_PER_SECOND = 100;
|
|
32
|
+
export const DEFAULT_PROCFS_SELF_ROOT = "/proc/self";
|
|
33
|
+
|
|
34
|
+
export interface RuntimeDiagnosticsCpuTotals {
|
|
35
|
+
readonly userMicros: number;
|
|
36
|
+
readonly systemMicros: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface RuntimeDiagnosticsCpu {
|
|
40
|
+
/** `process.cpuUsage()` since boot and its average in cores over `uptimeSeconds`. */
|
|
41
|
+
readonly lifetime: RuntimeDiagnosticsCpuTotals & { readonly averageCores: number };
|
|
42
|
+
/** `process.cpuUsage()` delta over the sampling window, as cores (1 = one CPU fully busy). */
|
|
43
|
+
readonly window: RuntimeDiagnosticsCpuTotals & {
|
|
44
|
+
readonly userCores: number;
|
|
45
|
+
readonly systemCores: number;
|
|
46
|
+
readonly totalCores: number;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface RuntimeDiagnosticsEventLoopUtilization {
|
|
51
|
+
readonly idle: number;
|
|
52
|
+
readonly active: number;
|
|
53
|
+
readonly utilization: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface RuntimeDiagnosticsEventLoop {
|
|
57
|
+
/**
|
|
58
|
+
* false when the runtime returned only zeros for the whole process lifetime.
|
|
59
|
+
* Bun 1.2 and 1.3 stub `performance.eventLoopUtilization`; read
|
|
60
|
+
* `cpu.window` and `procfs.threads` instead.
|
|
61
|
+
*/
|
|
62
|
+
readonly reported: boolean;
|
|
63
|
+
readonly lifetime: RuntimeDiagnosticsEventLoopUtilization;
|
|
64
|
+
readonly window: RuntimeDiagnosticsEventLoopUtilization;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface RuntimeDiagnosticsActiveResources {
|
|
68
|
+
/**
|
|
69
|
+
* false when the runtime listed nothing, although at least the socket that
|
|
70
|
+
* answers this request is alive. Bun 1.2 and 1.3 stub
|
|
71
|
+
* `process.getActiveResourcesInfo`; read `procfs.fileDescriptors` instead.
|
|
72
|
+
*/
|
|
73
|
+
readonly reported: boolean;
|
|
74
|
+
readonly total: number;
|
|
75
|
+
readonly byType: Readonly<Record<string, number>>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface RuntimeDiagnosticsMemory {
|
|
79
|
+
readonly rss: number;
|
|
80
|
+
readonly heapTotal: number;
|
|
81
|
+
readonly heapUsed: number;
|
|
82
|
+
readonly external: number;
|
|
83
|
+
readonly arrayBuffers: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface RuntimeDiagnosticsThreadCpuTicks {
|
|
87
|
+
readonly userTicks: number;
|
|
88
|
+
readonly systemTicks: number;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface RuntimeDiagnosticsThreadContextSwitches {
|
|
92
|
+
readonly voluntary: number;
|
|
93
|
+
readonly nonvoluntary: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface RuntimeDiagnosticsThreadWindow extends RuntimeDiagnosticsThreadCpuTicks {
|
|
97
|
+
/** CPU consumed by this thread over the window, in cores. */
|
|
98
|
+
readonly cores: number;
|
|
99
|
+
readonly contextSwitches: RuntimeDiagnosticsThreadContextSwitches;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface RuntimeDiagnosticsThread {
|
|
103
|
+
readonly tid: number;
|
|
104
|
+
/** Kernel thread name (`comm`, 15 bytes), e.g. `bun`, `HTTP Client`, `HeapHelper`. */
|
|
105
|
+
readonly name: string;
|
|
106
|
+
/** Scheduler state letter at the second sample (`R` running, `S` sleeping, ...). */
|
|
107
|
+
readonly state: string;
|
|
108
|
+
/** Kernel wait channel at the second sample (`0` while running); null when unreadable. */
|
|
109
|
+
readonly waitChannel: string | null;
|
|
110
|
+
readonly lifetime: RuntimeDiagnosticsThreadCpuTicks;
|
|
111
|
+
/** null for a thread that appeared after the first sample. */
|
|
112
|
+
readonly window: RuntimeDiagnosticsThreadWindow | null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type RuntimeDiagnosticsFdKind =
|
|
116
|
+
| "socket"
|
|
117
|
+
| "eventpoll"
|
|
118
|
+
| "timerfd"
|
|
119
|
+
| "eventfd"
|
|
120
|
+
| "pipe"
|
|
121
|
+
| "file"
|
|
122
|
+
| "other";
|
|
123
|
+
|
|
124
|
+
export interface RuntimeDiagnosticsProcfs {
|
|
125
|
+
readonly clockTicksPerSecond: number;
|
|
126
|
+
/**
|
|
127
|
+
* Elapsed time between the two /proc/self scans. Slightly longer than
|
|
128
|
+
* `window.observedMs` because it encloses the scans themselves; thread
|
|
129
|
+
* `window.cores` is computed over this interval.
|
|
130
|
+
*/
|
|
131
|
+
readonly observedMs: number;
|
|
132
|
+
readonly threads: {
|
|
133
|
+
readonly total: number;
|
|
134
|
+
readonly byName: Readonly<Record<string, number>>;
|
|
135
|
+
/** Sorted by window cores descending, so the hottest thread is first. */
|
|
136
|
+
readonly items: readonly RuntimeDiagnosticsThread[];
|
|
137
|
+
};
|
|
138
|
+
readonly fileDescriptors: {
|
|
139
|
+
readonly total: number;
|
|
140
|
+
readonly byKind: Readonly<Record<RuntimeDiagnosticsFdKind, number>>;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface RuntimeDiagnosticsReport {
|
|
145
|
+
readonly schemaVersion: typeof RUNTIME_DIAGNOSTICS_SCHEMA_VERSION;
|
|
146
|
+
readonly provider: { readonly id: string; readonly version: string };
|
|
147
|
+
readonly sdkVersion: string;
|
|
148
|
+
readonly runtime: {
|
|
149
|
+
readonly bunVersion: string | null;
|
|
150
|
+
readonly nodeCompatVersion: string;
|
|
151
|
+
readonly platform: string;
|
|
152
|
+
readonly arch: string;
|
|
153
|
+
readonly pid: number;
|
|
154
|
+
};
|
|
155
|
+
readonly sampledAt: string;
|
|
156
|
+
readonly uptimeSeconds: number;
|
|
157
|
+
readonly window: { readonly requestedMs: number; readonly observedMs: number };
|
|
158
|
+
readonly cpu: RuntimeDiagnosticsCpu;
|
|
159
|
+
readonly memory: RuntimeDiagnosticsMemory;
|
|
160
|
+
readonly eventLoop: RuntimeDiagnosticsEventLoop;
|
|
161
|
+
readonly activeResources: RuntimeDiagnosticsActiveResources;
|
|
162
|
+
/** null off Linux or when `/proc/self` is unreadable. */
|
|
163
|
+
readonly procfs: RuntimeDiagnosticsProcfs | null;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface RuntimeDiagnosticsClock {
|
|
167
|
+
now(): number;
|
|
168
|
+
sleep(ms: number): Promise<void>;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export interface CollectRuntimeDiagnosticsInput {
|
|
172
|
+
readonly provider: { readonly id: string; readonly version: string };
|
|
173
|
+
/** Sampling window; clamped to [MIN, MAX]. */
|
|
174
|
+
readonly windowMs?: number;
|
|
175
|
+
/** `/proc/self` substitute for tests. */
|
|
176
|
+
readonly procfsRoot?: string;
|
|
177
|
+
readonly clock?: RuntimeDiagnosticsClock;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const defaultClock: RuntimeDiagnosticsClock = {
|
|
181
|
+
now: () => performance.now(),
|
|
182
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export function normalizeRuntimeDiagnosticsWindowMs(value: number | undefined): number {
|
|
186
|
+
if (value === undefined || !Number.isFinite(value)) return DEFAULT_RUNTIME_DIAGNOSTICS_WINDOW_MS;
|
|
187
|
+
return Math.min(
|
|
188
|
+
MAX_RUNTIME_DIAGNOSTICS_WINDOW_MS,
|
|
189
|
+
Math.max(MIN_RUNTIME_DIAGNOSTICS_WINDOW_MS, Math.trunc(value)),
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Parses the `windowMs` query value; anything unparsable falls back to the default. */
|
|
194
|
+
export function resolveRuntimeDiagnosticsWindowMs(raw: string | undefined | null): number {
|
|
195
|
+
if (raw === undefined || raw === null || raw.trim() === "") {
|
|
196
|
+
return DEFAULT_RUNTIME_DIAGNOSTICS_WINDOW_MS;
|
|
197
|
+
}
|
|
198
|
+
const parsed = Number.parseInt(raw, 10);
|
|
199
|
+
return normalizeRuntimeDiagnosticsWindowMs(Number.isNaN(parsed) ? undefined : parsed);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export async function collectRuntimeDiagnostics(
|
|
203
|
+
input: CollectRuntimeDiagnosticsInput,
|
|
204
|
+
): Promise<RuntimeDiagnosticsReport> {
|
|
205
|
+
const clock = input.clock ?? defaultClock;
|
|
206
|
+
const procfsRoot = input.procfsRoot ?? DEFAULT_PROCFS_SELF_ROOT;
|
|
207
|
+
const requestedMs = normalizeRuntimeDiagnosticsWindowMs(input.windowMs);
|
|
208
|
+
|
|
209
|
+
// Two nested brackets. The procfs scans are synchronous work on the main
|
|
210
|
+
// thread, so the process-level CPU bracket starts after the first scan and
|
|
211
|
+
// closes before the second one: the scans' own CPU never lands inside it.
|
|
212
|
+
// The thread bracket encloses the scans and divides their tick deltas by
|
|
213
|
+
// its own elapsed time, so the scan cost is attributed over the interval it
|
|
214
|
+
// actually spans instead of inflating a short window.
|
|
215
|
+
const threadsStartedAt = clock.now();
|
|
216
|
+
const threadsStart = sampleThreads(procfsRoot);
|
|
217
|
+
const cpuStart = process.cpuUsage();
|
|
218
|
+
const eventLoopStart = sampleEventLoopUtilization();
|
|
219
|
+
const startedAt = clock.now();
|
|
220
|
+
await clock.sleep(requestedMs);
|
|
221
|
+
const observedMs = Math.max(0, clock.now() - startedAt);
|
|
222
|
+
const cpuWindow = process.cpuUsage(cpuStart);
|
|
223
|
+
const eventLoopEnd = sampleEventLoopUtilization();
|
|
224
|
+
const threadsEnd = sampleThreads(procfsRoot);
|
|
225
|
+
const threadsObservedMs = Math.max(0, clock.now() - threadsStartedAt);
|
|
226
|
+
const fileDescriptors = sampleFileDescriptors(procfsRoot);
|
|
227
|
+
|
|
228
|
+
const cpuLifetime = process.cpuUsage();
|
|
229
|
+
const uptimeSeconds = process.uptime();
|
|
230
|
+
const sampledAt = new Date().toISOString();
|
|
231
|
+
const memory = process.memoryUsage();
|
|
232
|
+
const activeResources = sampleActiveResources();
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
schemaVersion: RUNTIME_DIAGNOSTICS_SCHEMA_VERSION,
|
|
236
|
+
provider: { id: input.provider.id, version: input.provider.version },
|
|
237
|
+
sdkVersion: SDK_VERSION,
|
|
238
|
+
runtime: {
|
|
239
|
+
bunVersion: process.versions.bun ?? null,
|
|
240
|
+
nodeCompatVersion: process.versions.node,
|
|
241
|
+
platform: process.platform,
|
|
242
|
+
arch: process.arch,
|
|
243
|
+
pid: process.pid,
|
|
244
|
+
},
|
|
245
|
+
sampledAt,
|
|
246
|
+
uptimeSeconds,
|
|
247
|
+
window: { requestedMs, observedMs },
|
|
248
|
+
cpu: {
|
|
249
|
+
lifetime: {
|
|
250
|
+
userMicros: cpuLifetime.user,
|
|
251
|
+
systemMicros: cpuLifetime.system,
|
|
252
|
+
averageCores: coresFromMicros(cpuLifetime.user + cpuLifetime.system, uptimeSeconds * 1000),
|
|
253
|
+
},
|
|
254
|
+
window: {
|
|
255
|
+
userMicros: cpuWindow.user,
|
|
256
|
+
systemMicros: cpuWindow.system,
|
|
257
|
+
userCores: coresFromMicros(cpuWindow.user, observedMs),
|
|
258
|
+
systemCores: coresFromMicros(cpuWindow.system, observedMs),
|
|
259
|
+
totalCores: coresFromMicros(cpuWindow.user + cpuWindow.system, observedMs),
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
memory: {
|
|
263
|
+
rss: memory.rss,
|
|
264
|
+
heapTotal: memory.heapTotal,
|
|
265
|
+
heapUsed: memory.heapUsed,
|
|
266
|
+
external: memory.external,
|
|
267
|
+
arrayBuffers: memory.arrayBuffers,
|
|
268
|
+
},
|
|
269
|
+
eventLoop: {
|
|
270
|
+
reported: eventLoopEnd.idle + eventLoopEnd.active > 0,
|
|
271
|
+
lifetime: eventLoopEnd,
|
|
272
|
+
window: eventLoopUtilizationDelta(eventLoopEnd, eventLoopStart),
|
|
273
|
+
},
|
|
274
|
+
activeResources,
|
|
275
|
+
procfs:
|
|
276
|
+
threadsEnd === null || fileDescriptors === null
|
|
277
|
+
? null
|
|
278
|
+
: {
|
|
279
|
+
clockTicksPerSecond: PROCFS_CLOCK_TICKS_PER_SECOND,
|
|
280
|
+
observedMs: threadsObservedMs,
|
|
281
|
+
threads: summarizeThreads(threadsStart, threadsEnd, threadsObservedMs),
|
|
282
|
+
fileDescriptors,
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function coresFromMicros(micros: number, elapsedMs: number): number {
|
|
288
|
+
if (!(elapsedMs > 0)) return 0;
|
|
289
|
+
return micros / 1000 / elapsedMs;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function sampleEventLoopUtilization(): RuntimeDiagnosticsEventLoopUtilization {
|
|
293
|
+
const eventLoopUtilization: unknown = performance.eventLoopUtilization;
|
|
294
|
+
if (typeof eventLoopUtilization !== "function") return { idle: 0, active: 0, utilization: 0 };
|
|
295
|
+
try {
|
|
296
|
+
const sample: unknown = (eventLoopUtilization as () => unknown).call(performance);
|
|
297
|
+
return {
|
|
298
|
+
idle: numberProperty(sample, "idle"),
|
|
299
|
+
active: numberProperty(sample, "active"),
|
|
300
|
+
utilization: numberProperty(sample, "utilization"),
|
|
301
|
+
};
|
|
302
|
+
} catch {
|
|
303
|
+
return { idle: 0, active: 0, utilization: 0 };
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function eventLoopUtilizationDelta(
|
|
308
|
+
end: RuntimeDiagnosticsEventLoopUtilization,
|
|
309
|
+
start: RuntimeDiagnosticsEventLoopUtilization,
|
|
310
|
+
): RuntimeDiagnosticsEventLoopUtilization {
|
|
311
|
+
const idle = Math.max(0, end.idle - start.idle);
|
|
312
|
+
const active = Math.max(0, end.active - start.active);
|
|
313
|
+
const total = idle + active;
|
|
314
|
+
return { idle, active, utilization: total > 0 ? active / total : 0 };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function sampleActiveResources(): RuntimeDiagnosticsActiveResources {
|
|
318
|
+
const getActiveResourcesInfo: unknown = process.getActiveResourcesInfo;
|
|
319
|
+
let types: string[] = [];
|
|
320
|
+
if (typeof getActiveResourcesInfo === "function") {
|
|
321
|
+
try {
|
|
322
|
+
const listed: unknown = (getActiveResourcesInfo as () => unknown).call(process);
|
|
323
|
+
if (Array.isArray(listed)) {
|
|
324
|
+
types = listed.filter((entry): entry is string => typeof entry === "string");
|
|
325
|
+
}
|
|
326
|
+
} catch {
|
|
327
|
+
types = [];
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const byType: Record<string, number> = {};
|
|
331
|
+
for (const type of types) byType[type] = (byType[type] ?? 0) + 1;
|
|
332
|
+
return { reported: types.length > 0, total: types.length, byType };
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function numberProperty(value: unknown, key: string): number {
|
|
336
|
+
if (value === null || typeof value !== "object") return 0;
|
|
337
|
+
const candidate: unknown = (value as Record<string, unknown>)[key];
|
|
338
|
+
return typeof candidate === "number" && Number.isFinite(candidate) ? candidate : 0;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
interface ThreadSample {
|
|
342
|
+
readonly tid: number;
|
|
343
|
+
readonly name: string;
|
|
344
|
+
readonly state: string;
|
|
345
|
+
readonly userTicks: number;
|
|
346
|
+
readonly systemTicks: number;
|
|
347
|
+
readonly voluntary: number;
|
|
348
|
+
readonly nonvoluntary: number;
|
|
349
|
+
readonly waitChannel: string | null;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function sampleThreads(root: string): Map<number, ThreadSample> | null {
|
|
353
|
+
let entries: string[];
|
|
354
|
+
try {
|
|
355
|
+
entries = readdirSync(join(root, "task"));
|
|
356
|
+
} catch {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
const samples = new Map<number, ThreadSample>();
|
|
360
|
+
for (const entry of entries) {
|
|
361
|
+
if (!/^\d+$/.test(entry)) continue;
|
|
362
|
+
const sample = sampleThread(join(root, "task", entry), Number.parseInt(entry, 10));
|
|
363
|
+
if (sample) samples.set(sample.tid, sample);
|
|
364
|
+
}
|
|
365
|
+
return samples;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function sampleThread(taskDir: string, tid: number): ThreadSample | null {
|
|
369
|
+
let stat: string;
|
|
370
|
+
try {
|
|
371
|
+
stat = readFileSync(join(taskDir, "stat"), "utf8");
|
|
372
|
+
} catch {
|
|
373
|
+
// The thread exited between the directory listing and this read.
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
const open = stat.indexOf("(");
|
|
377
|
+
const close = stat.lastIndexOf(")");
|
|
378
|
+
if (open < 0 || close < open) return null;
|
|
379
|
+
const fields = stat
|
|
380
|
+
.slice(close + 2)
|
|
381
|
+
.trimEnd()
|
|
382
|
+
.split(" ");
|
|
383
|
+
const userTicks = Number.parseInt(fields[11] ?? "", 10);
|
|
384
|
+
const systemTicks = Number.parseInt(fields[12] ?? "", 10);
|
|
385
|
+
if (!Number.isFinite(userTicks) || !Number.isFinite(systemTicks)) return null;
|
|
386
|
+
const switches = readContextSwitches(join(taskDir, "status"));
|
|
387
|
+
return {
|
|
388
|
+
tid,
|
|
389
|
+
name: stat.slice(open + 1, close),
|
|
390
|
+
state: fields[0] ?? "?",
|
|
391
|
+
userTicks,
|
|
392
|
+
systemTicks,
|
|
393
|
+
voluntary: switches.voluntary,
|
|
394
|
+
nonvoluntary: switches.nonvoluntary,
|
|
395
|
+
waitChannel: readWaitChannel(join(taskDir, "wchan")),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function readContextSwitches(statusPath: string): RuntimeDiagnosticsThreadContextSwitches {
|
|
400
|
+
let voluntary = 0;
|
|
401
|
+
let nonvoluntary = 0;
|
|
402
|
+
let status: string;
|
|
403
|
+
try {
|
|
404
|
+
status = readFileSync(statusPath, "utf8");
|
|
405
|
+
} catch {
|
|
406
|
+
return { voluntary, nonvoluntary };
|
|
407
|
+
}
|
|
408
|
+
for (const line of status.split("\n")) {
|
|
409
|
+
const separator = line.indexOf(":");
|
|
410
|
+
if (separator < 0) continue;
|
|
411
|
+
const key = line.slice(0, separator);
|
|
412
|
+
if (key !== "voluntary_ctxt_switches" && key !== "nonvoluntary_ctxt_switches") continue;
|
|
413
|
+
const parsed = Number.parseInt(line.slice(separator + 1).trim(), 10);
|
|
414
|
+
if (!Number.isFinite(parsed)) continue;
|
|
415
|
+
if (key === "voluntary_ctxt_switches") voluntary = parsed;
|
|
416
|
+
else nonvoluntary = parsed;
|
|
417
|
+
}
|
|
418
|
+
return { voluntary, nonvoluntary };
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function readWaitChannel(wchanPath: string): string | null {
|
|
422
|
+
try {
|
|
423
|
+
const value = readFileSync(wchanPath, "utf8").trim();
|
|
424
|
+
return value === "" ? null : value;
|
|
425
|
+
} catch {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function summarizeThreads(
|
|
431
|
+
start: Map<number, ThreadSample> | null,
|
|
432
|
+
end: Map<number, ThreadSample>,
|
|
433
|
+
observedMs: number,
|
|
434
|
+
): RuntimeDiagnosticsProcfs["threads"] {
|
|
435
|
+
const byName: Record<string, number> = {};
|
|
436
|
+
const items: RuntimeDiagnosticsThread[] = [];
|
|
437
|
+
for (const sample of end.values()) {
|
|
438
|
+
byName[sample.name] = (byName[sample.name] ?? 0) + 1;
|
|
439
|
+
const baseline = start?.get(sample.tid);
|
|
440
|
+
let window: RuntimeDiagnosticsThreadWindow | null = null;
|
|
441
|
+
if (baseline) {
|
|
442
|
+
const userTicks = Math.max(0, sample.userTicks - baseline.userTicks);
|
|
443
|
+
const systemTicks = Math.max(0, sample.systemTicks - baseline.systemTicks);
|
|
444
|
+
window = {
|
|
445
|
+
userTicks,
|
|
446
|
+
systemTicks,
|
|
447
|
+
cores: coresFromTicks(userTicks + systemTicks, observedMs),
|
|
448
|
+
contextSwitches: {
|
|
449
|
+
voluntary: Math.max(0, sample.voluntary - baseline.voluntary),
|
|
450
|
+
nonvoluntary: Math.max(0, sample.nonvoluntary - baseline.nonvoluntary),
|
|
451
|
+
},
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
items.push({
|
|
455
|
+
tid: sample.tid,
|
|
456
|
+
name: sample.name,
|
|
457
|
+
state: sample.state,
|
|
458
|
+
waitChannel: sample.waitChannel,
|
|
459
|
+
lifetime: { userTicks: sample.userTicks, systemTicks: sample.systemTicks },
|
|
460
|
+
window,
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
items.sort(compareThreads);
|
|
464
|
+
return { total: items.length, byName, items };
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function coresFromTicks(ticks: number, elapsedMs: number): number {
|
|
468
|
+
if (!(elapsedMs > 0)) return 0;
|
|
469
|
+
return ((ticks / PROCFS_CLOCK_TICKS_PER_SECOND) * 1000) / elapsedMs;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function compareThreads(left: RuntimeDiagnosticsThread, right: RuntimeDiagnosticsThread): number {
|
|
473
|
+
const leftCores = left.window?.cores ?? -1;
|
|
474
|
+
const rightCores = right.window?.cores ?? -1;
|
|
475
|
+
if (leftCores !== rightCores) return rightCores - leftCores;
|
|
476
|
+
const leftLifetime = left.lifetime.userTicks + left.lifetime.systemTicks;
|
|
477
|
+
const rightLifetime = right.lifetime.userTicks + right.lifetime.systemTicks;
|
|
478
|
+
if (leftLifetime !== rightLifetime) return rightLifetime - leftLifetime;
|
|
479
|
+
return left.tid - right.tid;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function sampleFileDescriptors(root: string): RuntimeDiagnosticsProcfs["fileDescriptors"] | null {
|
|
483
|
+
let entries: string[];
|
|
484
|
+
try {
|
|
485
|
+
entries = readdirSync(join(root, "fd"));
|
|
486
|
+
} catch {
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
const byKind: Record<RuntimeDiagnosticsFdKind, number> = {
|
|
490
|
+
socket: 0,
|
|
491
|
+
eventpoll: 0,
|
|
492
|
+
timerfd: 0,
|
|
493
|
+
eventfd: 0,
|
|
494
|
+
pipe: 0,
|
|
495
|
+
file: 0,
|
|
496
|
+
other: 0,
|
|
497
|
+
};
|
|
498
|
+
let total = 0;
|
|
499
|
+
for (const entry of entries) {
|
|
500
|
+
let target: string;
|
|
501
|
+
try {
|
|
502
|
+
target = readlinkSync(join(root, "fd", entry));
|
|
503
|
+
} catch {
|
|
504
|
+
// Closed between the listing and the readlink (the listing's own
|
|
505
|
+
// directory handle always lands here).
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
byKind[classifyFileDescriptor(target)] += 1;
|
|
509
|
+
total += 1;
|
|
510
|
+
}
|
|
511
|
+
return { total, byKind };
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function classifyFileDescriptor(target: string): RuntimeDiagnosticsFdKind {
|
|
515
|
+
if (target.startsWith("socket:")) return "socket";
|
|
516
|
+
if (target === "anon_inode:[eventpoll]") return "eventpoll";
|
|
517
|
+
if (target === "anon_inode:[timerfd]") return "timerfd";
|
|
518
|
+
if (target === "anon_inode:[eventfd]") return "eventfd";
|
|
519
|
+
if (target.startsWith("pipe:")) return "pipe";
|
|
520
|
+
if (target.startsWith("/")) return "file";
|
|
521
|
+
return "other";
|
|
522
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
/** Published @apifuse/provider-sdk version, read from the package manifest; "unknown" when unreadable. */
|
|
4
|
+
export function resolveSdkVersion(): string {
|
|
5
|
+
try {
|
|
6
|
+
const packageJsonUrl = new URL("../../package.json", import.meta.url);
|
|
7
|
+
const parsed: unknown = JSON.parse(readFileSync(packageJsonUrl, "utf8"));
|
|
8
|
+
if (
|
|
9
|
+
parsed &&
|
|
10
|
+
typeof parsed === "object" &&
|
|
11
|
+
"version" in parsed &&
|
|
12
|
+
typeof (parsed as { version: unknown }).version === "string"
|
|
13
|
+
) {
|
|
14
|
+
return (parsed as { version: string }).version;
|
|
15
|
+
}
|
|
16
|
+
} catch {
|
|
17
|
+
// fall through to unknown
|
|
18
|
+
}
|
|
19
|
+
return "unknown";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const SDK_VERSION = resolveSdkVersion();
|
|
@@ -1,46 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Relative
|
|
3
|
-
*
|
|
4
|
-
* so
|
|
2
|
+
* Relative date-token resolution for health-check case inputs and fixture
|
|
3
|
+
* requests. The calendar defaults to KST; callers that need UTC must opt in
|
|
4
|
+
* explicitly so UTC and KST do not silently disagree from 15:00–23:59 UTC.
|
|
5
5
|
*
|
|
6
|
-
* Supported token: `+<days>d` or `+<days>d:YYYYMMDD` (1..365 days ahead
|
|
6
|
+
* Supported token: `+<days>d` or `+<days>d:YYYYMMDD` (1..365 days ahead).
|
|
7
7
|
*/
|
|
8
|
-
const
|
|
8
|
+
const RELATIVE_DATE_TOKEN = /^\+(\d{1,3})d(?::(YYYYMMDD))?$/i;
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
export type InputDateTokenCalendar = "KST" | "UTC";
|
|
11
|
+
|
|
12
|
+
function dateFromDaysAhead(
|
|
11
13
|
daysAhead: number,
|
|
12
14
|
now = new Date(),
|
|
13
15
|
format: "YYYY-MM-DD" | "YYYYMMDD" = "YYYY-MM-DD",
|
|
16
|
+
calendar: InputDateTokenCalendar = "KST",
|
|
14
17
|
): string {
|
|
15
|
-
const
|
|
18
|
+
const calendarNow = new Date(now.getTime() + (calendar === "KST" ? 9 * 60 * 60 * 1000 : 0));
|
|
16
19
|
const date = new Date(
|
|
17
|
-
Date.UTC(
|
|
20
|
+
Date.UTC(
|
|
21
|
+
calendarNow.getUTCFullYear(),
|
|
22
|
+
calendarNow.getUTCMonth(),
|
|
23
|
+
calendarNow.getUTCDate() + daysAhead,
|
|
24
|
+
),
|
|
18
25
|
);
|
|
19
26
|
const isoDate = date.toISOString().slice(0, 10);
|
|
20
27
|
return format === "YYYYMMDD" ? isoDate.replace(/-/g, "") : isoDate;
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
export function resolveHealthCheckInputDateTokens(
|
|
30
|
+
export function resolveHealthCheckInputDateTokens(
|
|
31
|
+
value: unknown,
|
|
32
|
+
now = new Date(),
|
|
33
|
+
calendar: InputDateTokenCalendar = "KST",
|
|
34
|
+
): unknown {
|
|
24
35
|
if (typeof value === "string") {
|
|
25
|
-
const relative = value.match(
|
|
36
|
+
const relative = value.match(RELATIVE_DATE_TOKEN);
|
|
26
37
|
if (!relative) return value;
|
|
27
38
|
const daysAhead = Number(relative[1]);
|
|
28
39
|
if (!Number.isInteger(daysAhead) || daysAhead < 1 || daysAhead > 365) {
|
|
29
40
|
return value;
|
|
30
41
|
}
|
|
31
42
|
const format = relative[2]?.toUpperCase() === "YYYYMMDD" ? "YYYYMMDD" : "YYYY-MM-DD";
|
|
32
|
-
return
|
|
43
|
+
return dateFromDaysAhead(daysAhead, now, format, calendar);
|
|
33
44
|
}
|
|
34
45
|
if (Array.isArray(value)) {
|
|
35
|
-
|
|
46
|
+
const resolved = value.map((entry) => resolveHealthCheckInputDateTokens(entry, now, calendar));
|
|
47
|
+
return resolved.some((entry, index) => entry !== value[index]) ? resolved : value;
|
|
36
48
|
}
|
|
37
49
|
if (value && typeof value === "object") {
|
|
38
|
-
|
|
50
|
+
const resolved = Object.fromEntries(
|
|
39
51
|
Object.entries(value).map(([key, entry]) => [
|
|
40
52
|
key,
|
|
41
|
-
resolveHealthCheckInputDateTokens(entry, now),
|
|
53
|
+
resolveHealthCheckInputDateTokens(entry, now, calendar),
|
|
42
54
|
]),
|
|
43
55
|
);
|
|
56
|
+
return Object.entries(resolved).some(([key, entry]) => entry !== Reflect.get(value, key))
|
|
57
|
+
? resolved
|
|
58
|
+
: value;
|
|
44
59
|
}
|
|
45
60
|
return value;
|
|
46
61
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ProviderDefinition } from "../types.js";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from "./
|
|
3
|
+
collectDiagnosticSensitiveValues,
|
|
4
|
+
SELF_TEST_SENSITIVE_SOURCE_KINDS,
|
|
5
|
+
} from "./sensitive-values.js";
|
|
6
6
|
|
|
7
7
|
export const SELF_TEST_REDACTED_PLACEHOLDER = "[REDACTED]";
|
|
8
8
|
|
|
@@ -31,39 +31,12 @@ export function collectSelfTestSensitiveValues(
|
|
|
31
31
|
credentialInputs?: Readonly<Record<string, string>>;
|
|
32
32
|
} = {},
|
|
33
33
|
): string[] {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
envNames.add(secret.name);
|
|
41
|
-
}
|
|
42
|
-
const healthProbe = provider.healthProbe ?? provider.healthMonitor;
|
|
43
|
-
for (const name of healthProbe?.requiredSecrets ?? []) {
|
|
44
|
-
envNames.add(name);
|
|
45
|
-
}
|
|
46
|
-
for (const name of Object.values(healthProbe?.credentialInputs ?? {})) {
|
|
47
|
-
envNames.add(name);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const values = new Set<string>();
|
|
51
|
-
for (const name of envNames) {
|
|
52
|
-
const value = env[name];
|
|
53
|
-
if (typeof value === "string" && value.length >= MIN_SENSITIVE_VALUE_LENGTH) {
|
|
54
|
-
values.add(value);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
for (const value of Object.values(options.credentialInputs ?? {})) {
|
|
58
|
-
if (value.length >= MIN_SENSITIVE_VALUE_LENGTH) {
|
|
59
|
-
values.add(value);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return [...values];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function escapeRegExp(value: string): string {
|
|
66
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
34
|
+
return collectDiagnosticSensitiveValues(provider, {
|
|
35
|
+
...options,
|
|
36
|
+
sourceKinds: SELF_TEST_SENSITIVE_SOURCE_KINDS,
|
|
37
|
+
minimumLength: MIN_SENSITIVE_VALUE_LENGTH,
|
|
38
|
+
includeResolvedEnvVariants: false,
|
|
39
|
+
});
|
|
67
40
|
}
|
|
68
41
|
|
|
69
42
|
/**
|
|
@@ -79,10 +52,7 @@ export function redactSelfTestText(
|
|
|
79
52
|
let redacted = text;
|
|
80
53
|
for (const value of sensitiveValues) {
|
|
81
54
|
if (value.length < MIN_SENSITIVE_VALUE_LENGTH) continue;
|
|
82
|
-
redacted = redacted.
|
|
83
|
-
new RegExp(escapeRegExp(value), "g"),
|
|
84
|
-
SELF_TEST_REDACTED_PLACEHOLDER,
|
|
85
|
-
);
|
|
55
|
+
redacted = redacted.replaceAll(value, SELF_TEST_REDACTED_PLACEHOLDER);
|
|
86
56
|
}
|
|
87
57
|
for (const pattern of HEADER_SHAPED_SECRETS) {
|
|
88
58
|
redacted = redacted.replace(
|