@postman/sdk-config 0.11.0 → 0.13.0

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 (36) hide show
  1. package/README.md +18 -6
  2. package/dist/index.cjs +372 -24
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.js +372 -24
  7. package/dist/index.js.map +1 -1
  8. package/dist/sdk-config/index.cjs +370 -23
  9. package/dist/sdk-config/index.cjs.map +1 -1
  10. package/dist/sdk-config/index.d.cts +1 -1
  11. package/dist/sdk-config/index.d.ts +1 -1
  12. package/dist/sdk-config/index.js +370 -23
  13. package/dist/sdk-config/index.js.map +1 -1
  14. package/dist/sdk-config/v1/index.cjs +370 -23
  15. package/dist/sdk-config/v1/index.cjs.map +1 -1
  16. package/dist/sdk-config/v1/index.d.cts +632 -31
  17. package/dist/sdk-config/v1/index.d.ts +632 -31
  18. package/dist/sdk-config/v1/index.js +370 -23
  19. package/dist/sdk-config/v1/index.js.map +1 -1
  20. package/dist/sdk-config-ir/index.cjs +57 -6
  21. package/dist/sdk-config-ir/index.cjs.map +1 -1
  22. package/dist/sdk-config-ir/index.d.cts +1 -1
  23. package/dist/sdk-config-ir/index.d.ts +1 -1
  24. package/dist/sdk-config-ir/index.js +57 -6
  25. package/dist/sdk-config-ir/index.js.map +1 -1
  26. package/dist/sdk-config-ir/v1/index.cjs +57 -6
  27. package/dist/sdk-config-ir/v1/index.cjs.map +1 -1
  28. package/dist/sdk-config-ir/v1/index.d.cts +211 -4
  29. package/dist/sdk-config-ir/v1/index.d.ts +211 -4
  30. package/dist/sdk-config-ir/v1/index.js +57 -6
  31. package/dist/sdk-config-ir/v1/index.js.map +1 -1
  32. package/dist/{typescript-CsAa1VSy.d.cts → typescript-BFRxjAah.d.cts} +65 -0
  33. package/dist/{typescript-CsAa1VSy.d.ts → typescript-BFRxjAah.d.ts} +65 -0
  34. package/package.json +1 -1
  35. package/src/sdk-config/v1/README.md +32 -11
  36. package/src/sdk-config-ir/v1/README.md +115 -60
@@ -44,6 +44,10 @@ declare const packageConfigSchema: z.ZodObject<{
44
44
  description: z.ZodOptional<z.ZodString>;
45
45
  repository: z.ZodOptional<z.ZodString>;
46
46
  homepage: z.ZodOptional<z.ZodString>;
47
+ bugs: z.ZodOptional<z.ZodObject<{
48
+ url: z.ZodOptional<z.ZodString>;
49
+ email: z.ZodOptional<z.ZodString>;
50
+ }, z.core.$strict>>;
47
51
  documentationUrl: z.ZodOptional<z.ZodString>;
48
52
  authors: z.ZodOptional<z.ZodArray<z.ZodObject<{
49
53
  name: z.ZodString;
@@ -167,6 +171,7 @@ declare const cliDistributionConfigSchema: z.ZodObject<{
167
171
  bucket: z.ZodString;
168
172
  tokenSecretName: z.ZodOptional<z.ZodString>;
169
173
  }, z.core.$strict>>;
174
+ githubAttestations: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean]>>;
170
175
  }, z.core.$strict>;
171
176
  declare const CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE = "CLI_DISTRIBUTION_NON_RELEASE_MODE";
172
177
  interface SdkConfigDiagnostic {
@@ -304,6 +309,7 @@ declare const mcpGenerationConfigSchema: z.ZodObject<{
304
309
  name: z.ZodEnum<{
305
310
  axios: "axios";
306
311
  fetch: "fetch";
312
+ "node-fetch": "node-fetch";
307
313
  }>;
308
314
  }, z.core.$strict>>;
309
315
  packageManager: z.ZodOptional<z.ZodEnum<{
@@ -323,6 +329,35 @@ declare const mcpGenerationConfigSchema: z.ZodObject<{
323
329
  exportClassDefault: z.ZodOptional<z.ZodBoolean>;
324
330
  namespaceExportName: z.ZodOptional<z.ZodString>;
325
331
  consolidateTypeFiles: z.ZodOptional<z.ZodBoolean>;
332
+ formDataSupport: z.ZodOptional<z.ZodEnum<{
333
+ Node16: "Node16";
334
+ Node18: "Node18";
335
+ }>>;
336
+ allowExtraFields: z.ZodOptional<z.ZodBoolean>;
337
+ generateSubpackageExports: z.ZodOptional<z.ZodBoolean>;
338
+ exportAllRequestsAtRoot: z.ZodOptional<z.ZodBoolean>;
339
+ generateEndpointMetadata: z.ZodOptional<z.ZodBoolean>;
340
+ outputEsm: z.ZodOptional<z.ZodBoolean>;
341
+ neverThrowErrors: z.ZodOptional<z.ZodBoolean>;
342
+ includeOtherInUnionTypes: z.ZodOptional<z.ZodBoolean>;
343
+ includeUtilsOnUnionMembers: z.ZodOptional<z.ZodBoolean>;
344
+ omitFernHeaders: z.ZodOptional<z.ZodBoolean>;
345
+ linter: z.ZodOptional<z.ZodEnum<{
346
+ biome: "biome";
347
+ oxlint: "oxlint";
348
+ none: "none";
349
+ }>>;
350
+ formatter: z.ZodOptional<z.ZodEnum<{
351
+ biome: "biome";
352
+ none: "none";
353
+ prettier: "prettier";
354
+ oxfmt: "oxfmt";
355
+ }>>;
356
+ exports: z.ZodOptional<z.ZodType<JsonObject, unknown, z.core.$ZodTypeInternals<JsonObject, unknown>>>;
357
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
358
+ engines: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
359
+ lintStaged: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
360
+ browser: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
326
361
  allowCustomFetcher: z.ZodOptional<z.ZodBoolean>;
327
362
  useBrandedStringAliases: z.ZodOptional<z.ZodBoolean>;
328
363
  useLegacyExports: z.ZodOptional<z.ZodBoolean>;
@@ -493,6 +528,7 @@ declare const typescriptGenerationConfigSchema: z.ZodObject<{
493
528
  name: z.ZodEnum<{
494
529
  axios: "axios";
495
530
  fetch: "fetch";
531
+ "node-fetch": "node-fetch";
496
532
  }>;
497
533
  }, z.core.$strict>>;
498
534
  packageManager: z.ZodOptional<z.ZodEnum<{
@@ -513,6 +549,35 @@ declare const typescriptGenerationConfigSchema: z.ZodObject<{
513
549
  /** Name of the top-level namespace export emitted by Fern-compatible TypeScript SDKs. */
514
550
  namespaceExportName: z.ZodOptional<z.ZodString>;
515
551
  consolidateTypeFiles: z.ZodOptional<z.ZodBoolean>;
552
+ formDataSupport: z.ZodOptional<z.ZodEnum<{
553
+ Node16: "Node16";
554
+ Node18: "Node18";
555
+ }>>;
556
+ allowExtraFields: z.ZodOptional<z.ZodBoolean>;
557
+ generateSubpackageExports: z.ZodOptional<z.ZodBoolean>;
558
+ exportAllRequestsAtRoot: z.ZodOptional<z.ZodBoolean>;
559
+ generateEndpointMetadata: z.ZodOptional<z.ZodBoolean>;
560
+ outputEsm: z.ZodOptional<z.ZodBoolean>;
561
+ neverThrowErrors: z.ZodOptional<z.ZodBoolean>;
562
+ includeOtherInUnionTypes: z.ZodOptional<z.ZodBoolean>;
563
+ includeUtilsOnUnionMembers: z.ZodOptional<z.ZodBoolean>;
564
+ omitFernHeaders: z.ZodOptional<z.ZodBoolean>;
565
+ linter: z.ZodOptional<z.ZodEnum<{
566
+ biome: "biome";
567
+ oxlint: "oxlint";
568
+ none: "none";
569
+ }>>;
570
+ formatter: z.ZodOptional<z.ZodEnum<{
571
+ biome: "biome";
572
+ none: "none";
573
+ prettier: "prettier";
574
+ oxfmt: "oxfmt";
575
+ }>>;
576
+ exports: z.ZodOptional<z.ZodType<JsonObject, unknown, z.core.$ZodTypeInternals<JsonObject, unknown>>>;
577
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
578
+ engines: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
579
+ lintStaged: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
580
+ browser: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
516
581
  allowCustomFetcher: z.ZodOptional<z.ZodBoolean>;
517
582
  useBrandedStringAliases: z.ZodOptional<z.ZodBoolean>;
518
583
  useLegacyExports: z.ZodOptional<z.ZodBoolean>;
@@ -44,6 +44,10 @@ declare const packageConfigSchema: z.ZodObject<{
44
44
  description: z.ZodOptional<z.ZodString>;
45
45
  repository: z.ZodOptional<z.ZodString>;
46
46
  homepage: z.ZodOptional<z.ZodString>;
47
+ bugs: z.ZodOptional<z.ZodObject<{
48
+ url: z.ZodOptional<z.ZodString>;
49
+ email: z.ZodOptional<z.ZodString>;
50
+ }, z.core.$strict>>;
47
51
  documentationUrl: z.ZodOptional<z.ZodString>;
48
52
  authors: z.ZodOptional<z.ZodArray<z.ZodObject<{
49
53
  name: z.ZodString;
@@ -167,6 +171,7 @@ declare const cliDistributionConfigSchema: z.ZodObject<{
167
171
  bucket: z.ZodString;
168
172
  tokenSecretName: z.ZodOptional<z.ZodString>;
169
173
  }, z.core.$strict>>;
174
+ githubAttestations: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"auto">, z.ZodBoolean]>>;
170
175
  }, z.core.$strict>;
171
176
  declare const CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE = "CLI_DISTRIBUTION_NON_RELEASE_MODE";
172
177
  interface SdkConfigDiagnostic {
@@ -304,6 +309,7 @@ declare const mcpGenerationConfigSchema: z.ZodObject<{
304
309
  name: z.ZodEnum<{
305
310
  axios: "axios";
306
311
  fetch: "fetch";
312
+ "node-fetch": "node-fetch";
307
313
  }>;
308
314
  }, z.core.$strict>>;
309
315
  packageManager: z.ZodOptional<z.ZodEnum<{
@@ -323,6 +329,35 @@ declare const mcpGenerationConfigSchema: z.ZodObject<{
323
329
  exportClassDefault: z.ZodOptional<z.ZodBoolean>;
324
330
  namespaceExportName: z.ZodOptional<z.ZodString>;
325
331
  consolidateTypeFiles: z.ZodOptional<z.ZodBoolean>;
332
+ formDataSupport: z.ZodOptional<z.ZodEnum<{
333
+ Node16: "Node16";
334
+ Node18: "Node18";
335
+ }>>;
336
+ allowExtraFields: z.ZodOptional<z.ZodBoolean>;
337
+ generateSubpackageExports: z.ZodOptional<z.ZodBoolean>;
338
+ exportAllRequestsAtRoot: z.ZodOptional<z.ZodBoolean>;
339
+ generateEndpointMetadata: z.ZodOptional<z.ZodBoolean>;
340
+ outputEsm: z.ZodOptional<z.ZodBoolean>;
341
+ neverThrowErrors: z.ZodOptional<z.ZodBoolean>;
342
+ includeOtherInUnionTypes: z.ZodOptional<z.ZodBoolean>;
343
+ includeUtilsOnUnionMembers: z.ZodOptional<z.ZodBoolean>;
344
+ omitFernHeaders: z.ZodOptional<z.ZodBoolean>;
345
+ linter: z.ZodOptional<z.ZodEnum<{
346
+ biome: "biome";
347
+ oxlint: "oxlint";
348
+ none: "none";
349
+ }>>;
350
+ formatter: z.ZodOptional<z.ZodEnum<{
351
+ biome: "biome";
352
+ none: "none";
353
+ prettier: "prettier";
354
+ oxfmt: "oxfmt";
355
+ }>>;
356
+ exports: z.ZodOptional<z.ZodType<JsonObject, unknown, z.core.$ZodTypeInternals<JsonObject, unknown>>>;
357
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
358
+ engines: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
359
+ lintStaged: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
360
+ browser: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
326
361
  allowCustomFetcher: z.ZodOptional<z.ZodBoolean>;
327
362
  useBrandedStringAliases: z.ZodOptional<z.ZodBoolean>;
328
363
  useLegacyExports: z.ZodOptional<z.ZodBoolean>;
@@ -493,6 +528,7 @@ declare const typescriptGenerationConfigSchema: z.ZodObject<{
493
528
  name: z.ZodEnum<{
494
529
  axios: "axios";
495
530
  fetch: "fetch";
531
+ "node-fetch": "node-fetch";
496
532
  }>;
497
533
  }, z.core.$strict>>;
498
534
  packageManager: z.ZodOptional<z.ZodEnum<{
@@ -513,6 +549,35 @@ declare const typescriptGenerationConfigSchema: z.ZodObject<{
513
549
  /** Name of the top-level namespace export emitted by Fern-compatible TypeScript SDKs. */
514
550
  namespaceExportName: z.ZodOptional<z.ZodString>;
515
551
  consolidateTypeFiles: z.ZodOptional<z.ZodBoolean>;
552
+ formDataSupport: z.ZodOptional<z.ZodEnum<{
553
+ Node16: "Node16";
554
+ Node18: "Node18";
555
+ }>>;
556
+ allowExtraFields: z.ZodOptional<z.ZodBoolean>;
557
+ generateSubpackageExports: z.ZodOptional<z.ZodBoolean>;
558
+ exportAllRequestsAtRoot: z.ZodOptional<z.ZodBoolean>;
559
+ generateEndpointMetadata: z.ZodOptional<z.ZodBoolean>;
560
+ outputEsm: z.ZodOptional<z.ZodBoolean>;
561
+ neverThrowErrors: z.ZodOptional<z.ZodBoolean>;
562
+ includeOtherInUnionTypes: z.ZodOptional<z.ZodBoolean>;
563
+ includeUtilsOnUnionMembers: z.ZodOptional<z.ZodBoolean>;
564
+ omitFernHeaders: z.ZodOptional<z.ZodBoolean>;
565
+ linter: z.ZodOptional<z.ZodEnum<{
566
+ biome: "biome";
567
+ oxlint: "oxlint";
568
+ none: "none";
569
+ }>>;
570
+ formatter: z.ZodOptional<z.ZodEnum<{
571
+ biome: "biome";
572
+ none: "none";
573
+ prettier: "prettier";
574
+ oxfmt: "oxfmt";
575
+ }>>;
576
+ exports: z.ZodOptional<z.ZodType<JsonObject, unknown, z.core.$ZodTypeInternals<JsonObject, unknown>>>;
577
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
578
+ engines: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
579
+ lintStaged: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
580
+ browser: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
516
581
  allowCustomFetcher: z.ZodOptional<z.ZodBoolean>;
517
582
  useBrandedStringAliases: z.ZodOptional<z.ZodBoolean>;
518
583
  useLegacyExports: z.ZodOptional<z.ZodBoolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postman/sdk-config",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Shared SDK configuration contracts and transformations for Postman SDK generation",
5
5
  "license": "UNLICENSED",
6
6
  "sideEffects": false,
@@ -211,9 +211,10 @@ properties of the generated language artifact.
211
211
  ## CLI distribution and npm publication
212
212
 
213
213
  A `language: cli` target's own `output` block accepts `distribution`, which publishes the generated
214
- CLI to Homebrew and Scoop from the generated `release.yml` on each tagged release. It exists only on
215
- the `cli` target; root `output` and other languages reject it as an unknown key. A CLI target may
216
- also publish to npm, which the CLI generator uses for its npm launcher packages.
214
+ CLI to Homebrew and Scoop from the generated `release.yml` on each tagged release and controls
215
+ whether that workflow attests build provenance. It exists only on the `cli` target; root `output`
216
+ and other languages reject it as an unknown key. A CLI target may also publish to npm, which the CLI
217
+ generator uses for its npm launcher packages.
217
218
 
218
219
  ```yaml
219
220
  targets:
@@ -238,8 +239,22 @@ targets:
238
239
  scoop:
239
240
  bucket: acme/scoop-bucket
240
241
  tokenSecretName: SCOOP_BUCKET_PAT # optional; overrides githubApp for Scoop
242
+ githubAttestations: auto # optional; auto (generator default), true, or false
241
243
  ```
242
244
 
245
+ ### Build attestations
246
+
247
+ `githubAttestations` controls the generated `actions/attest-build-provenance` step:
248
+
249
+ | Value | Release workflow |
250
+ | ------------------ | ---------------------------------------------------------------- |
251
+ | `auto` (or absent) | Attests only on public repositories |
252
+ | `true` | Always attests (private repositories on GitHub Enterprise Cloud) |
253
+ | `false` | No step or permissions; writes `github-attestations = false` |
254
+
255
+ `githubAttestations` may be the only `distribution` key, for example `{ githubAttestations: false }`
256
+ on a private repository that publishes only to npm. It is a plain value, not a secret name.
257
+
243
258
  ### Secret names, not secret values
244
259
 
245
260
  Every `*SecretName` field (`tokenSecretName`, `appIdSecretName`, `privateKeySecretName`) is the
@@ -265,28 +280,34 @@ The field names differ from the Fern generator's `tokenEnvironmentVariable`, `ap
265
280
  | `distribution` with `files` or `zip` delivery | Error with a fix instruction |
266
281
  | `distribution` on root `output` or a non-`cli` target | Unknown-key error |
267
282
  | `distribution: {}` or `githubApp` without `homebrew`/`scoop` | Error |
283
+ | `githubAttestations` other than `"auto"`, `true`, or `false` | Error |
268
284
  | `githubApp` missing either secret name | Error |
269
285
  | `tap`/`bucket` not `<owner>/<repo>`; `formula` not `^[a-z][a-z0-9-]*$` | Error |
270
286
  | npm publication on a `cli` target without `github` delivery | Error |
271
287
  | `trustedPublishing: true` with `token` | Error |
288
+ | `trustedPublishing: true` with `apiKey` | Error |
272
289
  | `distribution` with GitHub mode `pull-request`, `push`, or `commit` | Warning from `getSdkConfigV1Diagnostics` |
273
290
 
274
291
  Non-release modes are allowed because a customer may push a version tag themselves, but nothing is
275
- published until they do. Zod has no non-fatal issue channel, so warnings come from
276
- `getSdkConfigV1Diagnostics(document)` (and `getSdkConfigIrV1Diagnostics` for IR), which returns the
277
- same `code`/`severity`/`path`/`reason`/`suggestedAction` shape as Fern migration diagnostics.
292
+ published until they do. The warning also applies when `githubAttestations` is the only key, because
293
+ the release workflow it configures runs only on a version tag. Zod has no non-fatal issue channel, so
294
+ warnings come from `getSdkConfigV1Diagnostics(document)` (and `getSdkConfigIrV1Diagnostics` for IR),
295
+ which returns the same `code`/`severity`/`path`/`reason`/`suggestedAction` shape as Fern migration
296
+ diagnostics.
278
297
 
279
- `trustedPublishing` is shared by every npm target. It replaces Fern's `token: OIDC` marker
280
- (`<USE_OIDC>` in the generator) with a typed flag. For CLI npm, omitting `publish` is equivalent to
281
- the generator's `shouldGeneratePublishWorkflow: false`.
298
+ `trustedPublishing` replaces Fern's `token: OIDC` marker (`<USE_OIDC>` in the generator) with a
299
+ typed flag. npm reads it instead of `token`; NuGet and RubyGems read it instead of `apiKey`, which is
300
+ why setting both is an error. For CLI npm, omitting `publish` is equivalent to the generator's
301
+ `shouldGeneratePublishWorkflow: false`.
282
302
 
283
303
  ### Fern migration
284
304
 
285
305
  `mapFernConfigToSdkConfigV1` maps the CLI generator's `config.distribution` onto the target's
286
306
  `output.distribution` when the Fern output is a GitHub repository. Keys are matched by exact name:
287
307
  `appIdSecret` and `privateKeySecret` become `appIdSecretName` and `privateKeySecretName`, and each
288
- channel's `tokenEnvironmentVariable` becomes `tokenSecretName`. Secret names are copied verbatim and
289
- generator defaults are not written. Other keys are reported as `FERN_CONFIG_FIELD_UNSUPPORTED`.
308
+ channel's `tokenEnvironmentVariable` becomes `tokenSecretName`. `githubAttestations` is copied as a
309
+ plain value. Secret names are copied verbatim and generator defaults are not written. Other keys are
310
+ reported as `FERN_CONFIG_FIELD_UNSUPPORTED`.
290
311
 
291
312
  - A distribution this schema rejects, including the legacy no-ops above, is left out and reported
292
313
  as `FERN_CONFIG_VALUE_INVALID` at the legacy path, without the rejected value.
@@ -47,12 +47,13 @@ messages. Valid IR requests route only to the IR bridge and never fall through t
47
47
  - Credentials may be references to externally managed secrets or raw credential/signing values when
48
48
  an integration must carry the material through the normalized config. Raw values are sensitive and
49
49
  must be handled as secrets.
50
- - `output.distribution` (CLI Homebrew/Scoop channels) is valid only when `target.language` is `cli`
51
- and `output.delivery` is `github`. It is accepted on every delivery variant so files/zip produce an
52
- actionable error. Its `*SecretName` fields hold GitHub Actions secret names that the generated
53
- release workflow resolves; they are never credentials, references, or values to resolve, and
54
- `credentialResolution` does not apply to them. `getSdkConfigIrV1Diagnostics` warns when
55
- distribution is combined with a non-release GitHub mode. See the
50
+ - `output.distribution` (CLI Homebrew/Scoop channels and `githubAttestations`) is valid only when
51
+ `target.language` is `cli` and `output.delivery` is `github`. It is accepted on every delivery
52
+ variant so files/zip produce an actionable error. Its `*SecretName` fields hold GitHub Actions
53
+ secret names that the generated release workflow resolves; they are never credentials,
54
+ references, or values to resolve, and `credentialResolution` does not apply to them.
55
+ `getSdkConfigIrV1Diagnostics` warns when distribution is combined with a non-release GitHub mode.
56
+ See the
56
57
  [SDK Config v1 reference](../../sdk-config/v1/README.md#cli-distribution-and-npm-publication).
57
58
  - npm publication is valid for `cli` targets with GitHub delivery only.
58
59
 
@@ -239,6 +240,7 @@ audited on 2026-07-17. Counts guide the initial contract; they are not a permane
239
240
  | `user-agent`, `includePlatformHeaders`, `allowUserAgentAppInfo` | `client.userAgent` | Not in the project snapshot; see below |
240
241
  | `offsetSemantics` | `client.offsetSemantics` | Not in the project snapshot; see below |
241
242
  | `enable-wire-tests`, `enableWireTests`, `generateWireTests` | `generation.wireTests` | 1-15 per language |
243
+ | TypeScript `wireTestsFallbackToAutoGeneratedErrorExamples` | `generation.wireTests.fallbackToGeneratedErrorExamples` | Not in the project snapshot; see below |
242
244
  | WebSocket generation aliases | `generation.webSockets` | 3 TS, 3 Python |
243
245
  | `streamType`, `fileResponseType` | `generation.streams` | 1 TS |
244
246
  | client/exported/environment class aliases | `generation.naming` | 1-28 per language |
@@ -246,7 +248,7 @@ audited on 2026-07-17. Counts guide the initial contract; they are not a permane
246
248
  | namespace/package-prefix aliases | `package.namespace` | 1-30 per language |
247
249
  | output registry package names | `package.packageName` | 5-28 per registry language |
248
250
  | TypeScript `packageJson` / PHP `composerJson` portable metadata | `package.packageName`, `description`, `authors`, and `license` | Portable subset only. |
249
- | TypeScript `fetchSupport: native` | `generation.language.typescript.httpClient.name: "fetch"` | Native only. |
251
+ | TypeScript `fetchSupport` | `generation.language.typescript.httpClient.name`: `native` is `"fetch"`, `node-fetch` is `"node-fetch"` | Native only. |
250
252
  | Python custom `package_name` | `package.moduleName` | 18 |
251
253
  | Python `additional_init_exports` | `generation.language.python.additionalInitExports` | 3 |
252
254
  | Go `module.path` | `package.modulePath` | 3 |
@@ -258,11 +260,54 @@ audited on 2026-07-17. Counts guide the initial contract; they are not a permane
258
260
  | npm package privacy and JSR publication | `output.publish.isPackagePrivate` / `output.publish.publishToJsr` | NPM-only booleans |
259
261
  | registry version and workflow gate | `output.publish.version` / `output.publish.shouldGeneratePublishWorkflow` | Per-registry controls |
260
262
  | registry credentials and environment variables | `output.publish.credentials` / `output.publish.*EnvironmentVariable` | Registry-specific secret values/names |
261
- | trusted publishing / OIDC markers | `output.publish.trustedPublishing` | npm, PyPI, and NuGet |
263
+ | trusted publishing / OIDC markers | `output.publish.trustedPublishing` | npm, PyPI, NuGet, and RubyGems |
262
264
  | Maven coordinate and signing material/env vars | `output.publish.coordinate` / `output.publish.signature` / `output.publish.signatureEnvironmentVariables` | Maven-specific |
263
265
  | Fern README config | `docs.readme` | 12 API names; 11 disabled-section configs |
264
266
  | `customReadmeSections` | `docs.readme.customSections` | Not in the project snapshot; see below |
265
267
  | `includeApiReference` | `docs.includeApiReference` | 10 TS |
268
+ | TypeScript `formDataSupport` | `generation.language.typescript.formDataSupport` | Not in the project snapshot; see below |
269
+ | TypeScript `allowExtraFields` | `generation.language.typescript.allowExtraFields` | Not in the project snapshot; see below |
270
+ | TypeScript `generateSubpackageExports` | `generation.language.typescript.generateSubpackageExports` | Not in the project snapshot; see below |
271
+
272
+ The TypeScript options below are copied by the mapper only when they have the declared type, and
273
+ anything else is reported in `compatibility.unsupportedFields`. Omitted options stay omitted; the
274
+ generator applies Fern's defaults. Each maps to the field of the same name in
275
+ `generation.language.typescript` unless noted. The mapper reads them for the TypeScript SDK generator
276
+ only. The MCP generator's converter has never read them, so an MCP config that sets one still
277
+ reports it in `compatibility.unsupportedFields` (`fetchSupport: node-fetch` included; `native` still
278
+ maps).
279
+
280
+ | Fern option | Values | Fern default | Maps to |
281
+ | -------------------------------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------- |
282
+ | `formDataSupport` | `Node16`, `Node18` | `Node18` | |
283
+ | `allowExtraFields` | boolean | `false` | |
284
+ | `generateSubpackageExports` | boolean | `true` | |
285
+ | `exportAllRequestsAtRoot`, `generateEndpointMetadata`, `outputEsm`, `neverThrowErrors` | boolean | `false` | |
286
+ | `includeOtherInUnionTypes`, `includeUtilsOnUnionMembers`, `omitFernHeaders` | boolean | `false` | |
287
+ | `linter` | `biome`, `oxlint`, `none` | `biome` | |
288
+ | `formatter` | `prettier`, `biome`, `oxfmt`, `none` | `biome` | |
289
+ | `fetchSupport` | `native`, `node-fetch` | `native` | `httpClient.name` (`fetch`, `node-fetch`) |
290
+ | `wireTestsFallbackToAutoGeneratedErrorExamples` | boolean | `true` | `generation.wireTests.fallbackToGeneratedErrorExamples` |
291
+ | `packageJson.exports` | object keyed by subpath | generated map | `exports` |
292
+ | `packageJson.scripts` | object of name to command | generated scripts | `scripts` (`{ name, command }` list) |
293
+ | `packageJson.files` | string list | generated list | `files` |
294
+ | `packageJson.engines` | object of name to range | generated (`node >=18.0.0`) | `engines` |
295
+ | `packageJson["lint-staged"]` | object of glob to commands | none | `lintStaged` |
296
+ | `packageJson.browser` | object of module to `false` or path | generated (`fs`, `os`, `path`, `stream`, `crypto` set to `false`) | `browser` |
297
+ | `packageJson.bugs` | URL string, or `{ url, email }` | none | `package.bugs` |
298
+ | `packageJson.repository` | URL string, or `{ type: "git", url }` | none | `package.repository` |
299
+
300
+ `generation.wireTests` requires `enabled`, and Fern generates wire tests unless told not to, so a
301
+ config that sets only the fallback option maps to `{ enabled: true, fallbackToGeneratedErrorExamples }`.
302
+ The `packageJson` keys above are the ones that have a typed home. For `engines` and `browser`, Fern merges the
303
+ customer's entries into the generated object key by key, so a customer `node` range replaces the generated one and a
304
+ customer `browser` entry is added to the generated ones. Fern merges the values you set over
305
+ the generated `package.json`; `files` entries come first, and `exports` subpaths replace the
306
+ generated ones one subpath at a time (Fern's default `shallow` merge; `packageJsonMergeStrategy` is
307
+ not carried). A key outside this list, a repository `directory`, or a repository `type` other than
308
+ `git` is still reported as unsupported.
309
+ `outputEsm` marks the package as an ES module while still shipping its CommonJS build; `esmOnly`
310
+ drops the CommonJS build.
266
311
 
267
312
  The Rust language config was added after the initial audit. That audit compared existing Fern
268
313
  _customer projects_, which surfaced no Rust-specific options; comparing the Fern Rust generator's
@@ -304,28 +349,29 @@ normalized contract.
304
349
  These settings remain under `source.apiImportSettings` because they affect spec conversion rather
305
350
  than generated-language presentation.
306
351
 
307
- | Fern setting | Normalized field | Observed projects |
308
- | ----------------------------------------------------------- | ------------------------------------ | --------------------------------------: |
309
- | `respect-nullable-schemas` | `respectNullableSchemas` | 10 |
310
- | `title-as-schema-name` | `titleAsSchemaName` | 16 |
311
- | `ignore-tags` | `ignoreTags` | Not in the project snapshot; see below. |
312
- | `disambiguate-request-names` | `disambiguateRequestNames` | Not in the project snapshot; see below. |
313
- | `respect-readonly-schemas` | `respectReadonlySchemas` | Not in the project snapshot; see below. |
314
- | `unions: v1`, `prefer-undiscriminated-unions-with-literals` | `discriminatedUnionV2` | Not in the project snapshot; see below. |
315
- | `prefer-undiscriminated-unions-with-literals` | `undiscriminatedUnionsWithLiterals` | Not in the project snapshot; see below. |
316
- | `inline-all-of-schemas` | `inlineAllOfSchemas` | Not in the project snapshot; see below. |
317
- | `resolve-schema-collisions` | `resolveSchemaCollisions` | Not in the project snapshot; see below. |
318
- | `message-naming` | `asyncApiMessageNaming` | Not in the project snapshot; see below. |
319
- | `coerce-enums-to-literals` | `coerceEnumsToLiterals` | 14 |
320
- | `idiomatic-request-names` | `idiomaticRequestNames` | 12 |
321
- | `wrap-references-to-nullable-in-optional` | `wrapReferencesToNullableInOptional` | 9 |
322
- | `coerce-optional-schemas-to-nullable` | `coerceOptionalSchemasToNullable` | 9 |
323
- | `object-query-parameters` | `objectQueryParameters` | 9 |
324
- | `only-include-referenced-schemas` | `onlyIncludeReferencedSchemas` | 4 |
325
- | `group-multi-api-environments` | `groupMultiApiEnvironments` | 2 |
326
- | `path-parameter-order` | `pathParameterOrder` | 2 |
327
- | `type-dates-as-strings` | `typeDatesAsStrings` | 12 |
328
- | `default-integer-format` | `defaultIntegerFormat` | Importer defaults to `int32`. |
352
+ | Fern setting | Normalized field | Observed projects |
353
+ | ----------------------------------------------------------- | --------------------------------------- | --------------------------------------: |
354
+ | `respect-nullable-schemas` | `respectNullableSchemas` | 10 |
355
+ | `title-as-schema-name` | `titleAsSchemaName` | 16 |
356
+ | `ignore-tags` | `ignoreTags` | Not in the project snapshot; see below. |
357
+ | `disambiguate-request-names` | `disambiguateRequestNames` | Not in the project snapshot; see below. |
358
+ | `respect-readonly-schemas` | `respectReadonlySchemas` | Not in the project snapshot; see below. |
359
+ | `unions: v1`, `prefer-undiscriminated-unions-with-literals` | `discriminatedUnionV2` | Not in the project snapshot; see below. |
360
+ | `prefer-undiscriminated-unions-with-literals` | `undiscriminatedUnionsWithLiterals` | Not in the project snapshot; see below. |
361
+ | `inline-all-of-schemas` | `inlineAllOfSchemas` | Not in the project snapshot; see below. |
362
+ | `infer-discriminated-union-base-properties` | `inferDiscriminatedUnionBaseProperties` | Not in the project snapshot; see below. |
363
+ | `resolve-schema-collisions` | `resolveSchemaCollisions` | Not in the project snapshot; see below. |
364
+ | `message-naming` | `asyncApiMessageNaming` | Not in the project snapshot; see below. |
365
+ | `coerce-enums-to-literals` | `coerceEnumsToLiterals` | 14 |
366
+ | `idiomatic-request-names` | `idiomaticRequestNames` | 12 |
367
+ | `wrap-references-to-nullable-in-optional` | `wrapReferencesToNullableInOptional` | 9 |
368
+ | `coerce-optional-schemas-to-nullable` | `coerceOptionalSchemasToNullable` | 9 |
369
+ | `object-query-parameters` | `objectQueryParameters` | 9 |
370
+ | `only-include-referenced-schemas` | `onlyIncludeReferencedSchemas` | 4 |
371
+ | `group-multi-api-environments` | `groupMultiApiEnvironments` | 2 |
372
+ | `path-parameter-order` | `pathParameterOrder` | 2 |
373
+ | `type-dates-as-strings` | `typeDatesAsStrings` | 12 |
374
+ | `default-integer-format` | `defaultIntegerFormat` | Importer defaults to `int32`. |
329
375
 
330
376
  `ignoreTags` and `disambiguateRequestNames` postdate the project snapshot. Twilio declares both
331
377
  across its namespaced API specs. They stay undefaulted so omission remains distinguishable from an
@@ -348,6 +394,11 @@ fields above: `respectReadonlySchemas` changes which properties an imported sche
348
394
  `discriminatedUnionV2` changes how union variants are converted, so an absent value must leave an
349
395
  existing SDK's shapes alone rather than assert one.
350
396
 
397
+ `inferDiscriminatedUnionBaseProperties` postdates the snapshot too. Auth0's Management API sets it,
398
+ and Fern then lifts every property all of a discriminated `oneOf`'s mapped variants declare with an
399
+ equal schema onto the union itself — `ConnectionResponseContent::ad(string $id, string $displayName,
400
+ ...)` in its PHP SDK. It stays undefaulted: absent must leave a union's shape alone.
401
+
351
402
  `inlineAllOfSchemas`, `resolveSchemaCollisions`, and `asyncApiMessageNaming` complete the retained
352
403
  import settings with observed customer use. Each is refused today whenever it differs from the
353
404
  importer default, which blocks the declaring customer from a post-cutover generator version.
@@ -359,19 +410,19 @@ project's OpenAPI specs carry it too and are refused for it.
359
410
 
360
411
  Only options that remain language-specific stay in `generation.language`.
361
412
 
362
- | Language | Fern fields retained in language config | Shared mappings lifted out |
363
- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
364
- | TypeScript | `packageManager` (1), `testFramework` (2), `namespaceExportName`, `allowCustomFetcher` (13), branded aliases (1), legacy exports (1), `useBigInt`, and positive `serdeLayer` from `noSerdeLayer` (8) | Namespace, validation, inline types, dependencies, wire tests, streams, WebSockets, pager/client names |
365
- | Python | Python/Pydantic versions, client filenames, model switches, TypedDict requests, redirect/chunk/recursion compatibility, and package extras | Package/module names, enum form, extra fields, response validation, request style, dependencies, timeout, layout, wire tests, WebSockets |
366
- | Java/Kotlin | Package layout (3), local dates (2), optional-nullable collapse (2), Gradle settings (7), and JVM async-client style | Maven identity, namespace, names, forward-compatible enums, inline properties, dependencies, pager, wire tests |
367
- | Go | Legacy complex models, union version (3), legacy client options (1), and the fern root-client constructor name | Module/package identity, client name, environments, smart casing, inline properties, pager, wire tests |
368
- | C# | Optional wrapper, simplified dictionaries (1), explicit namespaces (7), core namespace behavior (1), exception handler (5), and the experimental explicit-nullable-optional switch | NuGet identity, namespace, class/error names, pager, wire tests |
369
- | PHP | Property access (2) and generated client interfaces (1) | Composer identity, namespace, client/pager names, request style, dependencies, wire tests, idempotency keys, User-Agent, offset semantics |
370
- | Ruby | Require paths (2) | Gem identity, client name, dependencies, pager, wire tests |
371
- | Rust | Datetime representation, initialism casing, and Cargo features/default-features | Crate identity, client name, and package metadata use shared fields. |
372
- | Swift | Module name and the nullable-as-optional collapse | Client, environment and error naming use shared fields. |
373
- | CLI | Pagination parameter names, the `skills` boolean, and the typed CLI settings below | Go module and package identity use `package`. |
374
- | MCP | Server identity, availability exclusions, tool filters and named toolsets, plus the TypeScript options | npm package identity, client and serialization behavior |
413
+ | Language | Fern fields retained in language config | Shared mappings lifted out |
414
+ | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
415
+ | TypeScript | `packageManager` (1), `testFramework` (2), `namespaceExportName`, `allowCustomFetcher` (13), branded aliases (1), legacy exports (1), `formDataSupport`, `allowExtraFields`, `generateSubpackageExports`, `exportAllRequestsAtRoot`, `generateEndpointMetadata`, `outputEsm`, `neverThrowErrors`, `includeOtherInUnionTypes`, `includeUtilsOnUnionMembers`, `omitFernHeaders`, `linter`, `formatter`, `useBigInt`, and positive `serdeLayer` from `noSerdeLayer` (8) | Namespace, validation, inline types, dependencies, wire tests, streams, WebSockets, pager/client names |
416
+ | Python | Python/Pydantic versions, client filenames, model switches, TypedDict requests, redirect/chunk/recursion compatibility, and package extras | Package/module names, enum form, extra fields, response validation, request style, dependencies, timeout, layout, wire tests, WebSockets |
417
+ | Java/Kotlin | Package layout (3), local dates (2), optional-nullable collapse (2), Gradle settings (7), and JVM async-client style | Maven identity, namespace, names, forward-compatible enums, inline properties, dependencies, pager, wire tests |
418
+ | Go | Legacy complex models, union version (3), legacy client options (1), and the fern root-client constructor name | Module/package identity, client name, environments, smart casing, inline properties, pager, wire tests |
419
+ | C# | Optional wrapper, simplified dictionaries (1), explicit namespaces (7), core namespace behavior (1), exception handler (5), and the experimental explicit-nullable-optional switch | NuGet identity, namespace, class/error names, pager, wire tests |
420
+ | PHP | Property access (2) and generated client interfaces (1) | Composer identity, namespace, client/pager names, request style, dependencies, wire tests, idempotency keys, User-Agent, offset semantics |
421
+ | Ruby | Require paths (2) | Gem identity, client name, dependencies, pager, wire tests |
422
+ | Rust | Datetime representation, initialism casing, and Cargo features/default-features | Crate identity, client name, and package metadata use shared fields. |
423
+ | Swift | Module name and the nullable-as-optional collapse | Client, environment and error naming use shared fields. |
424
+ | CLI | Pagination parameter names, the `skills` boolean, and the typed CLI settings below | Go module and package identity use `package`. |
425
+ | MCP | Server identity, availability exclusions, tool filters and named toolsets, plus the TypeScript options | npm package identity, client and serialization behavior |
375
426
 
376
427
  `generation.language.cli` also accepts the typed CLI settings `binaryName`, `customCommands`,
377
428
  `rootGroup`, `profiles`, `splitTypeCrates`, and `userAgentSuffixFlag`. Their shapes, validation,
@@ -400,18 +451,22 @@ the migration.
400
451
 
401
452
  ### Removed after finding no customer use and no sdk-gen-core equivalent
402
453
 
403
- - Common Fern generation: the omit platform-header override (`omitFernHeaders`). Output-profile
404
- defaults own this compatibility behavior instead of a second permanent switch. The include side
405
- was re-added as `client.userAgent.includePlatformInfo` once the Fern PHP generator documented it.
454
+ - Common Fern generation: the omit platform-header override (`omitFernHeaders`) was removed from the
455
+ shared blocks, and Output-profile defaults own that compatibility behavior. The include side was
456
+ re-added as `client.userAgent.includePlatformInfo` once the Fern PHP generator documented it. The
457
+ TypeScript `omitFernHeaders` option is carried as its own TypeScript setting because real
458
+ TypeScript configs set it.
406
459
  - Source import: optional-additional-properties defaults, environment grouping strategies,
407
460
  discriminant removal, forward-compatible inference, default environment inference, const
408
461
  coercion, endpoint filters, example-depth controls, alias resolution, single-schema oneOf
409
462
  preservation, read-variant responses, binary-response import coercion, form encoding defaults,
410
463
  additional-properties defaults, and discriminated-union inference.
411
- - TypeScript: linter/formatter selection, subpackage exports, and endpoint metadata. (Consolidated
412
- type files was re-added as `consolidateTypeFiles` in `typescriptGenerationConfigSchema` after
413
- real customer use turned up — `intercom`/`auth0_fern` both set it — so this list entry no longer
414
- applies to it.)
464
+ - TypeScript: the options once removed here were re-added as real configs turned up. Consolidated
465
+ type files is `consolidateTypeFiles` (`intercom` and `auth0_fern` set it), subpackage exports is
466
+ `generateSubpackageExports` (`auth0_fern`, `auth0_teams`, `corti_latest`, and `merge` set it),
467
+ and linter/formatter selection and endpoint metadata are `linter`, `formatter`, and
468
+ `generateEndpointMetadata` (`auth0_fern` and `auth0_teams` set them). None of these entries
469
+ applies to those options any more.
415
470
  - Python: ORM/smart-union/coercion/wrapped-alias/positional-constructor/inheritance/validator
416
471
  switches, flattened union bodies, lazy imports, and custom transport.
417
472
  - Java/JVM: JSON include, required-builder checks, public/extensible constructors, unknown-as-node,
@@ -425,16 +480,16 @@ the migration.
425
480
 
426
481
  ### Observed but deliberately deferred as bespoke or low-use
427
482
 
428
- | Legacy configuration | Observed projects | Reason |
429
- | ----------------------------------------------------------- | ----------------: | ------------------------------------------------------------------------ |
430
- | TypeScript arbitrary `packageJson` exports/scripts | 2 | Open-ended manifest rewriting conflicts with the typed package contract. |
431
- | TypeScript `outputEsm` and form-data runtime | 1-2 | Runtime-specific and not required by sdk-gen-core today. |
432
- | Python excluded `__init__` exports | 6 | File-layout customization with significant generator coupling. |
433
- | Python improved imports and file-upload-only TypedDict mode | 1-3 | Experimental or narrow compatibility behavior. |
434
- | Java custom Gradle plugins / include-wrapper | 1 | Arbitrary build-file injection or one-customer behavior. |
435
- | C# experimental fully qualified/version namespaces | 1 | Experimental one-customer behavior. |
436
- | PHP arbitrary Composer autoload files | 2 | Open-ended manifest rewriting; typed dependencies remain supported. |
437
- | Ruby flattened module structure | 1 | One-customer layout behavior. |
483
+ | Legacy configuration | Observed projects | Reason |
484
+ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------: | ------------------------------------------------------------------------------------------------------------- |
485
+ | TypeScript `packageJson` keys without a typed field (everything but `exports`, `scripts`, `files`, `engines`, `lint-staged`, `browser`, `bugs`, `repository` and the portable metadata) | 2 | Open-ended manifest rewriting conflicts with the typed package contract. |
486
+ | README `exampleStyle` | 1 | Only the Fern Java generator reads it and no Postman generator does, so a typed field would have no consumer. |
487
+ | Python excluded `__init__` exports | 6 | File-layout customization with significant generator coupling. |
488
+ | Python improved imports and file-upload-only TypedDict mode | 1-3 | Experimental or narrow compatibility behavior. |
489
+ | Java custom Gradle plugins / include-wrapper | 1 | Arbitrary build-file injection or one-customer behavior. |
490
+ | C# experimental fully qualified/version namespaces | 1 | Experimental one-customer behavior. |
491
+ | PHP arbitrary Composer autoload files | 2 | Open-ended manifest rewriting; typed dependencies remain supported. |
492
+ | Ruby flattened module structure | 1 | One-customer layout behavior. |
438
493
 
439
494
  Adding one of these fields later is additive. Retaining every historical generator flag now would
440
495
  make v1 expensive to implement and would turn temporary compatibility behavior into a permanent