@postman/sdk-config 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -73,10 +73,13 @@ if (!result.success) {
73
73
  ```
74
74
 
75
75
  SDK Config objects are strict. Unknown fields, duplicate language targets, incompatible package
76
- publication settings, and non-exact generator versions are rejected. Publishing credentials and
77
- signing material may be provided under `output.publish.credentials`, Maven
78
- `output.publish.signature`, or `output.github.credentials`; these fields can contain raw secrets and
79
- must be handled accordingly by clients and servers.
76
+ publication settings, and non-exact generator versions are rejected. npm and crates use
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
79
+ `${NPM_TOKEN}` rather than literal credentials. Clients must resolve and transport credentials using
80
+ 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.
80
83
 
81
84
  `SdkConfigV1` accepts customer-facing local source paths and HTTP(S) source URLs, but not
82
85
  server-owned signed URLs or artifact metadata. See the
package/dist/index.cjs CHANGED
@@ -581,7 +581,13 @@ function mapOutput(generator, language, index) {
581
581
  const raw = isObject(generator.raw) ? generator.raw : void 0;
582
582
  const rawOutput = raw && isObject(raw.output) ? raw.output : void 0;
583
583
  const outputPath = ["group", "generators", index, "outputMode"];
584
- const state = { consumedPaths: /* @__PURE__ */ new Set() };
584
+ const state = { consumedPaths: /* @__PURE__ */ new Set(), credentialDiagnostics: [] };
585
+ if (generator.output) {
586
+ return {
587
+ output: sanitizeNormalizedOutput(generator.output, rawOutput, state, index),
588
+ unsupportedFields: state.credentialDiagnostics ?? []
589
+ };
590
+ }
585
591
  if (rawOutput?.location === "local-file-system") {
586
592
  if (isObject(generator.outputMode)) consume(state, [...outputPath, "type"]);
587
593
  return finishOutputMapping(
@@ -613,7 +619,7 @@ function mapOutput(generator, language, index) {
613
619
  return finishOutputMapping({ output: { delivery: "zip" } }, output, outputPath, state, index);
614
620
  case "github":
615
621
  return finishOutputMapping(
616
- githubOutput(output, output.publishInfo, language, outputPath, state, index),
622
+ githubOutput(output, output.publishInfo, rawOutput, language, outputPath, state, index),
617
623
  output,
618
624
  outputPath,
619
625
  state,
@@ -633,6 +639,7 @@ function mapOutput(generator, language, index) {
633
639
  githubOutput(
634
640
  output.githubV2,
635
641
  output.githubV2.publishInfo,
642
+ rawOutput,
636
643
  language,
637
644
  githubPath,
638
645
  state,
@@ -647,6 +654,7 @@ function mapOutput(generator, language, index) {
647
654
  case "publishV2": {
648
655
  const publication = mapPublication(
649
656
  output.publishV2,
657
+ rawOutput,
650
658
  language,
651
659
  [...outputPath, "publishV2"],
652
660
  state,
@@ -666,6 +674,7 @@ function mapOutput(generator, language, index) {
666
674
  case "publish": {
667
675
  const publication = mapLegacyPublication(
668
676
  output.registryOverrides,
677
+ rawOutput,
669
678
  language,
670
679
  [...outputPath, "registryOverrides"],
671
680
  state,
@@ -692,7 +701,22 @@ function mapOutput(generator, language, index) {
692
701
  );
693
702
  }
694
703
  }
695
- function githubOutput(value, publishInfo, language, sourcePath, state, index) {
704
+ function sanitizeNormalizedOutput(output, rawOutput, state, index) {
705
+ const publish = output.publish ? sanitizePublishConfig(output.publish, output.publish, rawOutput, state, index) : void 0;
706
+ const publishShape = publish ? { publish } : {};
707
+ if (output.delivery !== "github") return { ...output, ...publishShape };
708
+ const { credentials, ...github } = output.github;
709
+ if (credentials) {
710
+ addCredentialDiagnostic(
711
+ state,
712
+ ["group", "generators", index, "output", "github", "credentials"],
713
+ ["targets", index, "output", "github", "credentials"],
714
+ "Normalized GitHub credentials have no raw environment-expression provenance"
715
+ );
716
+ }
717
+ return { ...output, github, ...publishShape };
718
+ }
719
+ function githubOutput(value, publishInfo, rawOutput, language, sourcePath, state, index) {
696
720
  const owner = stringValue(value.owner);
697
721
  const repo = stringValue(value.repo);
698
722
  if (!owner || !repo)
@@ -705,14 +729,22 @@ function githubOutput(value, publishInfo, language, sourcePath, state, index) {
705
729
  );
706
730
  consume(state, [...sourcePath, "owner"]);
707
731
  consume(state, [...sourcePath, "repo"]);
708
- const publication = publishInfo ? mapPublication(publishInfo, language, [...sourcePath, "publishInfo"], state, index) : void 0;
732
+ const publication = publishInfo ? mapPublication(publishInfo, rawOutput, language, [...sourcePath, "publishInfo"], state, index) : void 0;
709
733
  const type = stringValue(value.type);
710
734
  const reviewers = mapReviewers(value.reviewers, [...sourcePath, "reviewers"], state);
711
735
  if (type) consume(state, [...sourcePath, "type"]);
712
736
  if (typeof value.makePr === "boolean") consume(state, [...sourcePath, "makePr"]);
713
737
  if (stringValue(value.host)) consume(state, [...sourcePath, "host"]);
714
738
  if (stringValue(value.branch)) consume(state, [...sourcePath, "branch"]);
715
- const credentials = mapCredentials(value.credentials, [...sourcePath, "credentials"], state);
739
+ consumeCredentialObject(value.credentials, [...sourcePath, "credentials"], state);
740
+ if (isObject(value.credentials)) {
741
+ addCredentialDiagnostic(
742
+ state,
743
+ [...sourcePath, "credentials"],
744
+ ["targets", index, "output", "github", "credentials"],
745
+ "GitHub credentials cannot be traced safely to raw environment expressions"
746
+ );
747
+ }
716
748
  return {
717
749
  output: {
718
750
  delivery: "github",
@@ -721,57 +753,35 @@ function githubOutput(value, publishInfo, language, sourcePath, state, index) {
721
753
  ...optional("host", stringValue(value.host)),
722
754
  ...optional("branch", stringValue(value.branch)),
723
755
  mode: value.makePr === true || type === "pullRequest" ? "pull-request" : type === "push" ? "push" : "release",
724
- ...optional("reviewers", reviewers),
725
- ...optional("credentials", credentials)
756
+ ...optional("reviewers", reviewers)
726
757
  },
727
758
  ...publication ? { publish: publication.publish } : {}
728
759
  },
729
760
  ...optional("package", publication?.package)
730
761
  };
731
762
  }
732
- function mapCredentials(value, sourcePath, state) {
733
- if (!isObject(value)) return void 0;
734
- return credentialsFromObject(value, sourcePath, state);
735
- }
736
- function mapInlineCredentials(value, sourcePath, state) {
737
- const credentials = mapCredentials(value.credentials, [...sourcePath, "credentials"], state);
738
- if (credentials) return credentials;
739
- return credentialsFromObject(value, sourcePath, state);
740
- }
741
- function credentialsFromObject(value, sourcePath, state) {
742
- const credentials = {};
743
- const username = stringValue(value.username);
744
- const password = stringValue(value.password);
745
- const token = stringValue(value.token);
746
- const apiKey = stringValue(value.apiKey);
747
- if (username) {
748
- credentials.username = username;
749
- consume(state, [...sourcePath, "username"]);
750
- }
751
- if (password) {
752
- credentials.password = password;
753
- consume(state, [...sourcePath, "password"]);
754
- }
755
- if (token) {
756
- credentials.token = token;
757
- consume(state, [...sourcePath, "token"]);
758
- }
759
- if (apiKey) {
760
- credentials.apiKey = apiKey;
761
- consume(state, [...sourcePath, "apiKey"]);
762
- }
763
- return Object.keys(credentials).length === 0 ? void 0 : credentials;
764
- }
765
- function mapMavenSignature(value, sourcePath, state) {
766
- if (!isObject(value)) return void 0;
767
- const keyId = stringValue(value.keyId);
768
- const password = stringValue(value.password);
769
- const secretKey = stringValue(value.secretKey);
770
- if (!keyId || !password || !secretKey) return void 0;
771
- consume(state, [...sourcePath, "keyId"]);
772
- consume(state, [...sourcePath, "password"]);
773
- consume(state, [...sourcePath, "secretKey"]);
774
- return { keyId, password, secretKey };
763
+ function consumeCredentialObject(value, sourcePath, state) {
764
+ if (!isObject(value)) return;
765
+ for (const field of ["username", "password", "token", "apiKey"]) {
766
+ if (stringValue(value[field])) consume(state, [...sourcePath, field]);
767
+ }
768
+ }
769
+ function consumeResolvedCredentials(value, sourcePath, state) {
770
+ for (const field of ["username", "password", "token", "apiKey"]) {
771
+ if (stringValue(value[field])) {
772
+ consume(state, [...sourcePath, field]);
773
+ }
774
+ }
775
+ if (isObject(value.credentials)) {
776
+ for (const field of ["username", "password", "token", "apiKey"]) {
777
+ if (stringValue(value.credentials[field])) {
778
+ consume(state, [...sourcePath, "credentials", field]);
779
+ }
780
+ }
781
+ }
782
+ if (isObject(value.signature)) {
783
+ consume(state, [...sourcePath, "signature"]);
784
+ }
775
785
  }
776
786
  function mapReviewers(value, sourcePath, state) {
777
787
  if (Array.isArray(value)) {
@@ -800,7 +810,7 @@ function reviewerNames(value, expectedType, sourcePath, state) {
800
810
  });
801
811
  return names.length ? names : void 0;
802
812
  }
803
- function mapPublication(value, language, sourcePath, state, index) {
813
+ function mapPublication(value, rawOutput, language, sourcePath, state, index) {
804
814
  if (!isObject(value))
805
815
  fail(
806
816
  "FERN_PUBLICATION_INVALID",
@@ -816,13 +826,19 @@ function mapPublication(value, language, sourcePath, state, index) {
816
826
  const registry = publicationRegistry(type, language, [...sourcePath, "type"], index);
817
827
  const registryUrl = stringValue(nested.registryUrl);
818
828
  if (registryUrl) consume(state, [...nestedPath, "registryUrl"]);
819
- const credentials = mapInlineCredentials(nested, nestedPath, state);
829
+ consumeResolvedCredentials(nested, nestedPath, state);
830
+ const publish = sanitizePublishConfig(
831
+ compact({ registry, url: registryUrl }),
832
+ nested,
833
+ rawOutput,
834
+ state,
835
+ index
836
+ );
820
837
  if (registry === "maven") {
821
838
  const coordinate = stringValue(nested.coordinate);
822
- const signature = mapMavenSignature(nested.signature, [...nestedPath, "signature"], state);
823
839
  if (coordinate) consume(state, [...nestedPath, "coordinate"]);
824
840
  return {
825
- publish: compact({ registry, url: registryUrl, credentials, signature }),
841
+ publish,
826
842
  ...coordinate ? { package: mavenPackage(coordinate, [...nestedPath, "coordinate"], index) } : {}
827
843
  };
828
844
  }
@@ -831,15 +847,244 @@ function mapPublication(value, language, sourcePath, state, index) {
831
847
  if (packageName) consume(state, [...nestedPath, packageNameField]);
832
848
  const metadata = registry === "pypi" ? mapPypiMetadata(nested.pypiMetadata, nestedPath, state) : {};
833
849
  return {
834
- publish: compact({ registry, url: registryUrl, credentials }),
850
+ publish,
835
851
  ...packageName || Object.keys(metadata).length ? { package: { ...optional("packageName", packageName), ...metadata } } : {}
836
852
  };
837
853
  }
838
- function mapLegacyPublication(value, language, sourcePath, state, index) {
854
+ function sanitizePublishConfig(publish, resolvedPublication, rawOutput, state, index) {
855
+ const rawPublication = rawOutput?.location === publish.registry ? rawOutput : void 0;
856
+ const rawPath = ["group", "generators", index, "output"];
857
+ if (publish.registry === "npm" || publish.registry === "crates") {
858
+ const token = mapCredentialExpression(
859
+ rawPublication,
860
+ resolvedPublication,
861
+ "token",
862
+ rawPath,
863
+ state,
864
+ index
865
+ );
866
+ warnForUnexpectedCredentialFields(
867
+ rawPublication,
868
+ resolvedPublication,
869
+ ["token"],
870
+ rawPath,
871
+ state,
872
+ index
873
+ );
874
+ return compact({
875
+ registry: publish.registry,
876
+ url: publish.url,
877
+ releaseBranch: publish.releaseBranch,
878
+ tolerateRepublish: publish.tolerateRepublish,
879
+ token
880
+ });
881
+ }
882
+ if (publish.registry === "pypi") {
883
+ const { username, password } = mapPypiCredentialExpressions(
884
+ rawPublication,
885
+ resolvedPublication,
886
+ rawPath,
887
+ state,
888
+ index
889
+ );
890
+ warnForUnexpectedCredentialFields(
891
+ rawPublication,
892
+ resolvedPublication,
893
+ ["username", "password", "token"],
894
+ rawPath,
895
+ state,
896
+ index
897
+ );
898
+ return compact({
899
+ registry: publish.registry,
900
+ url: publish.url,
901
+ releaseBranch: publish.releaseBranch,
902
+ tolerateRepublish: publish.tolerateRepublish,
903
+ username,
904
+ password
905
+ });
906
+ }
907
+ if (publish.registry === "maven") {
908
+ const username = mapCredentialExpression(
909
+ rawPublication,
910
+ resolvedPublication,
911
+ "username",
912
+ rawPath,
913
+ state,
914
+ index
915
+ );
916
+ const password = mapCredentialExpression(
917
+ rawPublication,
918
+ resolvedPublication,
919
+ "password",
920
+ rawPath,
921
+ state,
922
+ index
923
+ );
924
+ const signature = mapMavenSignatureExpressions(
925
+ rawPublication?.signature,
926
+ resolvedPublication.signature,
927
+ [...rawPath, "signature"],
928
+ state,
929
+ index
930
+ );
931
+ warnForUnexpectedCredentialFields(
932
+ rawPublication,
933
+ resolvedPublication,
934
+ ["username", "password"],
935
+ rawPath,
936
+ state,
937
+ index,
938
+ true
939
+ );
940
+ return compact({
941
+ registry: publish.registry,
942
+ url: publish.url,
943
+ releaseBranch: publish.releaseBranch,
944
+ tolerateRepublish: publish.tolerateRepublish,
945
+ username,
946
+ password,
947
+ signature
948
+ });
949
+ }
950
+ warnForUnrepresentableCredentials(rawPublication, resolvedPublication, rawPath, state, index);
951
+ return compact({
952
+ registry: publish.registry,
953
+ url: publish.url,
954
+ releaseBranch: publish.releaseBranch,
955
+ tolerateRepublish: publish.tolerateRepublish
956
+ });
957
+ }
958
+ function mapLegacyPublication(value, rawOutput, language, sourcePath, state, index) {
839
959
  const registry = defaultRegistry(language, sourcePath, index);
840
960
  const overrides = isObject(value) ? value : {};
841
961
  const override = isObject(overrides[registry]) ? overrides[registry] : {};
842
- return mapPublication(override, language, [...sourcePath, registry], state, index);
962
+ return mapPublication(override, rawOutput, language, [...sourcePath, registry], state, index);
963
+ }
964
+ function mapCredentialExpression(rawPublication, resolvedPublication, field, rawPath, state, index) {
965
+ const rawValue = rawPublication?.[field];
966
+ if (isEnvironmentExpression(rawValue)) return rawValue;
967
+ if (rawValue !== void 0 || hasResolvedCredential(resolvedPublication, field)) {
968
+ addCredentialDiagnostic(
969
+ state,
970
+ [...rawPath, field],
971
+ ["targets", index, "output", "publish", field],
972
+ `Fern publishing ${field} is not an exact environment expression`
973
+ );
974
+ }
975
+ return void 0;
976
+ }
977
+ function mapPypiCredentialExpressions(rawPublication, resolvedPublication, rawPath, state, index) {
978
+ const rawToken = rawPublication?.token;
979
+ if (isEnvironmentExpression(rawToken)) {
980
+ return { username: "__token__", password: rawToken };
981
+ }
982
+ const resolvedUsesToken = resolvedCredentialValue(resolvedPublication, "username") === "__token__";
983
+ if (rawToken !== void 0 || resolvedUsesToken) {
984
+ addCredentialDiagnostic(
985
+ state,
986
+ [...rawPath, "token"],
987
+ ["targets", index, "output", "publish", "password"],
988
+ "Fern PyPI token is not an exact raw environment expression"
989
+ );
990
+ return {};
991
+ }
992
+ return {
993
+ ...optional(
994
+ "username",
995
+ mapCredentialExpression(
996
+ rawPublication,
997
+ resolvedPublication,
998
+ "username",
999
+ rawPath,
1000
+ state,
1001
+ index
1002
+ )
1003
+ ),
1004
+ ...optional(
1005
+ "password",
1006
+ mapCredentialExpression(
1007
+ rawPublication,
1008
+ resolvedPublication,
1009
+ "password",
1010
+ rawPath,
1011
+ state,
1012
+ index
1013
+ )
1014
+ )
1015
+ };
1016
+ }
1017
+ function mapMavenSignatureExpressions(rawValue, resolvedValue, rawPath, state, index) {
1018
+ if (isObject(rawValue)) {
1019
+ const yamlValues = [rawValue["key-id"], rawValue.password, rawValue["secret-key"]];
1020
+ const projectedValues = [rawValue.keyId, rawValue.password, rawValue.secretKey];
1021
+ const values = yamlValues.every(isEnvironmentExpression) ? yamlValues : projectedValues.every(isEnvironmentExpression) ? projectedValues : void 0;
1022
+ if (values) {
1023
+ const [keyId, password, secretKey] = values;
1024
+ return { keyId, password, secretKey };
1025
+ }
1026
+ }
1027
+ if (rawValue !== void 0 || isObject(resolvedValue)) {
1028
+ addCredentialDiagnostic(
1029
+ state,
1030
+ rawPath,
1031
+ ["targets", index, "output", "publish", "signature"],
1032
+ "Maven signing credentials are incomplete or not exact environment expressions"
1033
+ );
1034
+ }
1035
+ return void 0;
1036
+ }
1037
+ function warnForUnrepresentableCredentials(rawPublication, resolvedPublication, rawPath, state, index) {
1038
+ const rawHasCredential = ["username", "password", "token", "apiKey"].some(
1039
+ (field) => rawPublication?.[field] !== void 0
1040
+ ) || rawPublication?.signature !== void 0;
1041
+ if (rawHasCredential || hasAnyResolvedCredential(resolvedPublication)) {
1042
+ addCredentialDiagnostic(
1043
+ state,
1044
+ rawPath,
1045
+ ["targets", index, "output", "publish"],
1046
+ "This registry does not support credentials in public SDK Config v1"
1047
+ );
1048
+ }
1049
+ }
1050
+ function warnForUnexpectedCredentialFields(rawPublication, resolvedPublication, allowedFields, rawPath, state, index, allowSignature = false) {
1051
+ const credentialFields = ["username", "password", "token", "apiKey"];
1052
+ const unexpectedFields = credentialFields.filter(
1053
+ (field) => !allowedFields.includes(field) && (rawPublication?.[field] !== void 0 || hasResolvedCredential(resolvedPublication, field))
1054
+ );
1055
+ const hasUnexpectedSignature = !allowSignature && (rawPublication?.signature !== void 0 || resolvedPublication.signature !== void 0);
1056
+ if (unexpectedFields.length > 0 || hasUnexpectedSignature) {
1057
+ addCredentialDiagnostic(
1058
+ state,
1059
+ rawPath,
1060
+ ["targets", index, "output", "publish"],
1061
+ "Fern publishing credentials or signing material include fields unsupported by this registry"
1062
+ );
1063
+ }
1064
+ }
1065
+ function hasResolvedCredential(value, field) {
1066
+ return resolvedCredentialValue(value, field) !== void 0;
1067
+ }
1068
+ function resolvedCredentialValue(value, field) {
1069
+ return stringValue(value[field]) ?? (isObject(value.credentials) ? stringValue(value.credentials[field]) : void 0);
1070
+ }
1071
+ function hasAnyResolvedCredential(value) {
1072
+ return ["username", "password", "token", "apiKey"].some(
1073
+ (field) => hasResolvedCredential(value, field)
1074
+ ) || value.signature !== void 0;
1075
+ }
1076
+ function isEnvironmentExpression(value) {
1077
+ return typeof value === "string" && /^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(value);
1078
+ }
1079
+ function addCredentialDiagnostic(state, path, sdkConfigPath, reason) {
1080
+ state.credentialDiagnostics?.push({
1081
+ code: "FERN_OUTPUT_CREDENTIAL_OMITTED",
1082
+ severity: "warning",
1083
+ path,
1084
+ reason,
1085
+ sdkConfigPath,
1086
+ suggestedAction: `Configure ${sdkConfigPath.join(".")} with an environment expression such as \${CREDENTIAL_ENV_VAR}.`
1087
+ });
843
1088
  }
844
1089
  function publicationRegistry(type, language, sourcePath, index) {
845
1090
  if (type === "postman") {
@@ -947,6 +1192,7 @@ function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
947
1192
  return {
948
1193
  ...mapping,
949
1194
  unsupportedFields: [
1195
+ ...state.credentialDiagnostics ?? [],
950
1196
  ...hasCredentials ? [
951
1197
  {
952
1198
  code: "FERN_OUTPUT_CREDENTIAL_UNSUPPORTED",
@@ -1176,12 +1422,6 @@ var sdkConfigV1PublishRegistrySchema = zod.z.enum([
1176
1422
  "go",
1177
1423
  "composer"
1178
1424
  ]);
1179
- var registryCredentialsSchema = zod.z.strictObject({
1180
- username: nonEmptyStringSchema.optional(),
1181
- password: nonEmptyStringSchema.optional(),
1182
- token: nonEmptyStringSchema.optional(),
1183
- apiKey: nonEmptyStringSchema.optional()
1184
- });
1185
1425
  var mavenSignatureSchema = zod.z.strictObject({
1186
1426
  keyId: nonEmptyStringSchema,
1187
1427
  password: nonEmptyStringSchema,
@@ -1189,23 +1429,35 @@ var mavenSignatureSchema = zod.z.strictObject({
1189
1429
  });
1190
1430
  var commonPublishShape = {
1191
1431
  url: nonEmptyStringSchema.optional(),
1192
- /** Raw registry credentials. These values can be sensitive and must be handled as secrets. */
1193
- credentials: registryCredentialsSchema.optional(),
1194
1432
  releaseBranch: nonEmptyStringSchema.optional(),
1195
1433
  tolerateRepublish: zod.z.boolean().optional()
1196
1434
  };
1197
1435
  var sdkConfigV1PublishConfigSchema = zod.z.discriminatedUnion("registry", [
1198
- zod.z.strictObject({ registry: zod.z.literal("npm"), ...commonPublishShape }),
1199
- zod.z.strictObject({ registry: zod.z.literal("pypi"), ...commonPublishShape }),
1436
+ zod.z.strictObject({
1437
+ registry: zod.z.literal("npm"),
1438
+ token: nonEmptyStringSchema.optional(),
1439
+ ...commonPublishShape
1440
+ }),
1441
+ zod.z.strictObject({
1442
+ registry: zod.z.literal("pypi"),
1443
+ username: nonEmptyStringSchema.optional(),
1444
+ password: nonEmptyStringSchema.optional(),
1445
+ ...commonPublishShape
1446
+ }),
1200
1447
  zod.z.strictObject({
1201
1448
  registry: zod.z.literal("maven"),
1202
- /** Raw Maven signing material. These values can be sensitive and must be handled as secrets. */
1449
+ username: nonEmptyStringSchema.optional(),
1450
+ password: nonEmptyStringSchema.optional(),
1203
1451
  signature: mavenSignatureSchema.optional(),
1204
1452
  ...commonPublishShape
1205
1453
  }),
1206
1454
  zod.z.strictObject({ registry: zod.z.literal("nuget"), ...commonPublishShape }),
1207
1455
  zod.z.strictObject({ registry: zod.z.literal("rubygems"), ...commonPublishShape }),
1208
- zod.z.strictObject({ registry: zod.z.literal("crates"), ...commonPublishShape }),
1456
+ zod.z.strictObject({
1457
+ registry: zod.z.literal("crates"),
1458
+ token: nonEmptyStringSchema.optional(),
1459
+ ...commonPublishShape
1460
+ }),
1209
1461
  zod.z.strictObject({ registry: zod.z.literal("go"), ...commonPublishShape }),
1210
1462
  zod.z.strictObject({ registry: zod.z.literal("composer"), ...commonPublishShape })
1211
1463
  ]);
@@ -1213,7 +1465,12 @@ var reviewersSchema = zod.z.strictObject({
1213
1465
  teams: zod.z.array(nonEmptyStringSchema).optional(),
1214
1466
  users: zod.z.array(nonEmptyStringSchema).optional()
1215
1467
  });
1216
- var githubCredentialsSchema = registryCredentialsSchema;
1468
+ var githubCredentialsSchema = zod.z.strictObject({
1469
+ username: nonEmptyStringSchema.optional(),
1470
+ password: nonEmptyStringSchema.optional(),
1471
+ token: nonEmptyStringSchema.optional(),
1472
+ apiKey: nonEmptyStringSchema.optional()
1473
+ });
1217
1474
  var githubOutputSchema = zod.z.strictObject({
1218
1475
  repository: nonEmptyStringSchema,
1219
1476
  host: nonEmptyStringSchema.optional(),
@@ -1730,7 +1987,7 @@ function mapFernConfigToSdkConfigV1(input) {
1730
1987
  const mapped = input.group.generators.map((generator, index) => {
1731
1988
  const language = languages[index];
1732
1989
  const invocation = mapInvocation(generator, language, activeLanguages, index);
1733
- const outputMapping = generator.output ? { output: generator.output, unsupportedFields: [] } : mapOutput(generator, language, index);
1990
+ const outputMapping = mapOutput(generator, language, index);
1734
1991
  return {
1735
1992
  generator,
1736
1993
  language,
@@ -1789,6 +2046,7 @@ function mapFernConfigToSdkConfigV1(input) {
1789
2046
  source: input.source,
1790
2047
  ...optional("sdkVersion", input.sdkVersion),
1791
2048
  ...optional("apiVersion", input.apiVersion),
2049
+ ...optional("replay", input.replay),
1792
2050
  ...optionalObject("api", api),
1793
2051
  ...optionalObject("client", clients.shared),
1794
2052
  ...optionalObject("docs", docs.shared),
@@ -2721,7 +2979,7 @@ var credentialResolutionSchema = zod.z.enum([
2721
2979
  "resolved-by-orchestrator",
2722
2980
  "resolved-by-fiddle"
2723
2981
  ]);
2724
- var registryCredentialsSchema2 = zod.z.strictObject({
2982
+ var registryCredentialsSchema = zod.z.strictObject({
2725
2983
  username: nonEmptyStringSchema.optional(),
2726
2984
  password: nonEmptyStringSchema.optional(),
2727
2985
  token: nonEmptyStringSchema.optional(),
@@ -2732,7 +2990,7 @@ var commonPublishShape2 = {
2732
2990
  /** Reference to registry publishing credentials. */
2733
2991
  credentialsRef: nonEmptyStringSchema.optional(),
2734
2992
  /** Raw registry credentials. These values can be sensitive and must be handled as secrets. */
2735
- credentials: registryCredentialsSchema2.optional(),
2993
+ credentials: registryCredentialsSchema.optional(),
2736
2994
  /**
2737
2995
  * Registry-specific package version override. If omitted, the external publisher/orchestrator may
2738
2996
  * fall back to target.sdkVersion.
@@ -2837,7 +3095,7 @@ var githubOutputSchema2 = zod.z.strictObject({
2837
3095
  /** Reference to GitHub credentials. */
2838
3096
  credentialsRef: nonEmptyStringSchema.optional(),
2839
3097
  /** Raw GitHub credentials. These values can be sensitive and must be handled as secrets. */
2840
- credentials: registryCredentialsSchema2.optional(),
3098
+ credentials: registryCredentialsSchema.optional(),
2841
3099
  privateRepository: zod.z.boolean().optional(),
2842
3100
  /** GitHub license block scoped to repository delivery. */
2843
3101
  license: githubLicenseSchema.optional(),