@apifuse/provider-sdk 2.1.0-beta.9 → 2.2.0-beta.2

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.
Files changed (138) hide show
  1. package/AUTHORING.md +134 -0
  2. package/CHANGELOG.md +61 -0
  3. package/README.md +21 -9
  4. package/SUBMISSION.md +10 -11
  5. package/bin/apifuse-pack-check.ts +22 -0
  6. package/bin/apifuse-submit-check.ts +1747 -388
  7. package/dist/auth-turn/auth-turn.v1.schema.json +89 -0
  8. package/dist/auth-turn/fixtures/invalid/empty-kind.json +4 -0
  9. package/dist/auth-turn/fixtures/invalid/expires-at-not-string.json +5 -0
  10. package/dist/auth-turn/fixtures/invalid/missing-kind.json +3 -0
  11. package/dist/auth-turn/fixtures/invalid/missing-turn-id.json +3 -0
  12. package/dist/auth-turn/fixtures/invalid/timing-unknown-field.json +7 -0
  13. package/dist/auth-turn/fixtures/invalid/turn-id-snake-case.json +4 -0
  14. package/dist/auth-turn/fixtures/invalid/unknown-top-level-field.json +5 -0
  15. package/dist/auth-turn/fixtures/valid/abort.json +8 -0
  16. package/dist/auth-turn/fixtures/valid/challenge.json +17 -0
  17. package/dist/auth-turn/fixtures/valid/complete.json +13 -0
  18. package/dist/auth-turn/fixtures/valid/form.json +14 -0
  19. package/dist/auth-turn/fixtures/valid/message.json +13 -0
  20. package/dist/auth-turn/fixtures/valid/multi_choice.json +15 -0
  21. package/dist/auth-turn/fixtures/valid/pending.json +5 -0
  22. package/dist/auth-turn/fixtures/valid/poll.json +9 -0
  23. package/dist/auth-turn/fixtures/valid/redirect.json +16 -0
  24. package/dist/auth-turn/fixtures/valid/retry.json +8 -0
  25. package/dist/auth-turn/fixtures/valid/unknown-kind.json +7 -0
  26. package/dist/auth-turn/index.d.ts +195 -0
  27. package/dist/auth-turn/index.js +133 -0
  28. package/dist/auth.d.ts +76 -0
  29. package/dist/auth.js +436 -0
  30. package/dist/ceremonies/index.js +7 -31
  31. package/dist/cli/create.js +45 -30
  32. package/dist/cli/templates/provider/.dockerignore.tpl +22 -0
  33. package/dist/cli/templates/provider/.gitignore.tpl +22 -0
  34. package/dist/cli/templates/provider/AGENTS.md.tpl +87 -0
  35. package/dist/cli/templates/provider/CLAUDE.md.tpl +1 -0
  36. package/dist/cli/templates/provider/Dockerfile.tpl +7 -0
  37. package/dist/cli/templates/provider/README.md.tpl +163 -0
  38. package/dist/cli/templates/provider/dev.ts.tpl +5 -0
  39. package/dist/cli/templates/provider/domain/README.md.tpl +3 -0
  40. package/dist/cli/templates/provider/index.test.ts.tpl +13 -0
  41. package/dist/cli/templates/provider/index.ts.tpl +15 -0
  42. package/dist/cli/templates/provider/mappers/README.md.tpl +3 -0
  43. package/dist/cli/templates/provider/meta.ts.tpl +7 -0
  44. package/dist/cli/templates/provider/operations/index.ts.tpl +5 -0
  45. package/dist/cli/templates/provider/operations/ping.ts.tpl +24 -0
  46. package/dist/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  47. package/dist/cli/templates/provider/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
  48. package/dist/cli/templates/provider/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
  49. package/dist/cli/templates/provider/skills/normalization-standards/SKILL.md.tpl +57 -0
  50. package/dist/cli/templates/provider/skills/pagination-and-counts/SKILL.md.tpl +52 -0
  51. package/dist/cli/templates/provider/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
  52. package/dist/cli/templates/provider/skills/upstream-notes/README.md.tpl +13 -0
  53. package/dist/cli/templates/provider/start.ts.tpl +5 -0
  54. package/dist/cli/templates/provider/upstream/README.md.tpl +3 -0
  55. package/dist/contract.js +1 -0
  56. package/dist/define.d.ts +6 -1
  57. package/dist/define.js +140 -70
  58. package/dist/index.d.ts +3 -2
  59. package/dist/index.js +2 -1
  60. package/dist/lint.d.ts +1 -0
  61. package/dist/lint.js +27 -0
  62. package/dist/provider.d.ts +4 -2
  63. package/dist/provider.js +2 -1
  64. package/dist/runtime/auth-flow.js +2 -0
  65. package/dist/runtime/browser.js +203 -0
  66. package/dist/runtime/http.js +46 -336
  67. package/dist/runtime/proxy-retry-policy.d.ts +40 -0
  68. package/dist/runtime/proxy-retry-policy.js +326 -0
  69. package/dist/runtime/stealth.d.ts +5 -2
  70. package/dist/runtime/stealth.js +206 -206
  71. package/dist/server/index.d.ts +4 -0
  72. package/dist/server/index.js +4 -0
  73. package/dist/server/self-test-input-tokens.d.ts +1 -0
  74. package/dist/server/self-test-input-tokens.js +37 -0
  75. package/dist/server/self-test-redaction.d.ts +20 -0
  76. package/dist/server/self-test-redaction.js +70 -0
  77. package/dist/server/self-test-token.d.ts +30 -0
  78. package/dist/server/self-test-token.js +50 -0
  79. package/dist/server/self-test.d.ts +98 -0
  80. package/dist/server/self-test.js +555 -0
  81. package/dist/server/serve.d.ts +6 -0
  82. package/dist/server/serve.js +38 -10
  83. package/dist/server/types.d.ts +1 -0
  84. package/dist/server/types.js +1 -0
  85. package/dist/testing/run.js +5 -1
  86. package/dist/types.d.ts +150 -0
  87. package/package.json +9 -2
  88. package/src/auth-turn/auth-turn.v1.schema.json +89 -0
  89. package/src/auth-turn/fixtures/invalid/empty-kind.json +4 -0
  90. package/src/auth-turn/fixtures/invalid/expires-at-not-string.json +5 -0
  91. package/src/auth-turn/fixtures/invalid/missing-kind.json +3 -0
  92. package/src/auth-turn/fixtures/invalid/missing-turn-id.json +3 -0
  93. package/src/auth-turn/fixtures/invalid/timing-unknown-field.json +7 -0
  94. package/src/auth-turn/fixtures/invalid/turn-id-snake-case.json +4 -0
  95. package/src/auth-turn/fixtures/invalid/unknown-top-level-field.json +5 -0
  96. package/src/auth-turn/fixtures/valid/abort.json +8 -0
  97. package/src/auth-turn/fixtures/valid/challenge.json +17 -0
  98. package/src/auth-turn/fixtures/valid/complete.json +13 -0
  99. package/src/auth-turn/fixtures/valid/form.json +14 -0
  100. package/src/auth-turn/fixtures/valid/message.json +13 -0
  101. package/src/auth-turn/fixtures/valid/multi_choice.json +15 -0
  102. package/src/auth-turn/fixtures/valid/pending.json +5 -0
  103. package/src/auth-turn/fixtures/valid/poll.json +9 -0
  104. package/src/auth-turn/fixtures/valid/redirect.json +16 -0
  105. package/src/auth-turn/fixtures/valid/retry.json +8 -0
  106. package/src/auth-turn/fixtures/valid/unknown-kind.json +7 -0
  107. package/src/auth-turn/index.ts +177 -0
  108. package/src/auth.ts +786 -0
  109. package/src/ceremonies/index.ts +9 -43
  110. package/src/cli/create.ts +60 -97
  111. package/src/cli/templates/provider/AGENTS.md.tpl +87 -0
  112. package/src/cli/templates/provider/CLAUDE.md.tpl +1 -0
  113. package/src/cli/templates/provider/README.md.tpl +7 -4
  114. package/src/cli/templates/provider/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
  115. package/src/cli/templates/provider/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
  116. package/src/cli/templates/provider/skills/normalization-standards/SKILL.md.tpl +57 -0
  117. package/src/cli/templates/provider/skills/pagination-and-counts/SKILL.md.tpl +52 -0
  118. package/src/cli/templates/provider/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
  119. package/src/cli/templates/provider/skills/upstream-notes/README.md.tpl +13 -0
  120. package/src/contract.ts +1 -0
  121. package/src/define.ts +198 -71
  122. package/src/index.ts +16 -0
  123. package/src/lint.ts +33 -0
  124. package/src/provider.ts +27 -0
  125. package/src/runtime/auth-flow.ts +2 -0
  126. package/src/runtime/browser.ts +293 -1
  127. package/src/runtime/http.ts +84 -530
  128. package/src/runtime/proxy-retry-policy.ts +469 -0
  129. package/src/runtime/stealth.ts +269 -353
  130. package/src/server/index.ts +36 -0
  131. package/src/server/self-test-input-tokens.ts +46 -0
  132. package/src/server/self-test-redaction.ts +97 -0
  133. package/src/server/self-test-token.ts +70 -0
  134. package/src/server/self-test.ts +725 -0
  135. package/src/server/serve.ts +75 -6
  136. package/src/server/types.ts +1 -0
  137. package/src/testing/run.ts +9 -1
  138. package/src/types.ts +186 -0
package/AUTHORING.md CHANGED
@@ -264,6 +264,140 @@ deployment projection checks, and release workflows.
264
264
  - Credential-backed smoke requests pass local-only credential material in
265
265
  `connection.secrets`. Keep real values in shell env or `.env`, never in source
266
266
  or fixtures.
267
+ - Hand-written auth flows should use `ctx.auth` helpers and return exactly one
268
+ terminal/next turn from each handler: `ctx.auth.nextForm(...)` or
269
+ `ctx.auth.nextPoll(...)` to ask Gateway for the next user/system step,
270
+ `ctx.auth.complete(...)` to finish with `data.credential`, or
271
+ `ctx.auth.abort(...)` to stop safely. Keep abort `data` and `actionHint`
272
+ JSON-safe and secret-free; never include raw cookies, credentials, headers,
273
+ HTML, or upstream `Error` objects.
274
+
275
+ ```ts
276
+ export default defineProvider({
277
+ id: "example-provider",
278
+ version: "1.0.0",
279
+ runtime: "standard",
280
+ auth: {
281
+ mode: "credentials",
282
+ flow: {
283
+ async start(ctx) {
284
+ return ctx.auth.nextForm({
285
+ fields: {
286
+ email: { type: "email", labelKey: "auth.email.label" },
287
+ password: { type: "password", labelKey: "auth.password.label" },
288
+ },
289
+ hintKey: "auth.signIn",
290
+ });
291
+ },
292
+ async continue(ctx, input) {
293
+ const result = await loginWithSubmittedFields(ctx, input);
294
+ if (result.blocked) {
295
+ return ctx.auth.abort({
296
+ code: "account_action_required",
297
+ retry: "after_user_action",
298
+ actionHint: { kind: "open_provider_app" },
299
+ message: "Approve the login in the provider app.",
300
+ });
301
+ }
302
+ return ctx.auth.complete({
303
+ credential: { cookie: result.cookie },
304
+ metadata: { accountId: result.accountId },
305
+ });
306
+ },
307
+ },
308
+ },
309
+ credential: { keys: ["cookie"] },
310
+ // ...metadata and operations
311
+ });
312
+ ```
313
+
314
+ - Credentials auth providers should use `defineCredentialsAuth()` instead of
315
+ hand-writing `auth.flow.start/continue`. The helper exposes one happy path:
316
+ declare form `fields`, declare `credentialKeys`, and put upstream login/session
317
+ creation in `login(ctx, input)`. It returns both `auth` and `credential` for
318
+ `defineProvider()` and builds the complete turn as `data.credential`, which is
319
+ the only value Gateway persists onto the connection.
320
+
321
+ ```ts
322
+ import { defineCredentialsAuth, defineProvider } from "@apifuse/provider-sdk";
323
+
324
+ const credentialsAuth = defineCredentialsAuth({
325
+ fields: {
326
+ email: { type: "email", labelKey: "auth.email.label" },
327
+ password: { type: "password", labelKey: "auth.password.label" },
328
+ },
329
+ credentialKeys: ["cookie"] as const,
330
+ storesReusableSecret: true,
331
+ justification: "Session cookie is required for authenticated operations.",
332
+ async login(ctx, input) {
333
+ const cookie = await loginAndBuildSessionCookie(ctx, input);
334
+ return { credential: { cookie } };
335
+ },
336
+ });
337
+
338
+ export default defineProvider({
339
+ id: "example-provider",
340
+ version: "1.0.0",
341
+ runtime: "standard",
342
+ auth: credentialsAuth.auth,
343
+ credential: credentialsAuth.credential,
344
+ context: credentialsAuth.context,
345
+ // ...metadata and operations
346
+ });
347
+ ```
348
+
349
+ For OTP, MFA, CAPTCHA handoff, or user-approved login, return a challenge from
350
+ `login()` instead of hand-writing `contextPatch`, `poll`, and final credential
351
+ turns. SDK stores the pending challenge in auth-flow context, returns the next
352
+ form/pending turn, and still persists only the final `data.credential`.
353
+
354
+ ```ts
355
+ import {
356
+ credentialsAuthChallenge,
357
+ defineCredentialsAuth,
358
+ } from "@apifuse/provider-sdk";
359
+
360
+ const credentialsAuth = defineCredentialsAuth({
361
+ fields: {
362
+ email: { type: "email" },
363
+ password: { type: "password" },
364
+ },
365
+ credentialKeys: ["cookie"] as const,
366
+ async login(ctx, input) {
367
+ const result = await passwordLogin(ctx, input);
368
+ if (result.otpRequired) {
369
+ return credentialsAuthChallenge("otp", {
370
+ state: { transactionId: result.transactionId },
371
+ hintKey: "auth.otp.prompt",
372
+ });
373
+ }
374
+ if (result.manualApprovalRequired) {
375
+ return credentialsAuthChallenge("manualApproval", {
376
+ state: { transactionId: result.transactionId },
377
+ hintKey: "auth.manualApproval.openApp",
378
+ timing: { suggestedPollIntervalMs: 3000, maxWaitMs: 120000 },
379
+ });
380
+ }
381
+ return { credential: { cookie: result.cookie } };
382
+ },
383
+ challenges: {
384
+ otp: {
385
+ fields: { otp: { type: "otp", labelKey: "auth.otp.label" } },
386
+ async verify(ctx, input, state) {
387
+ const result = await verifyOtp(ctx, state.transactionId, input.otp);
388
+ return { credential: { cookie: result.cookie } };
389
+ },
390
+ },
391
+ manualApproval: {
392
+ async poll(ctx, state) {
393
+ const result = await checkApproval(ctx, state.transactionId);
394
+ if (!result.approved) return null;
395
+ return { credential: { cookie: result.cookie } };
396
+ },
397
+ },
398
+ },
399
+ });
400
+ ```
267
401
  - Auth-flow debugging starts with `/auth/start`, continues with
268
402
  `/auth/continue`, and carries returned `contextPatch` values into the next
269
403
  request's `context`.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,66 @@
1
1
  # @apifuse/provider-sdk Changelog
2
2
 
3
+ ## 2.2.0-beta.2
4
+
5
+ - Release candidate for main commit ceefad020a1038eade542fd3b128667b39625f6f.
6
+
7
+ ## 2.2.0-beta.1
8
+
9
+ - Release candidate for main commit 5056b8c89fe0fa8f10bafcd30f83bcc421d4b5c5.
10
+
11
+ ## 2.1.0-beta.22
12
+
13
+ - Release candidate for main commit af84b1e91c408b69773468fdaef80a01a36707cf.
14
+
15
+ ## 2.1.0-beta.21
16
+
17
+ - Release candidate for main commit 8124b3eb150cc7a73a86a95266b3747763a494ae.
18
+
19
+ ## 2.1.0-beta.20
20
+
21
+ - Release candidate for main commit 2a07cc5aef0d517c3b01d20445105f1669446bd3.
22
+
23
+ ## 2.1.0-beta.19
24
+
25
+ - Release candidate for main commit 71d76385f722b1202880f26b14ea3916a07852eb.
26
+
27
+ ## 2.1.0-beta.18
28
+
29
+ - Release candidate for main commit 46f93ecf8c2c8aab1afd0f23f5f62a87cbb45f6d.
30
+
31
+ ## 2.1.0-beta.17
32
+
33
+ - Release candidate for main commit c4466ffc8a30cb99740b50687a62b92cec9ba10e.
34
+
35
+ ## 2.1.0-beta.16
36
+
37
+ - Release candidate for main commit c0d8a1c4be519e1c1abc59e0304efc64f371634d.
38
+
39
+ ## Unreleased
40
+
41
+ - Add `arrayBuffer()` and `bytes()` to `HttpResponse` so `ctx.http` consumers can read binary-safe upstream bodies; internal response handling is now byte-first.
42
+ - Preserve identity-only operation `connectionId` values in `ProviderContext` without requiring credential material.
43
+
44
+ ## 2.1.0-beta.15
45
+
46
+ - Release candidate for main commit 4f51232d87828082f117dcc9f0c257a46f37c040.
47
+
48
+ ## 2.1.0-beta.14
49
+
50
+ - Release candidate for main commit 6eb132be6abf34ad9a70bfe28c6d26b36348ff4a.
51
+
52
+ ## 2.1.0-beta.13
53
+
54
+ - Release candidate for main commit d7b12716f54781df3e40206144c167844a485f8f.
55
+
56
+ ## 2.1.0-beta.12
57
+
58
+ - Release candidate for main commit 2bc1061c6a68facaa2efde08bee31bf5cd96945e.
59
+
60
+ ## 2.1.0-beta.11
61
+
62
+ - Release candidate for main commit b98ddc5024698f8c79e05e3295f7c8c8e8fe5a8a.
63
+
3
64
  ## 2.1.0-beta.9
4
65
 
5
66
  - Preserve raw stealth response bytes through the public SDK response wrapper.
package/README.md CHANGED
@@ -56,7 +56,7 @@ Removed legacy runtime paths are not supported:
56
56
  cd my-provider
57
57
  bun run check
58
58
  bun run test
59
- bun run submit-check
59
+ bun run submit-check -- --smoke
60
60
  bun run dev
61
61
  ```
62
62
 
@@ -120,16 +120,28 @@ the bad request path; provider/runtime failures include `code`, `message`, and
120
120
  `ctx.credential.get("key")` or `ctx.credential.getAccessToken()`.
121
121
  - **Provider env secrets**: declare `secrets[]`, set values in your shell or
122
122
  `.env`, and read only those names through `ctx.env.get("NAME")`.
123
+ - **Credentials auth flows**: prefer `defineCredentialsAuth()` over hand-written
124
+ `auth.flow`. Declare the form fields and credential keys once, then put the
125
+ upstream login/session creation in `login(ctx, input)`. Return
126
+ `credentialsAuthChallenge("otp" | "manualApproval" | ...)` for MFA, CAPTCHA
127
+ handoff, or user-approved login branches. The helper returns
128
+ `{ auth, credential, context }` for `defineProvider()` and always completes
129
+ with `data.credential`, which is the value Gateway persists onto the
130
+ connection.
123
131
  - **Auth flows**: call `/auth/start`, then `/auth/continue` with the same
124
132
  `flowId`; preserve any returned `contextPatch` in the next local request's
125
133
  `context` object.
126
134
  - **Stealth-sensitive providers**: use `ctx.http` for normal JSON/REST calls and
127
- `ctx.stealth.fetch()` when you need browser-like session or cookie control. `ctx.stealth.fetch()` uses the impit-backed browser stealth transport and accepts request
128
- controls for `params`, `proxy`, `timeout`, `profile`, `throwOnHttpError`, and
129
- `stealth.insecureSkipVerify`. Select an SDK stealth `profile` such as
130
- `chrome-146`; do not tune JA3, HTTP/2 SETTINGS, or pseudo-header order in
131
- provider code. Chrome/Firefox-style profiles are supported; use `ctx.browser`
132
- when Safari-specific behavior is required.
135
+ `ctx.stealth.fetch()` when you need browser-like session or cookie control.
136
+ `ctx.stealth.fetch()` uses the impit-backed browser stealth transport and
137
+ accepts request controls for `params`, `proxy`, `timeout`, `profile`,
138
+ `redirect`, `throwOnHttpError`, and `stealth.insecureSkipVerify`. For login
139
+ flows that must inspect intermediate `Location`/`Set-Cookie` headers, create
140
+ a session with `ctx.stealth.createSession()` and use `session.redirects.run()`;
141
+ inspect accumulated cookies through `session.cookies`. Select an SDK stealth
142
+ `profile` such as `chrome-146`; do not tune JA3, HTTP/2 SETTINGS, or
143
+ pseudo-header order in provider code. Chrome/Firefox-style profiles are
144
+ supported; use `ctx.browser` when Safari-specific behavior is required.
133
145
  - **Browser providers**: for TypeScript Providers use `runtime: "browser"` plus
134
146
  `browser.engine: "playwright-stealth"`; `nodriver` is a Python-runtime path.
135
147
  Install local browser assets with `bunx playwright install chromium` when
@@ -233,10 +245,10 @@ be replaced before recording fixtures.
233
245
  Standalone providers include a pre-submission script:
234
246
 
235
247
  ```bash
236
- bun run submit-check
248
+ bun run submit-check -- --smoke
237
249
  ```
238
250
 
239
- This runs the public review-readiness evaluator and writes `submission-report.md`. The report contains provider metadata, a 100-point readiness score, hard blockers, warnings, checklist evidence, and remediation. Blockers override the score; fix them before posting bounty evidence. The command is offline-safe by default and does not execute arbitrary upstream calls. Add local smoke notes to your assigned workspace PR after testing `/health` and `POST /v1/{operation}`. See [`SUBMISSION.md`](./SUBMISSION.md) for the full public-only bounty submission checklist shipped in the npm package.
251
+ This runs the public review-readiness evaluator and writes `submission-report.md`. The report contains provider metadata, a 100-point readiness score, hard blockers, warnings, checklist evidence, measured smoke details, and remediation. Blockers override the score; fix them before posting bounty evidence. `--smoke` boots the local dev server, checks `/health`, and POSTs every operation fixture. Set `APIFUSE__PROVIDER__*` env vars when live upstream credentials are available; without them, structured provider errors can still earn runtime-path smoke credit. See [`SUBMISSION.md`](./SUBMISSION.md) for the full public-only bounty submission checklist shipped in the npm package.
240
252
 
241
253
  ## Scope boundary
242
254
 
package/SUBMISSION.md CHANGED
@@ -9,11 +9,11 @@ bunx @apifuse/provider-sdk@beta create my-provider --yes
9
9
  cd my-provider
10
10
  bun run check
11
11
  bun run test
12
- bun run submit-check
12
+ bun run submit-check -- --smoke
13
13
  bun run dev
14
14
  ```
15
15
 
16
- `bun run submit-check` runs `apifuse submit-check . --markdown submission-report.md` in generated Providers.
16
+ `bun run submit-check -- --smoke` runs the generated `apifuse submit-check . --markdown submission-report.md` script with measured smoke enabled.
17
17
 
18
18
  ## What submit-check scores
19
19
 
@@ -52,20 +52,19 @@ Fix all blockers before submitting:
52
52
 
53
53
  Warnings do not fail the command, but they should be addressed when practical. For example, the generated starter `ping` operation warns because it is not a real upstream-backed bounty Operation. SDK-native warnings also flag moderate `as Type` assertion counts and credentialed Providers that never reference `ctx.credential`.
54
54
 
55
- ## Safe local smoke evidence
55
+ ## Measured local smoke
56
56
 
57
- `submit-check` does not call arbitrary live upstream APIs by default. After replacing starter logic, run the Provider locally and record a short evidence note:
57
+ `submit-check` does not call live upstream APIs by default. For smoke scoring,
58
+ run measured smoke so the CLI boots the Provider, checks `/health`, and POSTs
59
+ each operation fixture:
58
60
 
59
61
  ```bash
60
- bun run dev
61
- curl -s http://localhost:3900/health
62
- curl -s -X POST http://localhost:3900/v1/<operation> \
63
- -H 'Content-Type: application/json' \
64
- -d '{"requestId":"req_local_smoke","input":{...},"headers":{}}'
65
-
66
- bun run submit-check -- --smoke-note "GET /health and POST /v1/<operation> passed locally with redacted input."
62
+ bun run submit-check -- --smoke
67
63
  ```
68
64
 
65
+ `APIFUSE__PROVIDER__*` env vars enable live upstream calls. Their absence can
66
+ still produce 7/10 smoke credit when every operation routes and returns a
67
+ structured provider error envelope, but zero schema-valid successes are observed.
69
68
  Never paste real credentials, personal data, account numbers, access tokens, cookies, or unredacted upstream responses into workspace PR comments, chat, or reports.
70
69
 
71
70
  ## Submission evidence checklist
@@ -36,6 +36,9 @@ const requiredPaths = [
36
36
  "bin/apifuse-submit-check.ts",
37
37
  "SUBMISSION.md",
38
38
  "src/cli/create.ts",
39
+ "src/cli/templates/provider/.dockerignore.tpl",
40
+ "src/cli/templates/provider/.gitignore.tpl",
41
+ "src/cli/templates/provider/Dockerfile.tpl",
39
42
  "src/cli/templates/provider/index.ts.tpl",
40
43
  "src/cli/templates/provider/README.md.tpl",
41
44
  "src/cli/templates/provider/meta.ts.tpl",
@@ -45,6 +48,25 @@ const requiredPaths = [
45
48
  "src/cli/templates/provider/operations/ping.ts.tpl",
46
49
  "src/cli/templates/provider/schemas/ping.ts.tpl",
47
50
  "src/cli/templates/provider/upstream/README.md.tpl",
51
+ "dist/cli/templates/provider/.dockerignore.tpl",
52
+ "dist/cli/templates/provider/.gitignore.tpl",
53
+ "dist/cli/templates/provider/Dockerfile.tpl",
54
+ "dist/cli/templates/provider/index.ts.tpl",
55
+ "dist/cli/templates/provider/README.md.tpl",
56
+ "dist/cli/templates/provider/meta.ts.tpl",
57
+ "dist/cli/templates/provider/domain/README.md.tpl",
58
+ "dist/cli/templates/provider/mappers/README.md.tpl",
59
+ "dist/cli/templates/provider/operations/index.ts.tpl",
60
+ "dist/cli/templates/provider/operations/ping.ts.tpl",
61
+ "dist/cli/templates/provider/schemas/ping.ts.tpl",
62
+ "dist/cli/templates/provider/upstream/README.md.tpl",
63
+ "dist/auth-turn/index.js",
64
+ "dist/auth-turn/index.d.ts",
65
+ "dist/auth-turn/auth-turn.v1.schema.json",
66
+ "dist/auth-turn/fixtures/valid/abort.json",
67
+ "dist/auth-turn/fixtures/valid/complete.json",
68
+ "dist/auth-turn/fixtures/invalid/unknown-top-level-field.json",
69
+ "src/auth-turn/auth-turn.v1.schema.json",
48
70
  ];
49
71
  const forbiddenMatches = filePaths.filter(
50
72
  (path) =>