@apifuse/provider-sdk 2.2.0-beta.4 → 2.2.0-beta.7
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 +92 -0
- package/CHANGELOG.md +12 -0
- package/README.md +5 -1
- package/SUBMISSION.md +1 -1
- package/bin/apifuse-check.ts +26 -1
- package/bin/apifuse-pack-check.ts +14 -0
- package/bin/apifuse-submit-check.ts +433 -15
- package/bin/apifuse-sync-assets.ts +117 -0
- 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/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/runtime/executor.js +7 -0
- package/dist/runtime/secrets.d.ts +27 -0
- package/dist/runtime/secrets.js +51 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/self-test.d.ts +101 -0
- package/dist/server/self-test.js +670 -112
- package/dist/server/serve.d.ts +5 -0
- package/dist/server/serve.js +41 -1
- package/package.json +1 -1
- 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/index.ts +5 -0
- package/src/runtime/executor.ts +8 -0
- package/src/runtime/secrets.ts +64 -0
- package/src/server/index.ts +5 -0
- package/src/server/self-test.ts +852 -127
- package/src/server/serve.ts +60 -1
- 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
|
@@ -4,8 +4,8 @@ You are building an APIFuse provider. APIFuse turns messy upstream APIs into
|
|
|
4
4
|
normalized, typed, evidence-backed public APIs. A provider that merely proxies
|
|
5
5
|
the upstream is a failed provider, even if every check passes.
|
|
6
6
|
|
|
7
|
-
This file is the core contract. Detailed procedures live in
|
|
8
|
-
the matching skill BEFORE working on that area (index at the bottom).
|
|
7
|
+
This file is the core contract. Detailed procedures live in `.agents/skills/` —
|
|
8
|
+
load the matching skill BEFORE working on that area (index at the bottom).
|
|
9
9
|
|
|
10
10
|
## Non-negotiable principles
|
|
11
11
|
|
|
@@ -75,13 +75,22 @@ bun run submit-check # structural score; a high score does NOT prove quality
|
|
|
75
75
|
`submit-check` is a structural gate. Every principle above can be violated
|
|
76
76
|
while scoring 95/100 — reviewers and CI audit for exactly these classes.
|
|
77
77
|
|
|
78
|
+
## Managed prompt assets
|
|
79
|
+
|
|
80
|
+
`AGENTS.md` and `.agents/skills/**` are generated by the SDK; `CLAUDE.md`,
|
|
81
|
+
`.claude`, and `.codex` are symlinks onto them so every agent CLI reads the
|
|
82
|
+
same contract. Do not hand-edit these files — regenerate them with
|
|
83
|
+
`bun run sync-assets` (or `bunx apifuse sync-assets .`). `apifuse check` and
|
|
84
|
+
`submit-check` enforce a freshness gate: stale or modified prompt assets
|
|
85
|
+
(tracked in `.apifuse/prompt-assets.json`) block submission until re-synced.
|
|
86
|
+
|
|
78
87
|
## Skill index — load before working on:
|
|
79
88
|
|
|
80
89
|
| Area | Load |
|
|
81
90
|
| --- | --- |
|
|
82
|
-
| Output schemas, mappers, field naming, timestamps, enums |
|
|
83
|
-
| Upstream request params, new endpoint wiring, field mapping |
|
|
84
|
-
| Recording fixtures, writing tests against fixtures |
|
|
85
|
-
| List operations, paging, totals, client-side filtering |
|
|
86
|
-
| healthCheck blocks, error classification, fail-closed guards |
|
|
87
|
-
| Upstream-specific known pitfalls for THIS bounty |
|
|
91
|
+
| Output schemas, mappers, field naming, timestamps, enums | `.agents/skills/normalization-standards/SKILL.md` |
|
|
92
|
+
| Upstream request params, new endpoint wiring, field mapping | `.agents/skills/upstream-contract-verification/SKILL.md` |
|
|
93
|
+
| Recording fixtures, writing tests against fixtures | `.agents/skills/fixtures-and-recording/SKILL.md` |
|
|
94
|
+
| List operations, paging, totals, client-side filtering | `.agents/skills/pagination-and-counts/SKILL.md` |
|
|
95
|
+
| healthCheck blocks, error classification, fail-closed guards | `.agents/skills/health-checks-and-fail-closed/SKILL.md` |
|
|
96
|
+
| Upstream-specific known pitfalls for THIS bounty | `.agents/skills/upstream-notes/` (read every file) |
|
package/src/index.ts
CHANGED
|
@@ -74,6 +74,11 @@ export {
|
|
|
74
74
|
} from "./runtime/instrumentation.js";
|
|
75
75
|
export { type PrevalidateResult, prevalidate } from "./runtime/prevalidate.js";
|
|
76
76
|
export { getProviderBaseUrl } from "./runtime/provider.js";
|
|
77
|
+
export {
|
|
78
|
+
assertRequiredSecretsPresent,
|
|
79
|
+
listMissingRequiredSecrets,
|
|
80
|
+
MISSING_SECRET_CODE,
|
|
81
|
+
} from "./runtime/secrets.js";
|
|
77
82
|
export {
|
|
78
83
|
createUnsupportedProviderRuntimeState,
|
|
79
84
|
UnsupportedProviderStateError,
|
package/src/runtime/executor.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isSessionExpiredError, ProviderError, SessionExpiredError } from "../errors.js";
|
|
2
2
|
import { parseSchema } from "../schema.js";
|
|
3
3
|
import type { ProviderContext, ProviderDefinition } from "../types.js";
|
|
4
|
+
import { assertRequiredSecretsPresent } from "./secrets.js";
|
|
4
5
|
|
|
5
6
|
export function isStreamingOperation(provider: ProviderDefinition, operationId: string): boolean {
|
|
6
7
|
const kind = provider.operations[operationId]?.transport?.kind ?? "json";
|
|
@@ -34,6 +35,13 @@ export async function executeOperation(
|
|
|
34
35
|
});
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
// SDK-owned secret presence gate (single source of truth): declared
|
|
39
|
+
// `required: true` secrets are validated here, before input parsing and the
|
|
40
|
+
// handler, so every invocation path (serve /v1, self-test probes, perf,
|
|
41
|
+
// record) fails with the same structured MISSING_SECRET error instead of a
|
|
42
|
+
// handler-specific crash. Providers must not re-check presence locally.
|
|
43
|
+
assertRequiredSecretsPresent(provider, ctx.env);
|
|
44
|
+
|
|
37
45
|
const validatedInput = await parseSchema(
|
|
38
46
|
operation.input,
|
|
39
47
|
input,
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ProviderSecretError } from "../errors.js";
|
|
2
|
+
import type { EnvContext, ProviderDefinition } from "../types.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Canonical error code for a declared-but-unprovisioned provider secret.
|
|
6
|
+
*
|
|
7
|
+
* The SDK is the single source of truth for env/secret presence validation:
|
|
8
|
+
* providers declare secrets in `defineProvider({ secrets: [...] })` and the
|
|
9
|
+
* runtime enforces presence before any handler or auth-flow code runs.
|
|
10
|
+
* Provider-local presence guards (requireServiceKey/requireApiKey style) are a
|
|
11
|
+
* deprecated antipattern — see the `sdk-owned-secret-presence` submit-check
|
|
12
|
+
* rule.
|
|
13
|
+
*/
|
|
14
|
+
export const MISSING_SECRET_CODE = "MISSING_SECRET";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Names of declared `required: true` secrets whose env values are unset or
|
|
18
|
+
* whitespace-only. Whitespace-only values count as missing for parity with the
|
|
19
|
+
* `.trim()` guards well-built providers used before the SDK owned this check —
|
|
20
|
+
* a blank value provisioned by a broken secret pipeline must not pass the gate.
|
|
21
|
+
*/
|
|
22
|
+
export function listMissingRequiredSecrets(
|
|
23
|
+
provider: ProviderDefinition,
|
|
24
|
+
env: EnvContext,
|
|
25
|
+
): string[] {
|
|
26
|
+
const missing: string[] = [];
|
|
27
|
+
for (const secret of provider.secrets ?? []) {
|
|
28
|
+
if (secret.required !== true) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const value = env.get(secret.name);
|
|
32
|
+
if (value === undefined || value.trim() === "") {
|
|
33
|
+
missing.push(secret.name);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return missing;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Throws the canonical structured missing-secret error when any declared
|
|
41
|
+
* `required: true` secret is absent. All missing names are reported in a
|
|
42
|
+
* single error so operators can provision the full set in one pass instead of
|
|
43
|
+
* discovering them one deploy at a time (the 2026-07-22 unprovisioned-secret
|
|
44
|
+
* incident failure mode).
|
|
45
|
+
*/
|
|
46
|
+
export function assertRequiredSecretsPresent(
|
|
47
|
+
provider: ProviderDefinition,
|
|
48
|
+
env: EnvContext,
|
|
49
|
+
): void {
|
|
50
|
+
const missing = listMissingRequiredSecrets(provider, env);
|
|
51
|
+
if (missing.length === 0) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const names = missing.join(", ");
|
|
55
|
+
throw new ProviderSecretError(
|
|
56
|
+
`Missing required provider secret${missing.length > 1 ? "s" : ""}: ${names}`,
|
|
57
|
+
{
|
|
58
|
+
code: MISSING_SECRET_CODE,
|
|
59
|
+
category: "credential_unavailable",
|
|
60
|
+
retryable: false,
|
|
61
|
+
fix: `Provision ${names} in the provider environment (e.g. Doppler). Declared in defineProvider({ secrets: [...] }).`,
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
}
|
package/src/server/index.ts
CHANGED
|
@@ -2,15 +2,20 @@ export { createServerApp, type ServeOptions, serve } from "./serve.js";
|
|
|
2
2
|
export {
|
|
3
3
|
computeSelfTestPlanDigest,
|
|
4
4
|
createSelfTestApp,
|
|
5
|
+
createSelfTestAuthFlowInvoke,
|
|
5
6
|
createSelfTestInvoke,
|
|
6
7
|
DEFAULT_SELF_TEST_REQUEST_BUDGET_MS,
|
|
7
8
|
isSelfTestReadOnlyOperation,
|
|
8
9
|
PROVIDER_RUNTIME_SELF_TEST_REQUEST_BUDGET_MS_ENV,
|
|
9
10
|
resolveSelfTestPort,
|
|
11
|
+
SELF_TEST_AUTH_FLOW_MULTI_TURN_SKIP_REASON,
|
|
12
|
+
SELF_TEST_AUTH_FLOW_REJECTED_SKIP_REASON,
|
|
10
13
|
SELF_TEST_HEALTHZ_PATH,
|
|
11
14
|
SELF_TEST_PATH,
|
|
12
15
|
SELF_TEST_SCHEMA_VERSION,
|
|
13
16
|
type SelfTestAppOptions,
|
|
17
|
+
type SelfTestAuthFlowInvoke,
|
|
18
|
+
type SelfTestAuthFlowRoute,
|
|
14
19
|
type SelfTestCaseResult,
|
|
15
20
|
type SelfTestCaseStatus,
|
|
16
21
|
type SelfTestOperationInvoke,
|