@apifuse/provider-sdk 2.2.0-beta.5 → 2.2.0-beta.51
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 +537 -33
- package/CHANGELOG.md +205 -1
- package/README.md +83 -22
- package/SUBMISSION.md +2 -2
- package/bin/apifuse-check.ts +165 -11
- package/bin/apifuse-dev.ts +57 -13
- package/bin/apifuse-migrate-operation-declaration.ts +55 -0
- package/bin/apifuse-migrate-shape.ts +202 -0
- package/bin/apifuse-pack-check.ts +22 -2
- package/bin/apifuse-pack-smoke.ts +57 -2
- package/bin/apifuse-pack-types.ts +357 -38
- package/bin/apifuse-perf.ts +14 -13
- package/bin/apifuse-record.ts +709 -72
- package/bin/apifuse-submit-check.ts +2344 -324
- package/bin/apifuse-sync-assets.ts +117 -0
- 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 +27 -0
- package/dist/cli/create.d.ts +4 -1
- package/dist/cli/create.js +42 -37
- package/dist/cli/migrate-operation-declaration.d.ts +59 -0
- package/dist/cli/migrate-operation-declaration.js +1249 -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 +52 -0
- package/dist/cli/migrate-provider-shape.js +578 -0
- package/dist/cli/prompt-assets.d.ts +80 -0
- package/dist/cli/prompt-assets.js +743 -0
- package/dist/cli/templates/provider/AGENTS.md.tpl +17 -8
- package/dist/cli/templates/provider/Dockerfile.tpl +1 -1
- package/dist/cli/templates/provider/README.md.tpl +5 -5
- 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 +179 -16
- package/dist/config/loader.js +435 -127
- 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 +33 -0
- package/dist/declaration-validation.js +266 -0
- package/dist/define.d.ts +66 -29
- package/dist/define.js +778 -69
- package/dist/dev.d.ts +3 -0
- package/dist/dev.js +1 -1
- package/dist/engine.d.ts +78 -0
- package/dist/engine.js +133 -0
- package/dist/error-observability.d.ts +7 -0
- package/dist/error-observability.js +61 -0
- package/dist/error-resolution.d.ts +4 -0
- package/dist/error-resolution.js +122 -0
- package/dist/errors.d.ts +33 -0
- package/dist/errors.js +40 -0
- package/dist/fixture-sanitization.d.ts +28 -0
- package/dist/fixture-sanitization.js +227 -0
- package/dist/health-scenario.d.ts +1842 -0
- package/dist/health-scenario.js +624 -0
- package/dist/index.d.ts +21 -10
- package/dist/index.js +12 -7
- package/dist/lint.d.ts +23 -11
- package/dist/lint.js +572 -69
- 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 +10 -2
- package/dist/provider.js +4 -1
- package/dist/runtime/auth-flow.d.ts +5 -1
- package/dist/runtime/auth-flow.js +6 -0
- package/dist/runtime/browser.d.ts +1 -0
- package/dist/runtime/browser.js +492 -49
- package/dist/runtime/cache.d.ts +1 -0
- package/dist/runtime/cache.js +169 -15
- package/dist/runtime/choice-wordlist.d.ts +9 -0
- package/dist/runtime/choice-wordlist.js +138 -0
- package/dist/runtime/choice.d.ts +13 -1
- package/dist/runtime/choice.js +490 -102
- package/dist/runtime/chrome149-header-order.d.ts +58 -0
- package/dist/runtime/chrome149-header-order.js +289 -0
- package/dist/runtime/env.js +12 -0
- package/dist/runtime/executor.d.ts +3 -2
- package/dist/runtime/executor.js +26 -25
- package/dist/runtime/http.d.ts +1 -0
- package/dist/runtime/http.js +515 -53
- package/dist/runtime/insights.js +2 -2
- package/dist/runtime/instrumentation.d.ts +2 -2
- package/dist/runtime/instrumentation.js +366 -8
- 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 +96 -0
- package/dist/runtime/native-network.js +1232 -0
- package/dist/runtime/ocr.d.ts +29 -0
- package/dist/runtime/ocr.js +440 -0
- package/dist/runtime/otlp.d.ts +71 -2
- package/dist/runtime/otlp.js +397 -16
- package/dist/runtime/proxy-errors.js +6 -2
- package/dist/runtime/proxy-nodemaven.d.ts +56 -0
- package/dist/runtime/proxy-nodemaven.js +146 -0
- package/dist/runtime/proxy-telemetry.d.ts +80 -1
- package/dist/runtime/proxy-telemetry.js +154 -47
- package/dist/runtime/redirects.d.ts +29 -0
- package/dist/runtime/redirects.js +36 -0
- package/dist/runtime/redis.d.ts +1 -1
- package/dist/runtime/redis.js +4 -2
- package/dist/runtime/request-options.d.ts +68 -1
- package/dist/runtime/request-options.js +548 -0
- package/dist/runtime/resolver-config.d.ts +6 -0
- package/dist/runtime/resolver-config.js +6 -0
- package/dist/runtime/resolver-public.d.ts +1 -0
- package/dist/runtime/resolver-public.js +1 -0
- package/dist/runtime/resolver-shared.d.ts +14 -0
- package/dist/runtime/resolver-shared.js +12 -0
- package/dist/runtime/resolver-vendors/bindings.d.ts +48 -0
- package/dist/runtime/resolver-vendors/bindings.js +40 -0
- package/dist/runtime/resolver-vendors/browser.d.ts +22 -0
- package/dist/runtime/resolver-vendors/browser.js +377 -0
- package/dist/runtime/resolver-vendors/capsolver.d.ts +22 -0
- package/dist/runtime/resolver-vendors/capsolver.js +531 -0
- package/dist/runtime/resolver-vendors/hosts.d.ts +2 -0
- package/dist/runtime/resolver-vendors/hosts.js +33 -0
- package/dist/runtime/resolver-vendors/twocaptcha.d.ts +24 -0
- package/dist/runtime/resolver-vendors/twocaptcha.js +408 -0
- package/dist/runtime/resolver-vendors/types.d.ts +94 -0
- package/dist/runtime/resolver-vendors/types.js +96 -0
- package/dist/runtime/resolver.d.ts +72 -0
- package/dist/runtime/resolver.js +771 -0
- package/dist/runtime/secrets.d.ts +27 -0
- package/dist/runtime/secrets.js +51 -0
- package/dist/runtime/state.d.ts +3 -0
- package/dist/runtime/state.js +277 -71
- package/dist/runtime/stealth-cookies.d.ts +20 -0
- package/dist/runtime/stealth-cookies.js +111 -0
- package/dist/runtime/stealth.d.ts +41 -5
- package/dist/runtime/stealth.js +997 -291
- package/dist/runtime/stt.js +1 -12
- 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 +5 -0
- package/dist/runtime/trace.js +43 -10
- 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/index.d.ts +5 -2
- package/dist/server/index.js +2 -2
- 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.d.ts +14 -3
- package/dist/server/self-test.js +129 -58
- package/dist/server/serve-implementation.d.ts +230 -0
- package/dist/server/serve-implementation.js +2265 -0
- package/dist/server/serve.d.ts +1 -70
- package/dist/server/serve.js +1 -1131
- package/dist/server/trace-output.d.ts +6 -0
- package/dist/server/trace-output.js +79 -0
- package/dist/server/types.d.ts +30 -5
- package/dist/server/types.js +13 -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 +215 -0
- package/dist/stateful/stateful-provider-runtime-context.d.ts +32 -0
- package/dist/stateful/stateful-provider-runtime-context.js +60 -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 +9 -4
- package/dist/stealth/profiles.js +160 -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 +489 -21
- package/dist/trace-sanitization.d.ts +5 -0
- package/dist/trace-sanitization.js +45 -0
- package/dist/types.d.ts +673 -131
- package/dist/types.js +1 -0
- package/package.json +45 -5
- package/src/auth-turn/index.ts +1 -1
- package/src/auth.ts +118 -0
- package/src/ceremonies/index.ts +189 -46
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +6 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +3 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +10 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +8 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +15 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +9 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +5 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +24 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +16 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +3 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +31 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +11 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +11 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +11 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +21 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +11 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +14 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +7 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +6 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +7 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +6 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +7 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +7 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +15 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +4 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +12 -0
- package/src/cli/commands.ts +33 -0
- package/src/cli/create.ts +50 -37
- package/src/cli/migrate-operation-declaration.ts +1751 -0
- package/src/cli/migrate-operation-shape.ts +184 -0
- package/src/cli/migrate-provider-shape.ts +772 -0
- package/src/cli/prompt-assets.ts +865 -0
- package/src/cli/templates/provider/AGENTS.md.tpl +17 -8
- package/src/cli/templates/provider/Dockerfile.tpl +1 -1
- package/src/cli/templates/provider/README.md.tpl +5 -5
- 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 +690 -163
- 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 +330 -0
- package/src/define.ts +1048 -131
- package/src/dev.ts +4 -1
- package/src/engine.ts +279 -0
- package/src/error-observability.ts +64 -0
- package/src/error-resolution.ts +127 -0
- package/src/errors.ts +68 -0
- package/src/fixture-sanitization.ts +264 -0
- package/src/health-scenario.ts +875 -0
- package/src/index.ts +220 -13
- package/src/lint.ts +698 -90
- 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 +161 -3
- package/src/runtime/auth-flow.ts +12 -0
- package/src/runtime/browser.ts +661 -63
- package/src/runtime/cache.ts +189 -14
- package/src/runtime/choice-wordlist.ts +145 -0
- package/src/runtime/choice.ts +631 -120
- package/src/runtime/chrome149-header-order.ts +330 -0
- package/src/runtime/env.ts +13 -0
- package/src/runtime/executor.ts +43 -31
- package/src/runtime/http.ts +641 -61
- package/src/runtime/insights.ts +2 -2
- package/src/runtime/instrumentation.ts +520 -15
- package/src/runtime/native-network-errors.ts +99 -0
- package/src/runtime/native-network.ts +1605 -0
- package/src/runtime/ocr.ts +523 -0
- package/src/runtime/otlp.ts +467 -21
- package/src/runtime/proxy-errors.ts +12 -4
- package/src/runtime/proxy-nodemaven.ts +221 -0
- package/src/runtime/proxy-telemetry.ts +244 -75
- package/src/runtime/redirects.ts +66 -0
- package/src/runtime/redis.ts +7 -2
- package/src/runtime/request-options.ts +680 -1
- package/src/runtime/resolver-config.ts +6 -0
- package/src/runtime/resolver-public.ts +23 -0
- package/src/runtime/resolver-shared.ts +33 -0
- package/src/runtime/resolver-vendors/bindings.ts +56 -0
- package/src/runtime/resolver-vendors/browser.ts +533 -0
- package/src/runtime/resolver-vendors/capsolver.ts +707 -0
- package/src/runtime/resolver-vendors/hosts.ts +38 -0
- package/src/runtime/resolver-vendors/twocaptcha.ts +540 -0
- package/src/runtime/resolver-vendors/types.ts +212 -0
- package/src/runtime/resolver.ts +1157 -0
- package/src/runtime/secrets.ts +64 -0
- package/src/runtime/state.ts +394 -77
- package/src/runtime/stealth-cookies.ts +132 -0
- package/src/runtime/stealth.ts +1280 -336
- package/src/runtime/stt.ts +1 -19
- package/src/runtime/timeout.ts +18 -0
- package/src/runtime/trace-config.ts +78 -0
- package/src/runtime/trace.ts +57 -17
- package/src/serve.ts +6 -1
- package/src/server/error-observability.ts +1 -0
- package/src/server/index.ts +34 -2
- package/src/server/self-test-input-tokens.ts +29 -14
- package/src/server/self-test.ts +191 -68
- package/src/server/serve-implementation.ts +3378 -0
- package/src/server/serve.ts +1 -1632
- package/src/server/trace-output.ts +129 -0
- package/src/server/types.ts +13 -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 +287 -0
- package/src/stateful/stateful-provider-runtime-context.ts +92 -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 +202 -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 +658 -15
- package/src/trace-sanitization.ts +63 -0
- package/src/types.ts +788 -174
- package/dist/cli/templates/provider/CLAUDE.md.tpl +0 -1
- package/src/cli/templates/provider/CLAUDE.md.tpl +0 -1
- /package/dist/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
package/src/server/self-test.ts
CHANGED
|
@@ -77,11 +77,22 @@ export interface SelfTestResponse {
|
|
|
77
77
|
results: SelfTestCaseResult[];
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
export interface SelfTestCancellationLogEvent {
|
|
81
|
+
level: "info";
|
|
82
|
+
event: "self_test_run_cancelled";
|
|
83
|
+
providerId: string;
|
|
84
|
+
requestId: string;
|
|
85
|
+
operationId: string;
|
|
86
|
+
caseName: string;
|
|
87
|
+
reason: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
80
90
|
export type SelfTestOperationInvoke = (args: {
|
|
81
91
|
operationId: string;
|
|
82
92
|
input: unknown;
|
|
83
93
|
connection?: OperationConnection;
|
|
84
94
|
requestId: string;
|
|
95
|
+
signal?: AbortSignal;
|
|
85
96
|
}) => Promise<{
|
|
86
97
|
status: number;
|
|
87
98
|
data: unknown;
|
|
@@ -106,6 +117,7 @@ export type SelfTestAuthFlowInvoke = (args: {
|
|
|
106
117
|
externalRef?: string;
|
|
107
118
|
input?: Record<string, unknown>;
|
|
108
119
|
context?: Record<string, unknown>;
|
|
120
|
+
signal?: AbortSignal;
|
|
109
121
|
}) => Promise<{
|
|
110
122
|
status: number;
|
|
111
123
|
body: unknown;
|
|
@@ -165,6 +177,8 @@ export interface SelfTestAppOptions {
|
|
|
165
177
|
requestBudgetMs?: number;
|
|
166
178
|
/** Env override for secret collection + budget resolution (tests). */
|
|
167
179
|
env?: Readonly<Record<string, string | undefined>>;
|
|
180
|
+
/** Structured server logger; defaults to the same JSON console shape as the provider server. */
|
|
181
|
+
logger?: (event: SelfTestCancellationLogEvent) => void;
|
|
168
182
|
}
|
|
169
183
|
|
|
170
184
|
function resolveSdkVersion(): string {
|
|
@@ -231,33 +245,35 @@ export function computeSelfTestPlanDigest(provider: ProviderDefinition): string
|
|
|
231
245
|
|
|
232
246
|
/**
|
|
233
247
|
* Fail-closed read-only classification: an operation may self-test only when
|
|
234
|
-
* its
|
|
235
|
-
* toolRouter.riskClass "read") and nothing marks it side-effecting. Unclassified
|
|
236
|
-
* operations are refused so the endpoint cannot become a mutation oracle.
|
|
248
|
+
* its authored safety source of truth classifies it as read-only.
|
|
237
249
|
*/
|
|
238
250
|
export function isSelfTestReadOnlyOperation(operation: OperationDefinition): boolean {
|
|
239
|
-
|
|
240
|
-
if (annotations?.readOnly === false) return false;
|
|
241
|
-
if (annotations?.destructive === true) return false;
|
|
242
|
-
const riskClass = operation.toolRouter?.riskClass;
|
|
243
|
-
if (riskClass !== undefined && riskClass !== "read") return false;
|
|
244
|
-
return annotations?.readOnly === true || riskClass === "read";
|
|
251
|
+
return operation.riskClass === "read";
|
|
245
252
|
}
|
|
246
253
|
|
|
247
254
|
/** Binds the self-test executor to a tenant app's /v1 pipeline in-process. */
|
|
248
255
|
export function createSelfTestInvoke(app: {
|
|
249
256
|
request: (input: string, requestInit?: RequestInit) => Response | Promise<Response>;
|
|
250
257
|
}): SelfTestOperationInvoke {
|
|
251
|
-
return async ({ operationId, input, connection, requestId }) => {
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
258
|
+
return async ({ operationId, input, connection, requestId, signal }) => {
|
|
259
|
+
const responsePromise = Promise.resolve(
|
|
260
|
+
app.request(`/v1/${encodeURIComponent(operationId)}`, {
|
|
261
|
+
method: "POST",
|
|
262
|
+
headers: { "content-type": "application/json" },
|
|
263
|
+
body: JSON.stringify({
|
|
264
|
+
requestId,
|
|
265
|
+
input: input ?? {},
|
|
266
|
+
...(connection ? { connection } : {}),
|
|
267
|
+
}),
|
|
268
|
+
...(signal ? { signal } : {}),
|
|
259
269
|
}),
|
|
260
|
-
|
|
270
|
+
);
|
|
271
|
+
const response = await responsePromise;
|
|
272
|
+
if (signal?.aborted) {
|
|
273
|
+
await cancelSelfTestResponse(response);
|
|
274
|
+
signal.throwIfAborted();
|
|
275
|
+
}
|
|
276
|
+
// An abort after body consumption starts may let response.text() finish.
|
|
261
277
|
const text = await response.text();
|
|
262
278
|
let body: unknown = text;
|
|
263
279
|
try {
|
|
@@ -277,11 +293,58 @@ export function createSelfTestInvoke(app: {
|
|
|
277
293
|
};
|
|
278
294
|
}
|
|
279
295
|
|
|
296
|
+
async function cancelSelfTestResponse(response: Response): Promise<void> {
|
|
297
|
+
await response.body?.cancel().catch(() => undefined);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function selfTestAbortReason(reason: unknown, sensitiveValues: readonly string[]): string {
|
|
301
|
+
const text =
|
|
302
|
+
reason instanceof Error
|
|
303
|
+
? reason.message || reason.name
|
|
304
|
+
: reason === undefined
|
|
305
|
+
? "aborted"
|
|
306
|
+
: String(reason);
|
|
307
|
+
return redactSelfTestText(text, sensitiveValues);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function logSelfTestCancellation(
|
|
311
|
+
provider: ProviderDefinition,
|
|
312
|
+
options: SelfTestAppOptions,
|
|
313
|
+
requestId: string,
|
|
314
|
+
selected: SelectedCase,
|
|
315
|
+
signal: AbortSignal,
|
|
316
|
+
sensitiveValues: readonly string[],
|
|
317
|
+
): void {
|
|
318
|
+
const event: SelfTestCancellationLogEvent = {
|
|
319
|
+
level: "info",
|
|
320
|
+
event: "self_test_run_cancelled",
|
|
321
|
+
providerId: provider.id,
|
|
322
|
+
requestId,
|
|
323
|
+
operationId: selected.operationId,
|
|
324
|
+
caseName: selected.healthCase.name,
|
|
325
|
+
reason: selfTestAbortReason(signal.reason, sensitiveValues),
|
|
326
|
+
};
|
|
327
|
+
if (options.logger) {
|
|
328
|
+
options.logger(event);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
console.log(JSON.stringify(event));
|
|
332
|
+
}
|
|
333
|
+
|
|
280
334
|
/** Binds the self-test auth-flow driver to a tenant app's /auth pipeline in-process. */
|
|
281
335
|
export function createSelfTestAuthFlowInvoke(app: {
|
|
282
336
|
request: (input: string, requestInit?: RequestInit) => Response | Promise<Response>;
|
|
283
337
|
}): SelfTestAuthFlowInvoke {
|
|
284
|
-
return async ({
|
|
338
|
+
return async ({
|
|
339
|
+
route,
|
|
340
|
+
requestId,
|
|
341
|
+
flowId,
|
|
342
|
+
connectionId,
|
|
343
|
+
externalRef,
|
|
344
|
+
input,
|
|
345
|
+
context,
|
|
346
|
+
signal,
|
|
347
|
+
}) => {
|
|
285
348
|
const response = await app.request(`/auth/${route}`, {
|
|
286
349
|
method: "POST",
|
|
287
350
|
headers: { "content-type": "application/json" },
|
|
@@ -293,6 +356,7 @@ export function createSelfTestAuthFlowInvoke(app: {
|
|
|
293
356
|
...(input ? { input } : {}),
|
|
294
357
|
...(context ? { context } : {}),
|
|
295
358
|
}),
|
|
359
|
+
...(signal ? { signal } : {}),
|
|
296
360
|
});
|
|
297
361
|
const text = await response.text();
|
|
298
362
|
let body: unknown = text;
|
|
@@ -312,17 +376,32 @@ class SelfTestCaseTimeoutError extends Error {
|
|
|
312
376
|
}
|
|
313
377
|
}
|
|
314
378
|
|
|
315
|
-
async function withCaseTimeout<T>(
|
|
379
|
+
async function withCaseTimeout<T>(
|
|
380
|
+
run: () => Promise<T>,
|
|
381
|
+
timeoutMs: number,
|
|
382
|
+
controller: AbortController,
|
|
383
|
+
): Promise<T> {
|
|
316
384
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
385
|
+
let onAbort: (() => void) | undefined;
|
|
317
386
|
try {
|
|
318
387
|
return await Promise.race([
|
|
319
388
|
run(),
|
|
320
389
|
new Promise<never>((_, reject) => {
|
|
321
|
-
timer = setTimeout(() =>
|
|
390
|
+
timer = setTimeout(() => {
|
|
391
|
+
const error = new SelfTestCaseTimeoutError(timeoutMs);
|
|
392
|
+
controller.abort(error);
|
|
393
|
+
reject(error);
|
|
394
|
+
}, timeoutMs);
|
|
395
|
+
}),
|
|
396
|
+
new Promise<never>((_, reject) => {
|
|
397
|
+
onAbort = () => reject(controller.signal.reason);
|
|
398
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
399
|
+
if (controller.signal.aborted) onAbort();
|
|
322
400
|
}),
|
|
323
401
|
]);
|
|
324
402
|
} finally {
|
|
325
403
|
if (timer !== undefined) clearTimeout(timer);
|
|
404
|
+
if (onAbort) controller.signal.removeEventListener("abort", onAbort);
|
|
326
405
|
}
|
|
327
406
|
}
|
|
328
407
|
|
|
@@ -595,6 +674,7 @@ async function materializeFlowCredential(
|
|
|
595
674
|
isAbandoned?: () => boolean;
|
|
596
675
|
connectionId?: string;
|
|
597
676
|
externalRef?: string;
|
|
677
|
+
signal?: AbortSignal;
|
|
598
678
|
} = {},
|
|
599
679
|
): Promise<
|
|
600
680
|
| { credential: Record<string, string> }
|
|
@@ -621,6 +701,7 @@ async function materializeFlowCredential(
|
|
|
621
701
|
flowId,
|
|
622
702
|
...(options.connectionId ? { connectionId: options.connectionId } : {}),
|
|
623
703
|
...(options.externalRef ? { externalRef: options.externalRef } : {}),
|
|
704
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
624
705
|
}),
|
|
625
706
|
);
|
|
626
707
|
if (!started.ok) {
|
|
@@ -696,6 +777,7 @@ async function materializeFlowCredential(
|
|
|
696
777
|
...(options.externalRef ? { externalRef: options.externalRef } : {}),
|
|
697
778
|
input: submitInputs,
|
|
698
779
|
...(Object.keys(flowContext).length > 0 ? { context: flowContext } : {}),
|
|
780
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
699
781
|
}),
|
|
700
782
|
);
|
|
701
783
|
if (!continued.ok) {
|
|
@@ -756,7 +838,7 @@ async function resolveSelfTestConnection(
|
|
|
756
838
|
execution: SelfTestExecutionContext,
|
|
757
839
|
operationId: string,
|
|
758
840
|
suite: AnyHealthCheckSuite,
|
|
759
|
-
options: { forceLogin?: boolean; isAbandoned?: () => boolean } = {},
|
|
841
|
+
options: { forceLogin?: boolean; isAbandoned?: () => boolean; signal?: AbortSignal } = {},
|
|
760
842
|
): Promise<SelfTestConnectionResolution> {
|
|
761
843
|
if (!suite.requiresConnection) return { kind: "connection" };
|
|
762
844
|
const inputs = execution.credentials ?? {};
|
|
@@ -861,6 +943,7 @@ async function resolveSelfTestConnection(
|
|
|
861
943
|
...(options.isAbandoned !== undefined ? { isAbandoned: options.isAbandoned } : {}),
|
|
862
944
|
connectionId,
|
|
863
945
|
externalRef: `${execution.provider.id}-${operationId}-self-test`,
|
|
946
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
864
947
|
});
|
|
865
948
|
if (!("credential" in materialized)) {
|
|
866
949
|
// Only the multi-turn SKIP is negative-cached. Flow ERRORS
|
|
@@ -879,10 +962,9 @@ async function resolveSelfTestConnection(
|
|
|
879
962
|
}
|
|
880
963
|
return materialized;
|
|
881
964
|
}
|
|
882
|
-
//
|
|
883
|
-
//
|
|
884
|
-
//
|
|
885
|
-
// reuse a login whose latency just failed the case, hiding the failure.
|
|
965
|
+
// Abort is cooperative: a flow may still complete after the case deadline
|
|
966
|
+
// if provider code ignores the signal. Never cache that late credential or
|
|
967
|
+
// let the next probe hide the timed-out login.
|
|
886
968
|
if (options.isAbandoned?.() === true) {
|
|
887
969
|
return {
|
|
888
970
|
kind: "flow_error",
|
|
@@ -913,6 +995,7 @@ async function executeSelfTestCase(
|
|
|
913
995
|
operationId: string,
|
|
914
996
|
suite: AnyHealthCheckSuite,
|
|
915
997
|
healthCase: AnyHealthCheckCase,
|
|
998
|
+
caseController: AbortController,
|
|
916
999
|
): Promise<SelfTestCaseResult> {
|
|
917
1000
|
const { provider, invoke } = execution;
|
|
918
1001
|
// execution.sensitiveValues may grow while the case runs (flow-issued
|
|
@@ -926,6 +1009,8 @@ async function executeSelfTestCase(
|
|
|
926
1009
|
const caseDeadlineAtMs = performance.now() + timeoutMs;
|
|
927
1010
|
const remainingCaseTimeoutMs = () =>
|
|
928
1011
|
Math.max(1, Math.ceil(caseDeadlineAtMs - performance.now()));
|
|
1012
|
+
const runWithCaseTimeout = <T>(run: () => Promise<T>, remainingMs: number) =>
|
|
1013
|
+
withCaseTimeout(run, remainingMs, caseController);
|
|
929
1014
|
|
|
930
1015
|
const beginCase = () => {
|
|
931
1016
|
const startedAt = new Date().toISOString();
|
|
@@ -959,16 +1044,17 @@ async function executeSelfTestCase(
|
|
|
959
1044
|
}
|
|
960
1045
|
|
|
961
1046
|
const resolveConnection = async (forceLogin: boolean): Promise<SelfTestConnectionResolution> => {
|
|
962
|
-
// The
|
|
963
|
-
//
|
|
964
|
-
//
|
|
1047
|
+
// The deadline aborts the in-process flow request. Keep the abandonment
|
|
1048
|
+
// guard as a backstop for provider code that ignores cancellation so a
|
|
1049
|
+
// late completion still cannot write the session cache.
|
|
965
1050
|
let abandoned = false;
|
|
966
1051
|
try {
|
|
967
|
-
return await
|
|
1052
|
+
return await runWithCaseTimeout(
|
|
968
1053
|
() =>
|
|
969
1054
|
resolveSelfTestConnection(execution, operationId, suite, {
|
|
970
1055
|
forceLogin,
|
|
971
1056
|
isAbandoned: () => abandoned,
|
|
1057
|
+
signal: caseController.signal,
|
|
972
1058
|
}),
|
|
973
1059
|
remainingCaseTimeoutMs(),
|
|
974
1060
|
);
|
|
@@ -1012,7 +1098,12 @@ async function executeSelfTestCase(
|
|
|
1012
1098
|
// operation attempt, or a slow login reads as a fast healthy case.
|
|
1013
1099
|
const { startedAtMs, finish } = caseScope;
|
|
1014
1100
|
try {
|
|
1015
|
-
return await
|
|
1101
|
+
return await runWithCaseTimeout(async () => {
|
|
1102
|
+
if (healthCase.assertions === undefined) {
|
|
1103
|
+
throw new Error(
|
|
1104
|
+
`Self-test cannot execute declarative health-check case "${healthCase.name}"; run its scenario through the health monitor.`,
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1016
1107
|
const resolvedInput = resolveHealthCheckInputDateTokens(healthCase.input);
|
|
1017
1108
|
const preparedInput = healthCase.prepareInput
|
|
1018
1109
|
? await healthCase.prepareInput({
|
|
@@ -1033,6 +1124,7 @@ async function executeSelfTestCase(
|
|
|
1033
1124
|
input: gatewayInput,
|
|
1034
1125
|
connection,
|
|
1035
1126
|
requestId: `${execution.requestId}-prepare-${randomUUID()}`,
|
|
1127
|
+
signal: caseController.signal,
|
|
1036
1128
|
});
|
|
1037
1129
|
if (executed.status === 401 || executed.status === 403) {
|
|
1038
1130
|
prepareAuthStatus = executed.status;
|
|
@@ -1053,6 +1145,7 @@ async function executeSelfTestCase(
|
|
|
1053
1145
|
input: preparedInput,
|
|
1054
1146
|
connection,
|
|
1055
1147
|
requestId: `${execution.requestId}-${randomUUID()}`,
|
|
1148
|
+
signal: caseController.signal,
|
|
1056
1149
|
});
|
|
1057
1150
|
const durationMs = performance.now() - startedAtMs;
|
|
1058
1151
|
|
|
@@ -1383,47 +1476,77 @@ export function createSelfTestApp(provider: ProviderDefinition, options: SelfTes
|
|
|
1383
1476
|
};
|
|
1384
1477
|
const deadline = performance.now() + requestBudgetMs;
|
|
1385
1478
|
const results: SelfTestCaseResult[] = [];
|
|
1479
|
+
const runSignal = c.req.raw.signal;
|
|
1480
|
+
let interruptedCase: SelectedCase | undefined;
|
|
1386
1481
|
// Sequential execution (parallelism 1): self-tests run on serving pods
|
|
1387
1482
|
// and must never compete with themselves for upstream quota.
|
|
1388
1483
|
for (const selected of selection.cases) {
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1484
|
+
const caseController = new AbortController();
|
|
1485
|
+
const abortFromRun = () => caseController.abort(runSignal.reason);
|
|
1486
|
+
runSignal.addEventListener("abort", abortFromRun, { once: true });
|
|
1487
|
+
if (runSignal.aborted) abortFromRun();
|
|
1488
|
+
try {
|
|
1489
|
+
if (runSignal.aborted) {
|
|
1490
|
+
interruptedCase = selected;
|
|
1491
|
+
break;
|
|
1492
|
+
}
|
|
1493
|
+
if (performance.now() >= deadline) {
|
|
1494
|
+
const now = new Date().toISOString();
|
|
1495
|
+
results.push({
|
|
1496
|
+
operationId: selected.operationId,
|
|
1497
|
+
caseName: selected.healthCase.name,
|
|
1498
|
+
status: "skipped",
|
|
1499
|
+
label: selected.healthCase.name,
|
|
1500
|
+
responseTimeMs: 0,
|
|
1501
|
+
skipReason: "budget_exhausted",
|
|
1502
|
+
startedAt: now,
|
|
1503
|
+
finishedAt: now,
|
|
1504
|
+
});
|
|
1505
|
+
continue;
|
|
1506
|
+
}
|
|
1507
|
+
if (!isSelfTestReadOnlyOperation(selected.operation)) {
|
|
1508
|
+
const now = new Date().toISOString();
|
|
1509
|
+
results.push({
|
|
1510
|
+
operationId: selected.operationId,
|
|
1511
|
+
caseName: selected.healthCase.name,
|
|
1512
|
+
status: "error",
|
|
1513
|
+
label: selected.healthCase.name,
|
|
1514
|
+
responseTimeMs: 0,
|
|
1515
|
+
error: {
|
|
1516
|
+
code: "operation_not_read_only",
|
|
1517
|
+
message: `Operation "${selected.operationId}" is not classified read-only; self-test refuses to execute it.`,
|
|
1518
|
+
},
|
|
1519
|
+
startedAt: now,
|
|
1520
|
+
finishedAt: now,
|
|
1521
|
+
});
|
|
1522
|
+
continue;
|
|
1523
|
+
}
|
|
1524
|
+
results.push(
|
|
1525
|
+
await executeSelfTestCase(
|
|
1526
|
+
execution,
|
|
1527
|
+
selected.operationId,
|
|
1528
|
+
selected.suite,
|
|
1529
|
+
selected.healthCase,
|
|
1530
|
+
caseController,
|
|
1531
|
+
),
|
|
1532
|
+
);
|
|
1533
|
+
if (runSignal.aborted) {
|
|
1534
|
+
interruptedCase = selected;
|
|
1535
|
+
break;
|
|
1536
|
+
}
|
|
1537
|
+
} finally {
|
|
1538
|
+
runSignal.removeEventListener("abort", abortFromRun);
|
|
1539
|
+
caseController.abort();
|
|
1419
1540
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1541
|
+
}
|
|
1542
|
+
if (interruptedCase) {
|
|
1543
|
+
logSelfTestCancellation(
|
|
1544
|
+
provider,
|
|
1545
|
+
options,
|
|
1546
|
+
request.requestId,
|
|
1547
|
+
interruptedCase,
|
|
1548
|
+
runSignal,
|
|
1549
|
+
execution.sensitiveValues,
|
|
1427
1550
|
);
|
|
1428
1551
|
}
|
|
1429
1552
|
const singleCase = request.operationId !== undefined && request.caseName !== undefined;
|