@apifuse/provider-sdk 2.2.0-beta.2 → 2.2.0-beta.21
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 +487 -0
- package/CHANGELOG.md +90 -0
- package/README.md +49 -3
- package/SUBMISSION.md +1 -1
- package/bin/apifuse-check.ts +44 -59
- package/bin/apifuse-create.ts +1 -1
- package/bin/apifuse-dev.ts +27 -52
- package/bin/apifuse-pack-check.ts +14 -0
- package/bin/apifuse-pack-smoke.ts +36 -81
- package/bin/apifuse-pack-types.ts +305 -0
- package/bin/apifuse-perf.ts +45 -127
- package/bin/apifuse-record.ts +659 -111
- package/bin/apifuse-submit-check.ts +546 -48
- package/bin/apifuse-sync-assets.ts +117 -0
- package/bin/apifuse.ts +1 -1
- package/bin/submit-check-delimited-text.ts +50 -0
- package/bin/submit-check-xml-semantics.ts +204 -0
- package/bin/submit-check-xml.ts +134 -0
- package/dist/auth-turn/index.d.ts +3 -3
- package/dist/auth.d.ts +2 -2
- package/dist/auth.js +9 -18
- package/dist/ceremonies/index.d.ts +9 -1
- package/dist/ceremonies/index.js +65 -18
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +8 -0
- package/dist/cli/create.d.ts +3 -0
- package/dist/cli/create.js +34 -35
- 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/config/loader.d.ts +176 -8
- package/dist/config/loader.js +424 -95
- package/dist/contract-serialization.d.ts +2 -2
- package/dist/contract-serialization.js +3 -6
- package/dist/contract-types.d.ts +2 -2
- package/dist/contract.d.ts +3 -3
- package/dist/contract.js +4 -6
- package/dist/define.d.ts +9 -1
- package/dist/define.js +304 -119
- package/dist/dev.d.ts +1 -1
- package/dist/dev.js +1 -1
- package/dist/error-resolution.d.ts +2 -0
- package/dist/error-resolution.js +90 -0
- package/dist/errors.d.ts +22 -1
- package/dist/errors.js +88 -0
- package/dist/fixture-sanitization.d.ts +26 -0
- package/dist/fixture-sanitization.js +216 -0
- package/dist/i18n/catalog.d.ts +2 -2
- package/dist/i18n/catalog.js +4 -10
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/keys.d.ts +2 -2
- package/dist/index.d.ts +46 -42
- package/dist/index.js +41 -37
- package/dist/lint.d.ts +1 -1
- package/dist/lint.js +8 -15
- 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 +12 -11
- package/dist/provider.js +10 -9
- package/dist/public-schema-field-lint.d.ts +1 -1
- package/dist/recipes/gov-api.js +1 -1
- package/dist/runtime/auth-flow.d.ts +2 -1
- package/dist/runtime/auth-flow.js +4 -3
- package/dist/runtime/browser.d.ts +1 -1
- package/dist/runtime/browser.js +15 -29
- package/dist/runtime/cache.d.ts +1 -1
- package/dist/runtime/cache.js +4 -8
- package/dist/runtime/choice.d.ts +1 -1
- package/dist/runtime/choice.js +31 -35
- package/dist/runtime/credential.d.ts +1 -1
- package/dist/runtime/credential.js +1 -1
- package/dist/runtime/env.d.ts +1 -1
- package/dist/runtime/executor.d.ts +1 -1
- package/dist/runtime/executor.js +31 -4
- package/dist/runtime/http.d.ts +2 -2
- package/dist/runtime/http.js +387 -47
- package/dist/runtime/insights.d.ts +1 -1
- package/dist/runtime/insights.js +6 -13
- package/dist/runtime/instrumentation.d.ts +2 -2
- package/dist/runtime/instrumentation.js +345 -22
- package/dist/runtime/keyring.js +1 -1
- package/dist/runtime/namespace.js +1 -1
- package/dist/runtime/native-network.d.ts +127 -0
- package/dist/runtime/native-network.js +1298 -0
- package/dist/runtime/otlp.d.ts +1 -1
- package/dist/runtime/perf.d.ts +1 -1
- package/dist/runtime/provider.d.ts +1 -1
- package/dist/runtime/provider.js +1 -2
- package/dist/runtime/proxy-errors.d.ts +1 -1
- package/dist/runtime/proxy-errors.js +9 -7
- package/dist/runtime/proxy-nodemaven.d.ts +56 -0
- package/dist/runtime/proxy-nodemaven.js +146 -0
- package/dist/runtime/proxy-retry-policy.d.ts +2 -2
- package/dist/runtime/proxy-retry-policy.js +2 -2
- package/dist/runtime/proxy-telemetry.d.ts +2 -1
- package/dist/runtime/proxy-telemetry.js +55 -52
- 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 +2 -4
- package/dist/runtime/request-options.d.ts +68 -1
- package/dist/runtime/request-options.js +548 -0
- package/dist/runtime/secrets.d.ts +27 -0
- package/dist/runtime/secrets.js +51 -0
- package/dist/runtime/state.d.ts +2 -2
- package/dist/runtime/state.js +238 -26
- package/dist/runtime/stealth.d.ts +5 -3
- package/dist/runtime/stealth.js +423 -143
- package/dist/runtime/stt.d.ts +1 -1
- package/dist/runtime/stt.js +11 -15
- package/dist/runtime/trace.d.ts +2 -2
- package/dist/runtime/trace.js +2 -4
- package/dist/runtime/waterfall.d.ts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +7 -15
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +1 -1
- package/dist/server/index.d.ts +7 -7
- package/dist/server/index.js +6 -6
- 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.d.ts +1 -1
- package/dist/server/self-test-redaction.js +1 -1
- package/dist/server/self-test.d.ts +104 -3
- package/dist/server/self-test.js +673 -115
- package/dist/server/serve.d.ts +116 -4
- package/dist/server/serve.js +799 -128
- package/dist/server/types.d.ts +34 -9
- package/dist/server/types.js +8 -1
- package/dist/stateful/errors.d.ts +14 -0
- package/dist/stateful/errors.js +14 -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 +71 -0
- package/dist/stateful/stateful-provider-session-routing.js +353 -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 +1 -1
- package/dist/stealth/profiles.js +5 -14
- package/dist/stream-evidence.d.ts +74 -0
- package/dist/stream-evidence.js +785 -0
- package/dist/stream.d.ts +1 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -2
- package/dist/testing/run.d.ts +32 -2
- package/dist/testing/run.js +478 -28
- package/dist/types.d.ts +342 -14
- package/dist/types.js +1 -0
- package/dist/user-input.d.ts +30 -0
- package/dist/user-input.js +66 -0
- package/package.json +16 -5
- package/src/auth-turn/index.ts +1 -1
- package/src/auth.ts +28 -86
- package/src/ceremonies/index.ts +103 -78
- package/src/cli/commands.ts +10 -0
- package/src/cli/create.ts +42 -35
- package/src/cli/prompt-assets.ts +865 -0
- package/src/cli/templates/provider/AGENTS.md.tpl +17 -8
- package/src/config/loader.ts +652 -204
- package/src/contract-serialization.ts +5 -11
- package/src/contract-types.ts +2 -2
- package/src/contract.ts +12 -28
- package/src/define.ts +499 -498
- package/src/dev.ts +4 -9
- package/src/error-resolution.ts +91 -0
- package/src/errors.ts +110 -5
- package/src/fixture-sanitization.ts +247 -0
- package/src/i18n/catalog.ts +10 -32
- package/src/i18n/index.ts +2 -2
- package/src/i18n/keys.ts +5 -11
- package/src/index.ts +112 -42
- package/src/lint.ts +88 -152
- 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 +66 -11
- package/src/public-schema-field-lint.ts +7 -33
- package/src/recipes/gov-api.ts +2 -5
- package/src/runtime/auth-flow.ts +7 -7
- package/src/runtime/browser.ts +64 -187
- package/src/runtime/cache.ts +20 -67
- package/src/runtime/choice.ts +79 -132
- package/src/runtime/credential.ts +2 -2
- package/src/runtime/env.ts +1 -1
- package/src/runtime/executor.ts +43 -20
- package/src/runtime/http.ts +494 -57
- package/src/runtime/insights.ts +15 -53
- package/src/runtime/instrumentation.ts +495 -66
- package/src/runtime/keyring.ts +7 -19
- package/src/runtime/namespace.ts +2 -7
- package/src/runtime/native-network.ts +1686 -0
- package/src/runtime/otlp.ts +12 -23
- package/src/runtime/perf.ts +1 -1
- package/src/runtime/provider.ts +4 -9
- package/src/runtime/proxy-errors.ts +29 -42
- package/src/runtime/proxy-nodemaven.ts +221 -0
- package/src/runtime/proxy-retry-policy.ts +3 -3
- package/src/runtime/proxy-telemetry.ts +79 -77
- package/src/runtime/redirects.ts +66 -0
- package/src/runtime/redis.ts +4 -12
- package/src/runtime/request-options.ts +679 -9
- package/src/runtime/secrets.ts +64 -0
- package/src/runtime/state.ts +353 -133
- package/src/runtime/stealth.ts +505 -154
- package/src/runtime/stt.ts +38 -94
- package/src/runtime/trace.ts +14 -44
- package/src/runtime/waterfall.ts +5 -18
- package/src/schema.ts +23 -84
- package/src/serve.ts +1 -1
- package/src/server/index.ts +29 -7
- package/src/server/self-test-input-tokens.ts +29 -14
- package/src/server/self-test-redaction.ts +2 -2
- package/src/server/self-test.ts +857 -132
- package/src/server/serve.ts +1151 -328
- package/src/server/types.ts +12 -13
- package/src/stateful/README.md +146 -0
- package/src/stateful/errors.ts +23 -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 +555 -0
- package/src/stateful/stateful-provider-session-runtime.ts +403 -0
- package/src/stateful-signing.ts +46 -0
- package/src/stealth/profiles.ts +10 -26
- package/src/stream-evidence.ts +988 -0
- package/src/stream.ts +8 -19
- package/src/testing/index.ts +10 -2
- package/src/testing/run.ts +653 -74
- package/src/types.ts +408 -28
- package/src/user-input.ts +118 -0
- 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/lint.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import type { ZodType } from "zod";
|
|
2
2
|
|
|
3
|
-
import { lintPublicSchemaFieldNames } from "./public-schema-field-lint";
|
|
4
|
-
import {
|
|
5
|
-
APIFUSE_DESCRIPTION_KEY_META_KEY,
|
|
6
|
-
APIFUSE_SENSITIVE_META_KEY,
|
|
7
|
-
} from "./schema";
|
|
3
|
+
import { lintPublicSchemaFieldNames } from "./public-schema-field-lint.js";
|
|
4
|
+
import { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_SENSITIVE_META_KEY } from "./schema.js";
|
|
8
5
|
|
|
9
6
|
type AuthModeLike =
|
|
10
7
|
| "none"
|
|
11
8
|
| "platform-managed"
|
|
12
9
|
| "credentials"
|
|
13
10
|
| "oauth2"
|
|
11
|
+
| "oauth2_proxied"
|
|
14
12
|
| "api-key";
|
|
15
13
|
|
|
16
14
|
type ProviderAuthLike = {
|
|
@@ -141,28 +139,19 @@ function hasReusableSecretKeys(keys: readonly string[] | undefined): boolean {
|
|
|
141
139
|
}
|
|
142
140
|
|
|
143
141
|
return keys.some((key) =>
|
|
144
|
-
/(access_token|refresh_token|password|secret|cookie|session|token|api[_-]?key)/i.test(
|
|
145
|
-
key,
|
|
146
|
-
),
|
|
142
|
+
/(access_token|refresh_token|password|secret|cookie|session|token|api[_-]?key)/i.test(key),
|
|
147
143
|
);
|
|
148
144
|
}
|
|
149
145
|
|
|
150
|
-
function hasReusableReloginSecretKeys(
|
|
151
|
-
keys: readonly string[] | undefined,
|
|
152
|
-
): boolean {
|
|
146
|
+
function hasReusableReloginSecretKeys(keys: readonly string[] | undefined): boolean {
|
|
153
147
|
if (!keys) {
|
|
154
148
|
return false;
|
|
155
149
|
}
|
|
156
150
|
|
|
157
|
-
return keys.some((key) =>
|
|
158
|
-
/(password|passcode|secret|cookie|session)/i.test(key),
|
|
159
|
-
);
|
|
151
|
+
return keys.some((key) => /(password|passcode|secret|cookie|session)/i.test(key));
|
|
160
152
|
}
|
|
161
153
|
|
|
162
|
-
function getAuthFlowSource(provider: {
|
|
163
|
-
auth?: ProviderAuthLike;
|
|
164
|
-
authFlowSource?: string;
|
|
165
|
-
}): string {
|
|
154
|
+
function getAuthFlowSource(provider: { auth?: ProviderAuthLike; authFlowSource?: string }): string {
|
|
166
155
|
if (provider.authFlowSource) {
|
|
167
156
|
return provider.authFlowSource;
|
|
168
157
|
}
|
|
@@ -176,10 +165,7 @@ function getAuthFlowSource(provider: {
|
|
|
176
165
|
];
|
|
177
166
|
|
|
178
167
|
return parts
|
|
179
|
-
.filter(
|
|
180
|
-
(part): part is (...args: unknown[]) => unknown =>
|
|
181
|
-
typeof part === "function",
|
|
182
|
-
)
|
|
168
|
+
.filter((part): part is (...args: unknown[]) => unknown => typeof part === "function")
|
|
183
169
|
.map((part) => part.toString())
|
|
184
170
|
.join("\n");
|
|
185
171
|
}
|
|
@@ -243,8 +229,7 @@ function lintAuthModel(provider: {
|
|
|
243
229
|
|
|
244
230
|
if (
|
|
245
231
|
hasReusableSecretKeys(credentialKeys) &&
|
|
246
|
-
(!provider.credential?.storesReusableSecret ||
|
|
247
|
-
!provider.credential.justification)
|
|
232
|
+
(!provider.credential?.storesReusableSecret || !provider.credential.justification)
|
|
248
233
|
) {
|
|
249
234
|
diagnostics.push({
|
|
250
235
|
rule: "credential-reusable-secret",
|
|
@@ -257,8 +242,7 @@ function lintAuthModel(provider: {
|
|
|
257
242
|
if (
|
|
258
243
|
typeof provider.auth?.flow?.refresh === "function" &&
|
|
259
244
|
hasReusableReloginSecretKeys(credentialKeys) &&
|
|
260
|
-
(!provider.credential?.storesReusableSecret ||
|
|
261
|
-
!provider.credential.justification)
|
|
245
|
+
(!provider.credential?.storesReusableSecret || !provider.credential.justification)
|
|
262
246
|
) {
|
|
263
247
|
diagnostics.push({
|
|
264
248
|
rule: "auth-refresh-reusable-secret",
|
|
@@ -278,10 +262,7 @@ function lintAuthModel(provider: {
|
|
|
278
262
|
}
|
|
279
263
|
|
|
280
264
|
const authFlowSource = getAuthFlowSource(provider);
|
|
281
|
-
if (
|
|
282
|
-
authFlowSource.includes("ctx.context") &&
|
|
283
|
-
(provider.context?.keys?.length ?? 0) === 0
|
|
284
|
-
) {
|
|
265
|
+
if (authFlowSource.includes("ctx.context") && (provider.context?.keys?.length ?? 0) === 0) {
|
|
285
266
|
diagnostics.push({
|
|
286
267
|
rule: "context-keys-required",
|
|
287
268
|
level: "warn",
|
|
@@ -323,8 +304,7 @@ function isSchemaRecord(value: unknown): value is Record<string, SchemaLike> {
|
|
|
323
304
|
}
|
|
324
305
|
|
|
325
306
|
function getObjectShape(schema: SchemaLike): Record<string, SchemaLike> {
|
|
326
|
-
const rawShape =
|
|
327
|
-
typeof schema.shape === "function" ? schema.shape() : schema.shape;
|
|
307
|
+
const rawShape = typeof schema.shape === "function" ? schema.shape() : schema.shape;
|
|
328
308
|
if (isSchemaRecord(rawShape)) {
|
|
329
309
|
return rawShape;
|
|
330
310
|
}
|
|
@@ -344,9 +324,7 @@ function getObjectShape(schema: SchemaLike): Record<string, SchemaLike> {
|
|
|
344
324
|
return {};
|
|
345
325
|
}
|
|
346
326
|
|
|
347
|
-
function getChildSchemas(
|
|
348
|
-
schema: SchemaLike,
|
|
349
|
-
): Array<{ key: string; schema: SchemaLike }> {
|
|
327
|
+
function getChildSchemas(schema: SchemaLike): Array<{ key: string; schema: SchemaLike }> {
|
|
350
328
|
const seen = new Map<string, SchemaLike>();
|
|
351
329
|
const def = getSchemaDef(schema);
|
|
352
330
|
|
|
@@ -450,10 +428,7 @@ function getSchemaMetadata(schema: SchemaLike): Record<string, unknown> {
|
|
|
450
428
|
}
|
|
451
429
|
|
|
452
430
|
function getSchemaDescriptionKey(schema: SchemaLike): string | undefined {
|
|
453
|
-
const value = Reflect.get(
|
|
454
|
-
getSchemaMetadata(schema),
|
|
455
|
-
APIFUSE_DESCRIPTION_KEY_META_KEY,
|
|
456
|
-
);
|
|
431
|
+
const value = Reflect.get(getSchemaMetadata(schema), APIFUSE_DESCRIPTION_KEY_META_KEY);
|
|
457
432
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
458
433
|
}
|
|
459
434
|
|
|
@@ -597,22 +572,14 @@ function collectSchemaDescriptionKeyDiagnostics(
|
|
|
597
572
|
? `${currentPath}[]`
|
|
598
573
|
: `${currentPath}.${child.key}`;
|
|
599
574
|
diagnostics.push(
|
|
600
|
-
...collectSchemaDescriptionKeyDiagnostics(
|
|
601
|
-
child.schema,
|
|
602
|
-
childPath,
|
|
603
|
-
seen,
|
|
604
|
-
!isStructuralNode,
|
|
605
|
-
),
|
|
575
|
+
...collectSchemaDescriptionKeyDiagnostics(child.schema, childPath, seen, !isStructuralNode),
|
|
606
576
|
);
|
|
607
577
|
}
|
|
608
578
|
|
|
609
579
|
return diagnostics;
|
|
610
580
|
}
|
|
611
581
|
|
|
612
|
-
function isComplexSchema(
|
|
613
|
-
schema: unknown,
|
|
614
|
-
seen = new Set<SchemaLike>(),
|
|
615
|
-
): boolean {
|
|
582
|
+
function isComplexSchema(schema: unknown, seen = new Set<SchemaLike>()): boolean {
|
|
616
583
|
if (!isSchema(schema) || seen.has(schema)) {
|
|
617
584
|
return false;
|
|
618
585
|
}
|
|
@@ -624,10 +591,7 @@ function isComplexSchema(
|
|
|
624
591
|
return childChildren.length > 0;
|
|
625
592
|
});
|
|
626
593
|
|
|
627
|
-
return (
|
|
628
|
-
hasNestedComposite ||
|
|
629
|
-
children.some(({ schema: child }) => isComplexSchema(child, seen))
|
|
630
|
-
);
|
|
594
|
+
return hasNestedComposite || children.some(({ schema: child }) => isComplexSchema(child, seen));
|
|
631
595
|
}
|
|
632
596
|
|
|
633
597
|
function hasBidirectionalFixtures(fixtures: unknown): boolean {
|
|
@@ -638,16 +602,11 @@ function hasBidirectionalFixtures(fixtures: unknown): boolean {
|
|
|
638
602
|
return "request" in fixtures && "response" in fixtures;
|
|
639
603
|
}
|
|
640
604
|
|
|
641
|
-
function getOperationSource(operation: {
|
|
642
|
-
handler?: unknown;
|
|
643
|
-
source?: string;
|
|
644
|
-
}): string {
|
|
605
|
+
function getOperationSource(operation: { handler?: unknown; source?: string }): string {
|
|
645
606
|
if (operation.source) {
|
|
646
607
|
return operation.source;
|
|
647
608
|
}
|
|
648
|
-
return typeof operation.handler === "function"
|
|
649
|
-
? operation.handler.toString()
|
|
650
|
-
: "";
|
|
609
|
+
return typeof operation.handler === "function" ? operation.handler.toString() : "";
|
|
651
610
|
}
|
|
652
611
|
|
|
653
612
|
function lintStealthTransportUsage(provider: {
|
|
@@ -660,22 +619,20 @@ function lintStealthTransportUsage(provider: {
|
|
|
660
619
|
}
|
|
661
620
|
|
|
662
621
|
const providerLabel = provider.id ? `Provider "${provider.id}"` : "Provider";
|
|
663
|
-
return Object.entries(provider.operations).flatMap(
|
|
664
|
-
(
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
},
|
|
678
|
-
);
|
|
622
|
+
return Object.entries(provider.operations).flatMap(([operationKey, operation]) => {
|
|
623
|
+
const source = getOperationSource(operation);
|
|
624
|
+
if (!/\bctx\.stealth\b/.test(source)) {
|
|
625
|
+
return [];
|
|
626
|
+
}
|
|
627
|
+
return [
|
|
628
|
+
{
|
|
629
|
+
rule: "stealth-config-required",
|
|
630
|
+
level: "error" as const,
|
|
631
|
+
field: `operations.${operationKey}`,
|
|
632
|
+
message: `${providerLabel} operation "${operationKey}" uses ctx.stealth but provider.stealth is not declared.`,
|
|
633
|
+
},
|
|
634
|
+
];
|
|
635
|
+
});
|
|
679
636
|
}
|
|
680
637
|
|
|
681
638
|
function lintCredentialWriteUsage(provider: {
|
|
@@ -685,24 +642,22 @@ function lintCredentialWriteUsage(provider: {
|
|
|
685
642
|
return [];
|
|
686
643
|
}
|
|
687
644
|
|
|
688
|
-
return Object.entries(provider.operations).flatMap(
|
|
689
|
-
(
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
}
|
|
645
|
+
return Object.entries(provider.operations).flatMap(([operationKey, operation]) => {
|
|
646
|
+
const source = getOperationSource(operation);
|
|
647
|
+
if (!/\bctx\.credential\.(?:set|setMany)\s*\(/.test(source)) {
|
|
648
|
+
return [];
|
|
649
|
+
}
|
|
694
650
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
);
|
|
651
|
+
return [
|
|
652
|
+
{
|
|
653
|
+
rule: "ctx-credential-write-forbidden-in-handler",
|
|
654
|
+
level: "error" as const,
|
|
655
|
+
field: `operations.${operationKey}.handler`,
|
|
656
|
+
message:
|
|
657
|
+
"Operation handlers must not mutate credentials; return refreshed credentials from auth.flow.refresh instead.",
|
|
658
|
+
},
|
|
659
|
+
];
|
|
660
|
+
});
|
|
706
661
|
}
|
|
707
662
|
|
|
708
663
|
function lintPlaywrightDirectImports(provider: {
|
|
@@ -724,9 +679,7 @@ function lintPlaywrightDirectImports(provider: {
|
|
|
724
679
|
});
|
|
725
680
|
}
|
|
726
681
|
|
|
727
|
-
for (const [filePath, source] of Object.entries(
|
|
728
|
-
provider.providerSourceFiles ?? {},
|
|
729
|
-
)) {
|
|
682
|
+
for (const [filePath, source] of Object.entries(provider.providerSourceFiles ?? {})) {
|
|
730
683
|
if (!importPattern.test(source)) {
|
|
731
684
|
continue;
|
|
732
685
|
}
|
|
@@ -814,15 +767,11 @@ function lintSelfHostedBrowserPatterns(
|
|
|
814
767
|
sources.push({ field: "auth.flow", source: provider.authFlowSource });
|
|
815
768
|
}
|
|
816
769
|
|
|
817
|
-
for (const [filePath, source] of Object.entries(
|
|
818
|
-
provider.providerSourceFiles ?? {},
|
|
819
|
-
)) {
|
|
770
|
+
for (const [filePath, source] of Object.entries(provider.providerSourceFiles ?? {})) {
|
|
820
771
|
sources.push({ field: `sourceFiles.${filePath}`, source });
|
|
821
772
|
}
|
|
822
773
|
|
|
823
|
-
for (const [operationKey, operation] of Object.entries(
|
|
824
|
-
provider.operations ?? {},
|
|
825
|
-
)) {
|
|
774
|
+
for (const [operationKey, operation] of Object.entries(provider.operations ?? {})) {
|
|
826
775
|
const source = getOperationSource(operation);
|
|
827
776
|
if (source) {
|
|
828
777
|
sources.push({
|
|
@@ -865,16 +814,14 @@ export function lintOperation(op: {
|
|
|
865
814
|
}): LintDiagnostic[] {
|
|
866
815
|
const diagnostics: LintDiagnostic[] = [];
|
|
867
816
|
const description = op.description ?? "";
|
|
868
|
-
const hasDescriptionKey =
|
|
869
|
-
typeof op.descriptionKey === "string" && op.descriptionKey.length > 0;
|
|
817
|
+
const hasDescriptionKey = typeof op.descriptionKey === "string" && op.descriptionKey.length > 0;
|
|
870
818
|
|
|
871
819
|
if (description.trim().length > 0 && !hasDescriptionKey) {
|
|
872
820
|
diagnostics.push({
|
|
873
821
|
rule: "operation-description-raw-prose",
|
|
874
822
|
level: "error",
|
|
875
823
|
field: "description",
|
|
876
|
-
message:
|
|
877
|
-
"Operation description must use descriptionKey instead of raw static prose.",
|
|
824
|
+
message: "Operation description must use descriptionKey instead of raw static prose.",
|
|
878
825
|
});
|
|
879
826
|
}
|
|
880
827
|
|
|
@@ -892,21 +839,16 @@ export function lintOperation(op: {
|
|
|
892
839
|
rule: "operation-when-to-use-raw-prose",
|
|
893
840
|
level: "error",
|
|
894
841
|
field: "whenToUse",
|
|
895
|
-
message:
|
|
896
|
-
"Operation whenToUse must use whenToUseKeys instead of raw static prose.",
|
|
842
|
+
message: "Operation whenToUse must use whenToUseKeys instead of raw static prose.",
|
|
897
843
|
});
|
|
898
844
|
}
|
|
899
845
|
|
|
900
|
-
if (
|
|
901
|
-
(op.whenNotToUse?.length ?? 0) > 0 &&
|
|
902
|
-
!(op.whenNotToUseKeys?.length ?? 0)
|
|
903
|
-
) {
|
|
846
|
+
if ((op.whenNotToUse?.length ?? 0) > 0 && !(op.whenNotToUseKeys?.length ?? 0)) {
|
|
904
847
|
diagnostics.push({
|
|
905
848
|
rule: "operation-when-not-to-use-raw-prose",
|
|
906
849
|
level: "error",
|
|
907
850
|
field: "whenNotToUse",
|
|
908
|
-
message:
|
|
909
|
-
"Operation whenNotToUse must use whenNotToUseKeys instead of raw static prose.",
|
|
851
|
+
message: "Operation whenNotToUse must use whenNotToUseKeys instead of raw static prose.",
|
|
910
852
|
});
|
|
911
853
|
}
|
|
912
854
|
|
|
@@ -942,14 +884,11 @@ export function lintOperation(op: {
|
|
|
942
884
|
rule: "complex-input-has-examples",
|
|
943
885
|
level: "warn",
|
|
944
886
|
field: "inputExamples",
|
|
945
|
-
message:
|
|
946
|
-
"Complex input schemas should provide at least 2 input examples.",
|
|
887
|
+
message: "Complex input schemas should provide at least 2 input examples.",
|
|
947
888
|
});
|
|
948
889
|
}
|
|
949
890
|
|
|
950
|
-
for (const field of uniqueFields(
|
|
951
|
-
collectUnmarkedSensitiveFields(op.input, "input"),
|
|
952
|
-
)) {
|
|
891
|
+
for (const field of uniqueFields(collectUnmarkedSensitiveFields(op.input, "input"))) {
|
|
953
892
|
diagnostics.push({
|
|
954
893
|
rule: "sensitive-field-unmarked",
|
|
955
894
|
level: "warn",
|
|
@@ -958,9 +897,7 @@ export function lintOperation(op: {
|
|
|
958
897
|
});
|
|
959
898
|
}
|
|
960
899
|
|
|
961
|
-
for (const field of uniqueFields(
|
|
962
|
-
collectUnmarkedSensitiveFields(op.output, "output"),
|
|
963
|
-
)) {
|
|
900
|
+
for (const field of uniqueFields(collectUnmarkedSensitiveFields(op.output, "output"))) {
|
|
964
901
|
diagnostics.push({
|
|
965
902
|
rule: "sensitive-field-unmarked",
|
|
966
903
|
level: "warn",
|
|
@@ -1044,36 +981,35 @@ export function lintProvider(
|
|
|
1044
981
|
}
|
|
1045
982
|
|
|
1046
983
|
diagnostics.push(
|
|
1047
|
-
...Object.entries(provider.operations).flatMap(
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
})),
|
|
984
|
+
...Object.entries(provider.operations).flatMap(([operationKey, operation]) =>
|
|
985
|
+
[
|
|
986
|
+
...lintOperation({
|
|
987
|
+
description: operation.description ?? "",
|
|
988
|
+
descriptionKey: operation.descriptionKey,
|
|
989
|
+
whenToUse: operation.whenToUse,
|
|
990
|
+
whenToUseKeys: operation.whenToUseKeys,
|
|
991
|
+
whenNotToUse: operation.whenNotToUse,
|
|
992
|
+
whenNotToUseKeys: operation.whenNotToUseKeys,
|
|
993
|
+
input: operation.input,
|
|
994
|
+
output: operation.output,
|
|
995
|
+
fixtures: operation.fixtures,
|
|
996
|
+
inputExamples: operation.inputExamples,
|
|
997
|
+
derivations: operation.derivations,
|
|
998
|
+
}),
|
|
999
|
+
...lintPublicSchemaFieldNames(
|
|
1000
|
+
provider.id,
|
|
1001
|
+
operationKey,
|
|
1002
|
+
operation.input,
|
|
1003
|
+
operation.output,
|
|
1004
|
+
provider.meta?.contract?.publicSchemaFieldNames === "normalized",
|
|
1005
|
+
),
|
|
1006
|
+
].map((diagnostic) => ({
|
|
1007
|
+
...diagnostic,
|
|
1008
|
+
field: diagnostic.field
|
|
1009
|
+
? `operations.${operationKey}.${diagnostic.field}`
|
|
1010
|
+
: `operations.${operationKey}`,
|
|
1011
|
+
message: `[${operationKey}] ${diagnostic.message}`,
|
|
1012
|
+
})),
|
|
1077
1013
|
),
|
|
1078
1014
|
);
|
|
1079
1015
|
|