@postman/sdk-config 0.12.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 +158 -15
  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 +158 -15
  7. package/dist/index.js.map +1 -1
  8. package/dist/sdk-config/index.cjs +156 -14
  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 +156 -14
  13. package/dist/sdk-config/index.js.map +1 -1
  14. package/dist/sdk-config/v1/index.cjs +156 -14
  15. package/dist/sdk-config/v1/index.cjs.map +1 -1
  16. package/dist/sdk-config/v1/index.d.cts +400 -31
  17. package/dist/sdk-config/v1/index.d.ts +400 -31
  18. package/dist/sdk-config/v1/index.js +156 -14
  19. package/dist/sdk-config/v1/index.js.map +1 -1
  20. package/dist/sdk-config-ir/index.cjs +18 -5
  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 +18 -5
  25. package/dist/sdk-config-ir/index.js.map +1 -1
  26. package/dist/sdk-config-ir/v1/index.cjs +18 -5
  27. package/dist/sdk-config-ir/v1/index.cjs.map +1 -1
  28. package/dist/sdk-config-ir/v1/index.d.cts +27 -4
  29. package/dist/sdk-config-ir/v1/index.d.ts +27 -4
  30. package/dist/sdk-config-ir/v1/index.js +18 -5
  31. package/dist/sdk-config-ir/v1/index.js.map +1 -1
  32. package/dist/{typescript-Byhn4MqL.d.cts → typescript-BFRxjAah.d.cts} +1 -0
  33. package/dist/{typescript-Byhn4MqL.d.ts → typescript-BFRxjAah.d.ts} +1 -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 +36 -29
package/README.md CHANGED
@@ -75,15 +75,27 @@ if (!result.success) {
75
75
  SDK Config objects are strict. Unknown fields, duplicate language targets, incompatible package
76
76
  publication settings, and non-exact generator versions are rejected. npm and crates use
77
77
  `output.publish.token`, PyPI and Maven use flat `username` and `password` fields, and Maven may also
78
- use a complete `signature` object. Configure these fields with environment expressions such as
78
+ use a complete `signature` object. NuGet and RubyGems use `output.publish.apiKey` to name the
79
+ repository secret that the generated release workflow reads the API key from, such as
80
+ `${MY_NUGET_KEY}`. That value is a secret name, never the key itself. Configure these fields with
81
+ environment expressions such as
79
82
  `${NPM_TOKEN}` rather than literal credentials. Clients must resolve and transport credentials using
80
83
  a dedicated secret channel and remove them from generation payloads, logs, and stored artifacts.
81
- Fern migration preserves a credential only when the raw `generators.yml` value is exactly an
82
- environment expression; normalized, resolved, or literal values are omitted with a warning.
84
+ NuGet and RubyGems may instead set `output.publish.trustedPublishing`, which authenticates the
85
+ release workflow with a short-lived OIDC token the registry verifies against the repository. There is
86
+ then no API key secret to name, so `apiKey` and `trustedPublishing` cannot both be set.
83
87
 
84
- CLI targets may also declare `output.distribution` (Homebrew and Scoop channels) and npm
85
- publication. Distribution credentials are GitHub Actions secret **names**, not environment
86
- expressions: clients must not resolve them or send them through the publish-credential channel. See
88
+ Fern migration preserves a credential only when the raw `generators.yml` value is exactly an
89
+ environment expression; normalized, resolved, or literal values are omitted with a warning. A GitHub
90
+ NuGet target whose `api-key` names no secret gets `${NUGET_API_TOKEN}`, the secret Fern's generated
91
+ workflow reads in that case, and no warning, because publishing keeps working unchanged. Fern states
92
+ trusted publishing through the same `api-key` field, as `OIDC` or `<USE_OIDC>`, and migration maps
93
+ either to `trustedPublishing: true` rather than dropping it.
94
+
95
+ CLI targets may also declare `output.distribution` (Homebrew and Scoop channels and
96
+ `githubAttestations` for release build provenance) and npm publication. Distribution credentials are
97
+ GitHub Actions secret **names**, not environment expressions: clients must not resolve them or send
98
+ them through the publish-credential channel. See
87
99
  [CLI distribution and npm publication](src/sdk-config/v1/README.md#cli-distribution-and-npm-publication).
88
100
  Call `getSdkConfigV1Diagnostics` after validation to surface non-fatal warnings.
89
101
 
package/dist/index.cjs CHANGED
@@ -514,7 +514,10 @@ var cliDistributionConfigSchema = zod.z.strictObject({
514
514
  "A GitHub App used to mint short-lived tokens for every channel without its own tokenSecretName."
515
515
  ),
516
516
  homebrew: cliDistributionHomebrewSchema.optional().describe("Publishes a Homebrew formula to a tap repository on each tagged release."),
517
- scoop: cliDistributionScoopSchema.optional().describe("Publishes a Scoop manifest to a bucket repository on each tagged release.")
517
+ scoop: cliDistributionScoopSchema.optional().describe("Publishes a Scoop manifest to a bucket repository on each tagged release."),
518
+ githubAttestations: zod.z.union([zod.z.literal("auto"), zod.z.boolean()], { error: 'must be "auto", true, or false' }).optional().describe(
519
+ 'Whether the generated release workflow attests build provenance. "auto" (the generator default) attests only on public repositories; true always attests, for private repositories on GitHub Enterprise Cloud; false omits the attestation step and its permissions.'
520
+ )
518
521
  }).superRefine((distribution, context) => {
519
522
  if (distribution.homebrew !== void 0 || distribution.scoop !== void 0) {
520
523
  return;
@@ -527,6 +530,9 @@ var cliDistributionConfigSchema = zod.z.strictObject({
527
530
  });
528
531
  return;
529
532
  }
533
+ if (distribution.githubAttestations !== void 0) {
534
+ return;
535
+ }
530
536
  context.addIssue({
531
537
  code: "custom",
532
538
  message: "distribution must configure at least one channel: homebrew or scoop"
@@ -538,14 +544,17 @@ var CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE = "CLI_DISTRIBUTION_NON_RELEASE_MODE"
538
544
  var nonReleaseGithubModes = /* @__PURE__ */ new Set(["pull-request", "push", "commit"]);
539
545
  function cliDistributionModeDiagnostic(output, outputPath) {
540
546
  const mode = output?.github?.mode;
541
- if (output?.distribution === void 0 || mode === void 0 || !nonReleaseGithubModes.has(mode)) {
547
+ const distribution = output?.distribution;
548
+ if (distribution === void 0 || mode === void 0 || !nonReleaseGithubModes.has(mode)) {
542
549
  return void 0;
543
550
  }
551
+ const hasChannel = distribution.homebrew !== void 0 || distribution.scoop !== void 0;
552
+ const consequence = hasChannel ? "Homebrew and Scoop publish only after a semantic-version tag is pushed to the repository." : "the release workflow, including its githubAttestations setting, runs only after a semantic-version tag is pushed to the repository.";
544
553
  return {
545
554
  code: CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE,
546
555
  severity: "warning",
547
556
  path: [...outputPath, "github", "mode"],
548
- reason: `GitHub mode "${mode}" does not create a release tag, so Homebrew and Scoop publish only after a semantic-version tag is pushed to the repository.`,
557
+ reason: `GitHub mode "${mode}" does not create a release tag, so ${consequence}`,
549
558
  suggestedAction: 'Use mode "release" or "commit-and-release", or push a version tag after merging generated changes.'
550
559
  };
551
560
  }
@@ -980,6 +989,7 @@ var DISTRIBUTION_KEYS = {
980
989
  homebrew: { tap: "tap", formula: "formula", tokenEnvironmentVariable: "tokenSecretName" },
981
990
  scoop: { bucket: "bucket", tokenEnvironmentVariable: "tokenSecretName" }
982
991
  };
992
+ var DISTRIBUTION_SCALAR_KEYS = ["githubAttestations"];
983
993
  function mapCliDistribution(config, state, basePath, targetIndex) {
984
994
  if (!Object.hasOwn(config, "distribution")) return;
985
995
  const raw = config.distribution;
@@ -1026,6 +1036,11 @@ function translateDistribution(distribution, path) {
1026
1036
  }
1027
1037
  value[block] = translatedBlock;
1028
1038
  }
1039
+ for (const key of DISTRIBUTION_SCALAR_KEYS) {
1040
+ if (!Object.hasOwn(distribution, key)) continue;
1041
+ value[key] = distribution[key];
1042
+ consumedPaths.push([...path, key]);
1043
+ }
1029
1044
  return { value, consumedPaths, legacyKeys };
1030
1045
  }
1031
1046
  function invalidDistributionDiagnostic(issue, path, legacyKeys, targetIndex) {
@@ -1165,6 +1180,7 @@ function mapOutput(generator, language, index) {
1165
1180
  output.publishV2,
1166
1181
  rawOutput,
1167
1182
  language,
1183
+ "zip",
1168
1184
  [...outputPath, "publishV2"],
1169
1185
  state,
1170
1186
  index
@@ -1186,6 +1202,7 @@ function mapOutput(generator, language, index) {
1186
1202
  output.registryOverrides,
1187
1203
  rawOutput,
1188
1204
  language,
1205
+ "zip",
1189
1206
  [...outputPath, "registryOverrides"],
1190
1207
  state,
1191
1208
  index
@@ -1213,7 +1230,14 @@ function mapOutput(generator, language, index) {
1213
1230
  }
1214
1231
  }
1215
1232
  function sanitizeNormalizedOutput(output, rawOutput, state, index) {
1216
- const publish = output.publish ? sanitizePublishConfig(output.publish, output.publish, rawOutput, state, index) : void 0;
1233
+ const publish = output.publish ? sanitizePublishConfig(
1234
+ output.publish,
1235
+ output.publish,
1236
+ rawOutput,
1237
+ output.delivery,
1238
+ state,
1239
+ index
1240
+ ) : void 0;
1217
1241
  const publishShape = publish ? { publish } : {};
1218
1242
  if (output.delivery !== "github") return { ...output, ...publishShape };
1219
1243
  const { credentials, ...github } = output.github;
@@ -1240,7 +1264,15 @@ function githubOutput(value, publishInfo, rawOutput, language, sourcePath, state
1240
1264
  );
1241
1265
  consume(state, [...sourcePath, "owner"]);
1242
1266
  consume(state, [...sourcePath, "repo"]);
1243
- const publication = publishInfo ? mapPublication(publishInfo, rawOutput, language, [...sourcePath, "publishInfo"], state, index) : void 0;
1267
+ const publication = publishInfo ? mapPublication(
1268
+ publishInfo,
1269
+ rawOutput,
1270
+ language,
1271
+ "github",
1272
+ [...sourcePath, "publishInfo"],
1273
+ state,
1274
+ index
1275
+ ) : void 0;
1244
1276
  const type = stringValue(value.type);
1245
1277
  const licensePackage = mapGithubLicense(value.license, [...sourcePath, "license"], state);
1246
1278
  const reviewers = mapReviewers(value.reviewers, [...sourcePath, "reviewers"], state);
@@ -1333,7 +1365,7 @@ function reviewerNames(value, expectedType, sourcePath, state) {
1333
1365
  });
1334
1366
  return names.length ? names : void 0;
1335
1367
  }
1336
- function mapPublication(value, rawOutput, language, sourcePath, state, index) {
1368
+ function mapPublication(value, rawOutput, language, delivery, sourcePath, state, index) {
1337
1369
  if (!isObject(value))
1338
1370
  fail(
1339
1371
  "FERN_PUBLICATION_INVALID",
@@ -1354,6 +1386,7 @@ function mapPublication(value, rawOutput, language, sourcePath, state, index) {
1354
1386
  compact({ registry, url: registryUrl }),
1355
1387
  nested,
1356
1388
  rawOutput,
1389
+ delivery,
1357
1390
  state,
1358
1391
  index
1359
1392
  );
@@ -1374,7 +1407,7 @@ function mapPublication(value, rawOutput, language, sourcePath, state, index) {
1374
1407
  ...packageName || Object.keys(metadata).length ? { package: { ...optional("packageName", packageName), ...metadata } } : {}
1375
1408
  };
1376
1409
  }
1377
- function sanitizePublishConfig(publish, resolvedPublication, rawOutput, state, index) {
1410
+ function sanitizePublishConfig(publish, resolvedPublication, rawOutput, delivery, state, index) {
1378
1411
  const rawPublication = rawOutput?.location === publish.registry ? rawOutput : void 0;
1379
1412
  const rawPath = ["group", "generators", index, "output"];
1380
1413
  if (publish.registry === "npm" || publish.registry === "crates") {
@@ -1470,6 +1503,33 @@ function sanitizePublishConfig(publish, resolvedPublication, rawOutput, state, i
1470
1503
  signature
1471
1504
  });
1472
1505
  }
1506
+ if (publish.registry === "nuget" || publish.registry === "rubygems") {
1507
+ const apiKey = mapApiKeyExpression(
1508
+ publish.registry,
1509
+ rawPublication,
1510
+ resolvedPublication,
1511
+ rawPath,
1512
+ state,
1513
+ index,
1514
+ fernDefaultApiKey(publish.registry, rawOutput, delivery)
1515
+ );
1516
+ warnForUnexpectedCredentialFields(
1517
+ rawPublication,
1518
+ resolvedPublication,
1519
+ ["apiKey"],
1520
+ rawPath,
1521
+ state,
1522
+ index
1523
+ );
1524
+ return compact({
1525
+ registry: publish.registry,
1526
+ url: publish.url,
1527
+ releaseBranch: publish.releaseBranch,
1528
+ tolerateRepublish: publish.tolerateRepublish,
1529
+ apiKey,
1530
+ trustedPublishing: usesTrustedPublishing(rawPublication) || void 0
1531
+ });
1532
+ }
1473
1533
  warnForUnrepresentableCredentials(rawPublication, resolvedPublication, rawPath, state, index);
1474
1534
  return compact({
1475
1535
  registry: publish.registry,
@@ -1478,11 +1538,19 @@ function sanitizePublishConfig(publish, resolvedPublication, rawOutput, state, i
1478
1538
  tolerateRepublish: publish.tolerateRepublish
1479
1539
  });
1480
1540
  }
1481
- function mapLegacyPublication(value, rawOutput, language, sourcePath, state, index) {
1541
+ function mapLegacyPublication(value, rawOutput, language, delivery, sourcePath, state, index) {
1482
1542
  const registry = defaultRegistry(language, sourcePath, index);
1483
1543
  const overrides = isObject(value) ? value : {};
1484
1544
  const override = isObject(overrides[registry]) ? overrides[registry] : {};
1485
- return mapPublication(override, rawOutput, language, [...sourcePath, registry], state, index);
1545
+ return mapPublication(
1546
+ override,
1547
+ rawOutput,
1548
+ language,
1549
+ delivery,
1550
+ [...sourcePath, registry],
1551
+ state,
1552
+ index
1553
+ );
1486
1554
  }
1487
1555
  function mapCredentialExpression(rawPublication, resolvedPublication, field, rawPath, state, index) {
1488
1556
  const rawValue = rawPublication?.[field];
@@ -1497,6 +1565,45 @@ function mapCredentialExpression(rawPublication, resolvedPublication, field, raw
1497
1565
  }
1498
1566
  return void 0;
1499
1567
  }
1568
+ var TRUSTED_PUBLISHING_VALUES = /* @__PURE__ */ new Set(["OIDC", "<USE_OIDC>"]);
1569
+ function rawApiKeyValue(raw) {
1570
+ return raw?.apiKey ?? raw?.["api-key"];
1571
+ }
1572
+ function usesTrustedPublishing(rawPublication) {
1573
+ const rawValue = rawApiKeyValue(rawPublication);
1574
+ return typeof rawValue === "string" && TRUSTED_PUBLISHING_VALUES.has(rawValue);
1575
+ }
1576
+ function mapApiKeyExpression(registry, rawPublication, resolvedPublication, rawPath, state, index, defaultSecretName) {
1577
+ const rawValue = rawApiKeyValue(rawPublication);
1578
+ if (isEnvironmentExpression(rawValue)) return rawValue;
1579
+ if (usesTrustedPublishing(rawPublication)) return void 0;
1580
+ if (defaultSecretName !== void 0) return defaultSecretName;
1581
+ if (rawValue === void 0 && !hasResolvedCredential(resolvedPublication, "apiKey")) {
1582
+ return void 0;
1583
+ }
1584
+ addCredentialDiagnostic(
1585
+ state,
1586
+ [...rawPath, "apiKey"],
1587
+ ["targets", index, "output", "publish", "apiKey"],
1588
+ apiKeyOmissionReason(registry)
1589
+ );
1590
+ return void 0;
1591
+ }
1592
+ function apiKeyOmissionReason(registry) {
1593
+ const label = registry === "nuget" ? "NuGet" : "RubyGems";
1594
+ return `Fern ${label} apiKey is not an exact environment expression naming a secret`;
1595
+ }
1596
+ var FERN_DEFAULT_NUGET_API_KEY = "${NUGET_API_TOKEN}";
1597
+ function fernDefaultApiKey(registry, rawOutput, delivery) {
1598
+ if (registry !== "nuget" || delivery !== "github" || rawOutput?.location !== "nuget") {
1599
+ return void 0;
1600
+ }
1601
+ const rawApiKey = rawApiKeyValue(rawOutput);
1602
+ if (typeof rawApiKey === "string" && TRUSTED_PUBLISHING_VALUES.has(rawApiKey)) {
1603
+ return void 0;
1604
+ }
1605
+ return FERN_DEFAULT_NUGET_API_KEY;
1606
+ }
1500
1607
  function mapPypiCredentialExpressions(rawPublication, resolvedPublication, rawPath, state, index) {
1501
1608
  const rawToken = rawPublication?.token;
1502
1609
  if (isEnvironmentExpression(rawToken)) {
@@ -2212,6 +2319,29 @@ var mavenSignatureSchema = zod.z.strictObject({
2212
2319
  "The armored secret key, or an environment expression that resolves to it."
2213
2320
  )
2214
2321
  });
2322
+ function apiKeySecretSchema(registry, example) {
2323
+ return nonEmptyStringSchema.regex(
2324
+ /^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/,
2325
+ `${registry} apiKey must be an environment expression naming a secret, such as ${example}`
2326
+ );
2327
+ }
2328
+ function apiKeySecretDescription(registry, example) {
2329
+ return `An environment expression naming the repository secret that the generated release workflow reads the ${registry} API key from, such as ${example}. This is a secret name, never the key itself.`;
2330
+ }
2331
+ function trustedPublishingSchema(registry) {
2332
+ return zod.z.boolean().optional().describe(
2333
+ `Whether ${registry} publication uses trusted publishing (OIDC) instead of an API key secret.`
2334
+ );
2335
+ }
2336
+ function refineApiKeyAgainstTrustedPublishing(publish, context) {
2337
+ if (publish.trustedPublishing === true && publish.apiKey !== void 0) {
2338
+ context.addIssue({
2339
+ code: "custom",
2340
+ message: "apiKey must be omitted when trustedPublishing is true",
2341
+ path: ["apiKey"]
2342
+ });
2343
+ }
2344
+ }
2215
2345
  var commonPublishShape = {
2216
2346
  url: nonEmptyStringSchema.optional().describe("A custom package registry URL."),
2217
2347
  releaseBranch: nonEmptyStringSchema.optional().describe("The branch used by generated package release workflows."),
@@ -2247,12 +2377,16 @@ var sdkConfigV1PublishConfigSchema = zod.z.discriminatedUnion("registry", [
2247
2377
  }),
2248
2378
  zod.z.strictObject({
2249
2379
  registry: zod.z.literal("nuget").describe("Publishes the package to a NuGet-compatible registry."),
2380
+ apiKey: apiKeySecretSchema("NuGet", "${NUGET_API_KEY}").optional().describe(apiKeySecretDescription("NuGet", "${NUGET_API_KEY}")),
2381
+ trustedPublishing: trustedPublishingSchema("NuGet"),
2250
2382
  ...commonPublishShape
2251
- }),
2383
+ }).superRefine(refineApiKeyAgainstTrustedPublishing),
2252
2384
  zod.z.strictObject({
2253
2385
  registry: zod.z.literal("rubygems").describe("Publishes the package to a RubyGems-compatible registry."),
2386
+ apiKey: apiKeySecretSchema("RubyGems", "${RUBYGEMS_API_KEY}").optional().describe(apiKeySecretDescription("RubyGems", "${RUBYGEMS_API_KEY}")),
2387
+ trustedPublishing: trustedPublishingSchema("RubyGems"),
2254
2388
  ...commonPublishShape
2255
- }),
2389
+ }).superRefine(refineApiKeyAgainstTrustedPublishing),
2256
2390
  zod.z.strictObject({
2257
2391
  registry: zod.z.literal("crates").describe("Publishes the crate to a Cargo-compatible registry."),
2258
2392
  token: nonEmptyStringSchema.optional().describe("The Cargo registry token, or an environment expression that resolves to it."),
@@ -2310,7 +2444,7 @@ var sdkConfigV1OutputConfigSchema = zod.z.discriminatedUnion(
2310
2444
  );
2311
2445
  var cliDistributionShape = {
2312
2446
  distribution: cliDistributionConfigSchema.optional().describe(
2313
- "CLI release channels published by the generated release workflow; credentials are GitHub Actions secret names."
2447
+ "CLI release channels and build attestation settings for the generated release workflow; credentials are GitHub Actions secret names."
2314
2448
  )
2315
2449
  };
2316
2450
  function rejectDistributionWithoutGithub(output, context) {
@@ -2356,6 +2490,9 @@ var apiImportSettingsSchema = zod.z.strictObject({
2356
2490
  discriminatedUnionV2: zod.z.boolean().optional().describe("Whether oneOf and anyOf schemas use the newer discriminator inference rules."),
2357
2491
  undiscriminatedUnionsWithLiterals: zod.z.boolean().optional().describe("Whether literal-bearing unions remain undiscriminated during import."),
2358
2492
  inlineAllOfSchemas: zod.z.boolean().optional().describe("Whether schemas composed with allOf are inlined when possible."),
2493
+ inferDiscriminatedUnionBaseProperties: zod.z.boolean().optional().describe(
2494
+ "Whether properties every discriminated-union variant shares are lifted onto the union."
2495
+ ),
2359
2496
  resolveSchemaCollisions: zod.z.boolean().optional().describe("Whether colliding imported schema names are resolved automatically."),
2360
2497
  asyncApiMessageNaming: zod.z.enum(["v1", "v2"]).optional().describe("The naming strategy used for messages imported from AsyncAPI."),
2361
2498
  defaultIntegerFormat: zod.z.enum(["int32", "int64", "uint32", "uint64"]).optional().describe("The integer format used when a schema does not declare one.")
@@ -2574,7 +2711,7 @@ var pythonGenerationConfigSchema = zod.z.strictObject({
2574
2711
  additionalInitExports: zod.z.array(additionalInitExportSchema).optional().describe("Additional names re-exported from the package initializer.")
2575
2712
  });
2576
2713
  var rubyGenerationConfigSchema = zod.z.strictObject({
2577
- requirePaths: zod.z.array(nonEmptyStringSchema).optional().describe("Ruby load paths included in the generated gem specification.")
2714
+ requirePaths: zod.z.array(nonEmptyStringSchema).optional().describe("Files the generated entry file loads with `require`.")
2578
2715
  });
2579
2716
  var rustGenerationConfigSchema = zod.z.strictObject({
2580
2717
  /**
@@ -3305,7 +3442,12 @@ function mapCommonConfig(language, config, state, client, generation, packageCon
3305
3442
  }
3306
3443
  const pythonClient = language === "python" ? takeObject(config, ["client"], state, basePath) : void 0;
3307
3444
  const typescriptNaming = language === "typescript" || language === "mcp" ? takeObject(config, ["naming"], state, basePath) : void 0;
3308
- const directClientName = takeString(config, ["clientName", "clientClassName"], state, basePath);
3445
+ const directClientName = takeString(
3446
+ config,
3447
+ language === "ruby" ? ["clientName"] : ["clientName", "clientClassName"],
3448
+ state,
3449
+ basePath
3450
+ );
3309
3451
  const nestedClientName = pythonClient ? takeString(pythonClient.value, ["className"], state, pythonClient.path) : typescriptNaming ? takeString(typescriptNaming.value, ["client"], state, typescriptNaming.path) : language === "ruby" ? (
3310
3452
  // Fern's Ruby generator renames the root client class (`Auth0::Management`) with it.
3311
3453
  takeString(config, ["clientModuleName"], state, basePath)
@@ -4355,6 +4497,7 @@ var publishConfigSchema = zod.z.discriminatedUnion("registry", [
4355
4497
  zod.z.strictObject({
4356
4498
  registry: zod.z.literal("rubygems").describe("Publishes the package to a RubyGems-compatible registry."),
4357
4499
  apiKeyEnvironmentVariable: nonEmptyStringSchema.optional().describe("The environment variable containing the RubyGems API key."),
4500
+ ...trustedPublishingShape,
4358
4501
  ...commonPublishShape2
4359
4502
  }),
4360
4503
  zod.z.strictObject({
@@ -4425,7 +4568,7 @@ var githubOutputSchema2 = zod.z.strictObject({
4425
4568
  var distributionShape = {
4426
4569
  /** Valid only for `cli` targets with GitHub delivery; secret names only, never values. */
4427
4570
  distribution: cliDistributionConfigSchema.optional().describe(
4428
- "CLI release channels published by the generated release workflow; credentials are GitHub Actions secret names."
4571
+ "CLI release channels and build attestation settings for the generated release workflow; credentials are GitHub Actions secret names."
4429
4572
  )
4430
4573
  };
4431
4574
  var credentialResolutionShape = {