vercel 59.4.0 → 59.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/chunks/{add-FQMB3XPM.js → add-4GQZ22ZN.js} +20 -16
  2. package/dist/chunks/{add-73X2SKBH.js → add-HJSEM4YJ.js} +17 -13
  3. package/dist/chunks/{add-QJ3WT4FW.js → add-SIGUSM3Y.js} +21 -17
  4. package/dist/chunks/{build-YUYCLCXD.js → build-XOMJDX4M.js} +18 -15
  5. package/dist/chunks/{chunk-F7OXZLY2.js → chunk-26XDDLXM.js} +2 -2
  6. package/dist/chunks/{chunk-VCE6QKFE.js → chunk-2O5J3KMT.js} +4 -4
  7. package/dist/chunks/{chunk-XI6NJLI4.js → chunk-2YRAWYGE.js} +3 -3
  8. package/dist/chunks/{chunk-X6O6XJEA.js → chunk-37V5P4VO.js} +16 -14
  9. package/dist/chunks/{chunk-EB7NJKPL.js → chunk-3F5EGINT.js} +3 -3
  10. package/dist/chunks/{chunk-RIB4S2IB.js → chunk-3HZLXCVL.js} +1 -1
  11. package/dist/chunks/{chunk-KQRVZWJU.js → chunk-3T7WSWZH.js} +1 -1
  12. package/dist/chunks/{chunk-3KNPVXJ3.js → chunk-4KD5BYHB.js} +1 -1
  13. package/dist/chunks/{chunk-XLKFJPMT.js → chunk-57RHXXXG.js} +1 -1
  14. package/dist/chunks/chunk-5GGUB4EO.js +31 -0
  15. package/dist/chunks/{chunk-R6IGDGX3.js → chunk-5XECIWME.js} +1 -1
  16. package/dist/chunks/{chunk-KAYSW4CJ.js → chunk-6JPVTPTU.js} +3 -3
  17. package/dist/chunks/{chunk-ZFWNMVNR.js → chunk-6M2KZUED.js} +19 -8
  18. package/dist/chunks/{chunk-HT2XWSAJ.js → chunk-7AEEQOD4.js} +2 -29
  19. package/dist/chunks/{chunk-HURL5EBN.js → chunk-7HE63HCR.js} +124 -161
  20. package/dist/chunks/chunk-7Q45OKWR.js +149 -0
  21. package/dist/chunks/{chunk-RI7KKKII.js → chunk-7R6M3BHM.js} +4 -18
  22. package/dist/chunks/{chunk-XBN2O34P.js → chunk-7ST552E3.js} +17 -4
  23. package/dist/chunks/{chunk-JKQWQA2T.js → chunk-AINIBIP4.js} +1 -1
  24. package/dist/chunks/{chunk-CV4S27SS.js → chunk-ASBP32T6.js} +1 -1
  25. package/dist/chunks/chunk-AYLY3ZVL.js +104 -0
  26. package/dist/chunks/{chunk-SOFC4MLS.js → chunk-BMKU5KEL.js} +9 -569
  27. package/dist/chunks/{chunk-KDYRLN6H.js → chunk-C5HKWXRR.js} +1 -1
  28. package/dist/chunks/{chunk-2MF3ZAVW.js → chunk-CJV7J7B5.js} +6 -6
  29. package/dist/chunks/{chunk-HJVTLJHO.js → chunk-DE7MBNHQ.js} +6 -6
  30. package/dist/chunks/{chunk-3L2YLLHC.js → chunk-DWIC7MRV.js} +2 -2
  31. package/dist/chunks/{chunk-GFCTRJI5.js → chunk-EZKW5YJ2.js} +1 -1
  32. package/dist/chunks/{chunk-MWYQ24FO.js → chunk-FRAXI2WT.js} +3 -3
  33. package/dist/chunks/{chunk-DDIZGOCK.js → chunk-FRZULOVH.js} +8 -6
  34. package/dist/chunks/{chunk-Y3J4VU2H.js → chunk-FWKSJYDV.js} +2 -2
  35. package/dist/chunks/chunk-FXD67VN5.js +467 -0
  36. package/dist/chunks/{chunk-EB5NBVTV.js → chunk-GISTGGBO.js} +8 -8
  37. package/dist/chunks/chunk-GY5I4AYD.js +122 -0
  38. package/dist/chunks/{chunk-PD4DYNSB.js → chunk-GZQQNLF5.js} +5 -5
  39. package/dist/chunks/{chunk-PIMIKY4X.js → chunk-IJ4X426J.js} +1 -1
  40. package/dist/chunks/{chunk-KSZ4MNHO.js → chunk-JH4WQRIU.js} +2 -2
  41. package/dist/chunks/{chunk-TVXCXIRO.js → chunk-L3UXB2CW.js} +1 -1
  42. package/dist/chunks/{chunk-O5DLWLT7.js → chunk-LXZVOR6F.js} +9 -9
  43. package/dist/chunks/{chunk-EG5BSAXD.js → chunk-MTWHQEXI.js} +1 -1
  44. package/dist/chunks/{chunk-WC7IINFV.js → chunk-NFU4XJIR.js} +1 -1
  45. package/dist/chunks/{chunk-TH2XUVDP.js → chunk-NGGLYKNU.js} +30 -6
  46. package/dist/chunks/{chunk-2PX6N4FE.js → chunk-NGNN6WF2.js} +10 -10
  47. package/dist/chunks/{chunk-GGPE5377.js → chunk-O26N2UPI.js} +1 -1
  48. package/dist/chunks/chunk-O75LSD3C.js +34 -0
  49. package/dist/chunks/{chunk-BBSS3XIW.js → chunk-OQ3C5VXZ.js} +1 -1
  50. package/dist/chunks/{chunk-M22O6CYY.js → chunk-POOO7W47.js} +1 -1
  51. package/dist/chunks/{chunk-LKTQR5JE.js → chunk-PRH6KRUT.js} +2 -2
  52. package/dist/chunks/chunk-Q2DGFCO7.js +579 -0
  53. package/dist/chunks/{chunk-OX7KI3LF.js → chunk-QFAS4OVW.js} +18 -0
  54. package/dist/chunks/{chunk-CHEZBD7H.js → chunk-R5PULMHT.js} +3 -3
  55. package/dist/chunks/{chunk-VAFU7DXZ.js → chunk-RKDCNQ4S.js} +1 -91
  56. package/dist/chunks/{chunk-BLYBHFIE.js → chunk-SF3AYAIF.js} +61 -24
  57. package/dist/chunks/{chunk-GMWRTZVZ.js → chunk-SLPSPYVR.js} +1 -1
  58. package/dist/chunks/{chunk-J5Y2QGGU.js → chunk-SWI6F4X3.js} +2 -2
  59. package/dist/chunks/chunk-V3MDDR2X.js +249 -0
  60. package/dist/chunks/{chunk-HMJVUXE6.js → chunk-VJ5NAOWB.js} +867 -625
  61. package/dist/chunks/{chunk-O5GNPPTU.js → chunk-VP5Y3SZG.js} +1 -1
  62. package/dist/chunks/{chunk-G75NFPIT.js → chunk-WNAKOXGK.js} +1 -1
  63. package/dist/chunks/{chunk-NP6BQPCN.js → chunk-WZ2S3A2A.js} +8 -6
  64. package/dist/chunks/{chunk-7QVJTI5H.js → chunk-XDGOOW3K.js} +1 -1
  65. package/dist/chunks/{chunk-UMA66MKW.js → chunk-XM3LOQIX.js} +1 -1
  66. package/dist/chunks/{chunk-CYNB6LL4.js → chunk-XNFHNTS2.js} +1 -1
  67. package/dist/chunks/{chunk-VDJN4WKH.js → chunk-XRWOTCDO.js} +1 -1
  68. package/dist/chunks/{chunk-UV2ZMFVG.js → chunk-YJKZQEHS.js} +2 -2
  69. package/dist/chunks/{chunk-STPH4Y62.js → chunk-YJUO3EKH.js} +1 -1
  70. package/dist/chunks/{chunk-Y42SPI2H.js → chunk-ZNMTDLYH.js} +6 -6
  71. package/dist/chunks/{chunk-VLPLCJZC.js → chunk-ZSFEACZU.js} +1 -1
  72. package/dist/chunks/{clear-USQM5VW5.js → clear-BWT2FJY4.js} +17 -13
  73. package/dist/chunks/{compile-vercel-config-2JNYMI6W.js → compile-vercel-config-DGM4NISW.js} +10 -7
  74. package/dist/chunks/{config-VTRIDLY4.js → config-NJAN3RMU.js} +20 -16
  75. package/dist/chunks/config-RSE6Z4LB.js +122 -0
  76. package/dist/chunks/{constants-YMCRE6IG.js → constants-WEQVJSYS.js} +1 -1
  77. package/dist/chunks/{delete-ILLSBCVQ.js → delete-LROBRBAH.js} +15 -11
  78. package/dist/chunks/{delete-VTPHK3EB.js → delete-SSL2PK2F.js} +12 -9
  79. package/dist/chunks/{disable-VTOMO64V.js → disable-ASG5JDZR.js} +12 -9
  80. package/dist/chunks/{discard-ZIOZ34ZI.js → discard-PV47B6IL.js} +12 -9
  81. package/dist/chunks/{edit-E3AMR4KM.js → edit-5ATYIOLX.js} +14 -11
  82. package/dist/chunks/{edit-JMZ5XWVW.js → edit-REI7HXGG.js} +16 -12
  83. package/dist/chunks/{enable-A4PMZ7QZ.js → enable-LZXL7XAG.js} +12 -9
  84. package/dist/chunks/{exec-CNBOV577.js → exec-XH4K34JM.js} +3 -3
  85. package/dist/chunks/{export-Y6AJ3WRZ.js → export-ZAZFQU2E.js} +12 -9
  86. package/dist/chunks/{image-26BKPAUB.js → image-QPHN5V7L.js} +7 -6
  87. package/dist/chunks/{import-builders-3H7J2SEK.js → import-builders-W3YE2V6A.js} +12 -9
  88. package/dist/chunks/{inspect-7DGKYHKW.js → inspect-BFGK72WY.js} +18 -14
  89. package/dist/chunks/{inspect-OEY4DJRI.js → inspect-FRXJRM6T.js} +18 -14
  90. package/dist/chunks/{inspect-ZW5N6O5P.js → inspect-RDMC2Z3Q.js} +17 -13
  91. package/dist/chunks/{inspect-GJFVAZIJ.js → inspect-SJEZVGPK.js} +20 -16
  92. package/dist/chunks/{inspect-N3E2PO6K.js → inspect-SSOM3FXS.js} +17 -13
  93. package/dist/chunks/{list-MIQ5D6PM.js → list-2HTR7Q3J.js} +18 -14
  94. package/dist/chunks/{list-2VTCNQEB.js → list-PHDUZVMR.js} +15 -11
  95. package/dist/chunks/{list-DTJBW7OQ.js → list-W33GXKDA.js} +18 -14
  96. package/dist/chunks/{login-L34UHAU5.js → login-JWAFHVDG.js} +30 -17
  97. package/dist/chunks/{ls-OBUDC4SB.js → ls-3AN2DZHN.js} +20 -15
  98. package/dist/chunks/{ls-SXJFBLUT.js → ls-3MH2OCP3.js} +20 -15
  99. package/dist/chunks/ls-D2POUHI7.js +176 -0
  100. package/dist/chunks/{ls-VDYUFSSC.js → ls-KDFU224B.js} +20 -15
  101. package/dist/chunks/{ls-OKO4IHWB.js → ls-KX2VBOGV.js} +18 -14
  102. package/dist/chunks/{ls-NCPQY4FV.js → ls-RWKNJQNT.js} +23 -18
  103. package/dist/chunks/{open-V5JDGXUP.js → open-IEYRB6RL.js} +15 -11
  104. package/dist/chunks/{permissions-6CPRPPBY.js → permissions-ZWZUMEHR.js} +10 -9
  105. package/dist/chunks/{publish-R27DPHFO.js → publish-UWZYBDHK.js} +12 -9
  106. package/dist/chunks/{push-VLVTBS42.js → push-IAEQ3FBF.js} +18 -15
  107. package/dist/chunks/{query-IVVRYMJN.js → query-NNOZYSED.js} +18 -14
  108. package/dist/chunks/{reorder-LJ2RBZM2.js → reorder-TKBM244W.js} +12 -9
  109. package/dist/chunks/{reply-USAISZYC.js → reply-FLBSBMTW.js} +16 -12
  110. package/dist/chunks/{resolve-CRCJYVS5.js → resolve-GJYPMWUE.js} +15 -11
  111. package/dist/chunks/{restore-6PBPEAMU.js → restore-PNI3TM3U.js} +12 -9
  112. package/dist/chunks/{rm-HHELZB7R.js → rm-76CSSSSV.js} +17 -13
  113. package/dist/chunks/{rm-TWU3JR6Z.js → rm-FN7LTIIL.js} +17 -13
  114. package/dist/chunks/{rm-KGOEOWVK.js → rm-FTE33UHE.js} +16 -12
  115. package/dist/chunks/rm-FXA5DLXQ.js +315 -0
  116. package/dist/chunks/{rm-EOD7RDSO.js → rm-PGJ4KR6U.js} +20 -16
  117. package/dist/chunks/{routes-SZI2G4SE.js → routes-2OLIBRYX.js} +3 -3
  118. package/dist/chunks/{rule-inspect-WFTVRK6B.js → rule-inspect-LJIGPTWS.js} +18 -14
  119. package/dist/chunks/{rules-AQYTFJI6.js → rules-6BMNO6M5.js} +11 -10
  120. package/dist/chunks/{schema-LUVFYPWN.js → schema-45SJNY5L.js} +9 -7
  121. package/dist/chunks/{schema-ZCDCJC7E.js → schema-HATXEQDP.js} +14 -11
  122. package/dist/chunks/set-C3UQUQ42.js +243 -0
  123. package/dist/chunks/{tags-RCNRFX7U.js → tags-BTVDROFG.js} +6 -5
  124. package/dist/chunks/{types-AJHILHO5.js → types-JGANJ5EQ.js} +12 -8
  125. package/dist/chunks/{update-I7QGAOYF.js → update-B6PSOHUW.js} +19 -15
  126. package/dist/commands/build/builder-worker.cjs +281 -0
  127. package/dist/commands/build/index.js +695 -236
  128. package/dist/commands/deploy/index.js +131 -50
  129. package/dist/commands/dev/index.js +677 -144
  130. package/dist/commands/env/index.js +1199 -565
  131. package/dist/commands/link/index.js +27 -22
  132. package/dist/commands/list/index.js +21 -14
  133. package/dist/commands-bulk.js +2051 -1019
  134. package/dist/help.js +1 -1
  135. package/dist/index.js +39 -33
  136. package/dist/version.mjs +1 -1
  137. package/package.json +48 -48
@@ -9,24 +9,27 @@ import {
9
9
  getCustomEnvironments,
10
10
  readStandardInput,
11
11
  require_dist as require_dist3
12
- } from "../../chunks/chunk-VLPLCJZC.js";
12
+ } from "../../chunks/chunk-ZSFEACZU.js";
13
13
  import {
14
14
  getInvalidSubcommand
15
15
  } from "../../chunks/chunk-VGIMO3ZK.js";
16
16
  import {
17
17
  ellipsis
18
- } from "../../chunks/chunk-KDYRLN6H.js";
18
+ } from "../../chunks/chunk-C5HKWXRR.js";
19
19
  import {
20
20
  formatTable
21
- } from "../../chunks/chunk-BBSS3XIW.js";
22
- import "../../chunks/chunk-VDJN4WKH.js";
21
+ } from "../../chunks/chunk-OQ3C5VXZ.js";
22
+ import "../../chunks/chunk-XRWOTCDO.js";
23
23
  import {
24
+ isGuidanceEnabled,
24
25
  suggestNextCommands
25
- } from "../../chunks/chunk-XBN2O34P.js";
26
+ } from "../../chunks/chunk-7ST552E3.js";
27
+ import {
28
+ formatEnvironment
29
+ } from "../../chunks/chunk-7R6M3BHM.js";
26
30
  import {
27
- formatEnvironment,
28
31
  validateLsArgs
29
- } from "../../chunks/chunk-RI7KKKII.js";
32
+ } from "../../chunks/chunk-O75LSD3C.js";
30
33
  import {
31
34
  validateJsonOutput
32
35
  } from "../../chunks/chunk-KXDWXXJH.js";
@@ -35,61 +38,85 @@ import {
35
38
  } from "../../chunks/chunk-YPQSDAEW.js";
36
39
  import {
37
40
  getCommandAliases
38
- } from "../../chunks/chunk-HURL5EBN.js";
39
- import "../../chunks/chunk-2MF3ZAVW.js";
40
- import "../../chunks/chunk-WC7IINFV.js";
41
- import "../../chunks/chunk-RIB4S2IB.js";
42
- import "../../chunks/chunk-GFCTRJI5.js";
43
- import "../../chunks/chunk-EG5BSAXD.js";
44
- import "../../chunks/chunk-M22O6CYY.js";
45
- import "../../chunks/chunk-GMWRTZVZ.js";
46
- import "../../chunks/chunk-3KNPVXJ3.js";
47
- import "../../chunks/chunk-3L2YLLHC.js";
48
- import "../../chunks/chunk-UMA66MKW.js";
49
- import "../../chunks/chunk-7QVJTI5H.js";
50
- import "../../chunks/chunk-O5GNPPTU.js";
51
- import {
52
- require_execa
53
- } from "../../chunks/chunk-R6IGDGX3.js";
41
+ } from "../../chunks/chunk-7HE63HCR.js";
42
+ import "../../chunks/chunk-7Q45OKWR.js";
43
+ import "../../chunks/chunk-GY5I4AYD.js";
44
+ import "../../chunks/chunk-CJV7J7B5.js";
45
+ import "../../chunks/chunk-EZKW5YJ2.js";
46
+ import "../../chunks/chunk-NFU4XJIR.js";
47
+ import "../../chunks/chunk-3HZLXCVL.js";
48
+ import "../../chunks/chunk-MTWHQEXI.js";
49
+ import "../../chunks/chunk-POOO7W47.js";
50
+ import "../../chunks/chunk-SLPSPYVR.js";
51
+ import "../../chunks/chunk-4KD5BYHB.js";
52
+ import "../../chunks/chunk-DWIC7MRV.js";
53
+ import "../../chunks/chunk-XM3LOQIX.js";
54
+ import "../../chunks/chunk-XDGOOW3K.js";
55
+ import "../../chunks/chunk-VP5Y3SZG.js";
54
56
  import {
55
57
  autoInstallVercelPlugin
56
- } from "../../chunks/chunk-HT2XWSAJ.js";
58
+ } from "../../chunks/chunk-7AEEQOD4.js";
59
+ import {
60
+ require_execa
61
+ } from "../../chunks/chunk-5XECIWME.js";
57
62
  import {
58
63
  stamp_default
59
64
  } from "../../chunks/chunk-64IF634X.js";
60
65
  import "../../chunks/chunk-VXYGCOKL.js";
61
- import "../../chunks/chunk-Y3J4VU2H.js";
66
+ import "../../chunks/chunk-FWKSJYDV.js";
62
67
  import {
63
68
  help
64
- } from "../../chunks/chunk-XI6NJLI4.js";
69
+ } from "../../chunks/chunk-2YRAWYGE.js";
65
70
  import {
71
+ ENV_VISIBILITY_DEPRECATION_MESSAGE,
72
+ SENSITIVE_ENV_VALUE_PLACEHOLDER,
66
73
  STANDARD_ENVIRONMENTS,
67
- addSubcommand,
68
- envCommand,
69
- envTargetChoices,
70
74
  formatProject,
75
+ formatVisibilityLabel,
76
+ getApiPublicPrefix,
77
+ getEnvKeyWarnings,
71
78
  getEnvRecords,
72
- getEnvTargetPlaceholder,
79
+ getFrameworkPublicPrefix,
80
+ getLocalSecretFallbackMessage,
81
+ getLocalSvelteKitPublicPrefixes,
82
+ getPublicPrefix,
83
+ getPublicPrefixSecretVisibilityError,
73
84
  getTeamById,
74
- isValidEnvTarget,
75
- listSubcommand,
85
+ getUnavailableSecretValuesMessage,
86
+ isFlagsSecretNeedingSplit,
87
+ isSecretEnvVar,
88
+ looksLikeSecret,
89
+ looksLikeSecretValue,
90
+ normalizeStdinEnvValue,
76
91
  param,
77
- parseEnvTargetArg,
78
92
  parseTarget,
79
93
  printAlignedLabel,
80
94
  pull,
81
95
  pullEnvRecords,
96
+ removePublicPrefix,
97
+ resolveEnvVarTypeOption,
98
+ resolveEnvVarVisibility,
99
+ resolveProjectContext,
100
+ shouldConfirmRotationBeforeDelete,
101
+ validateEnvValue
102
+ } from "../../chunks/chunk-VJ5NAOWB.js";
103
+ import {
104
+ addSubcommand,
105
+ envCommand,
106
+ envTargetChoices,
107
+ getEnvTargetPlaceholder,
108
+ isValidEnvTarget,
109
+ listSubcommand,
110
+ parseEnvTargetArg,
82
111
  pullSubcommand,
83
112
  removeSubcommand,
84
- require_frameworks,
85
- resolveProjectContext,
86
113
  runSubcommand,
87
114
  updateSubcommand
88
- } from "../../chunks/chunk-HMJVUXE6.js";
115
+ } from "../../chunks/chunk-FXD67VN5.js";
89
116
  import {
90
117
  TelemetryClient,
91
118
  require_dist as require_dist2
92
- } from "../../chunks/chunk-CYNB6LL4.js";
119
+ } from "../../chunks/chunk-XNFHNTS2.js";
93
120
  import {
94
121
  buildCommandWithYes,
95
122
  buildEnvAddCommandWithPreservedArgs,
@@ -99,25 +126,31 @@ import {
99
126
  getPreservedArgsForEnvRm,
100
127
  getPreservedArgsForEnvUpdate,
101
128
  outputActionRequired,
102
- outputAgentError
103
- } from "../../chunks/chunk-TH2XUVDP.js";
129
+ outputAgentError,
130
+ quoteArg,
131
+ redactEnvValueArgs,
132
+ withGlobalFlags
133
+ } from "../../chunks/chunk-NGGLYKNU.js";
104
134
  import {
105
135
  require_ms
106
136
  } from "../../chunks/chunk-GGP5R3FU.js";
107
137
  import {
108
138
  printError
109
- } from "../../chunks/chunk-VAFU7DXZ.js";
139
+ } from "../../chunks/chunk-AYLY3ZVL.js";
110
140
  import {
111
141
  parseArguments
112
- } from "../../chunks/chunk-XLKFJPMT.js";
142
+ } from "../../chunks/chunk-57RHXXXG.js";
143
+ import "../../chunks/chunk-RKDCNQ4S.js";
144
+ import {
145
+ isAPIError
146
+ } from "../../chunks/chunk-BMKU5KEL.js";
113
147
  import {
114
148
  getCommandName,
115
149
  getCommandNamePlain,
116
150
  getFlagsSpecification,
117
151
  getGlobalFlagsFromArgs,
118
- isAPIError,
119
152
  require_lib
120
- } from "../../chunks/chunk-SOFC4MLS.js";
153
+ } from "../../chunks/chunk-Q2DGFCO7.js";
121
154
  import "../../chunks/chunk-P4QNYOFB.js";
122
155
  import "../../chunks/chunk-52QYYTM5.js";
123
156
  import {
@@ -125,7 +158,7 @@ import {
125
158
  output_manager_default,
126
159
  prependEmoji,
127
160
  require_dist
128
- } from "../../chunks/chunk-OX7KI3LF.js";
161
+ } from "../../chunks/chunk-QFAS4OVW.js";
129
162
  import {
130
163
  require_source
131
164
  } from "../../chunks/chunk-S7KYDPEM.js";
@@ -203,180 +236,6 @@ function isKnownError(error) {
203
236
  return knownErrorsCodes.has(code.toUpperCase());
204
237
  }
205
238
 
206
- // src/util/env/validate-env.ts
207
- var import_frameworks = __toESM(require_frameworks(), 1);
208
- function getEnvValueWarnings(value) {
209
- const warnings = [];
210
- const normalized = value.replace(/\n$/, "");
211
- if (/^[ \t]+/.test(normalized)) {
212
- warnings.push({
213
- message: "starts with whitespace",
214
- requiresConfirmation: false
215
- });
216
- }
217
- if (/[ \t]+$/.test(normalized)) {
218
- warnings.push({
219
- message: "ends with whitespace",
220
- requiresConfirmation: false
221
- });
222
- }
223
- if (normalized.includes("\r") || normalized.includes("\n")) {
224
- warnings.push({
225
- message: "contains newlines",
226
- requiresConfirmation: false
227
- });
228
- }
229
- if (value.includes("\0")) {
230
- warnings.push({
231
- message: "contains null characters",
232
- requiresConfirmation: false
233
- });
234
- }
235
- if (value === "") {
236
- warnings.push({
237
- message: "is empty",
238
- requiresConfirmation: true
239
- });
240
- }
241
- if (value.length > 2 && (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))) {
242
- warnings.push({
243
- message: "includes surrounding quotes (these will be stored literally)",
244
- requiresConfirmation: false
245
- });
246
- }
247
- return warnings;
248
- }
249
- function formatWarnings(warnings) {
250
- if (warnings.length === 0)
251
- return null;
252
- const messages = warnings.map((w) => w.message);
253
- const startsIdx = messages.indexOf("starts with whitespace");
254
- const endsIdx = messages.indexOf("ends with whitespace");
255
- if (startsIdx !== -1 && endsIdx !== -1) {
256
- messages.splice(Math.max(startsIdx, endsIdx), 1);
257
- messages[Math.min(startsIdx, endsIdx)] = "starts and ends with whitespace";
258
- }
259
- if (messages.length === 1) {
260
- return `Value ${messages[0]}`;
261
- }
262
- if (messages.length === 2) {
263
- return `Value ${messages[0]} and ${messages[1]}`;
264
- }
265
- const last = messages.pop();
266
- return `Value ${messages.join(", ")}, and ${last}`;
267
- }
268
- var PUBLIC_PREFIXES = [
269
- ...new Set(
270
- import_frameworks.frameworkList.map((f) => f.envPrefix).filter((p) => !!p)
271
- )
272
- ];
273
- var SENSITIVE_PATTERN = /(?:^|_)(password|secret|private|token|key|auth|jwt|signature)(?:_|$)/i;
274
- function hasOnlyWhitespaceWarnings(warnings) {
275
- return warnings.length > 0 && warnings.every(
276
- (w) => w.message === "starts with whitespace" || w.message === "ends with whitespace"
277
- );
278
- }
279
- function trimValue(value) {
280
- return value.replace(/\n$/, "").trim();
281
- }
282
- function normalizeStdinEnvValue(value) {
283
- let valueWithoutTrailingNewline = value;
284
- if (value.endsWith("\r\n")) {
285
- valueWithoutTrailingNewline = value.slice(0, -2);
286
- } else if (value.endsWith("\n")) {
287
- valueWithoutTrailingNewline = value.slice(0, -1);
288
- } else {
289
- return {
290
- value,
291
- strippedTrailingNewline: false
292
- };
293
- }
294
- if (valueWithoutTrailingNewline.includes("\n") || valueWithoutTrailingNewline.includes("\r")) {
295
- return {
296
- value,
297
- strippedTrailingNewline: false
298
- };
299
- }
300
- return {
301
- value: valueWithoutTrailingNewline,
302
- strippedTrailingNewline: true
303
- };
304
- }
305
- function getPublicPrefix(key) {
306
- const upperKey = key.toUpperCase();
307
- return PUBLIC_PREFIXES.find((p) => upperKey.startsWith(p)) || null;
308
- }
309
- function removePublicPrefix(key) {
310
- const prefix = getPublicPrefix(key);
311
- if (!prefix)
312
- return key;
313
- return key.slice(prefix.length);
314
- }
315
- async function validateEnvValue(opts) {
316
- let finalValue = opts.initialValue;
317
- let alreadyConfirmed = false;
318
- if (!opts.skipConfirm) {
319
- let valueAccepted = false;
320
- while (!valueAccepted) {
321
- const valueWarnings = getEnvValueWarnings(finalValue);
322
- const warningMessage = formatWarnings(valueWarnings);
323
- if (!warningMessage) {
324
- valueAccepted = true;
325
- break;
326
- }
327
- opts.showWarning(warningMessage);
328
- const canTrim = hasOnlyWhitespaceWarnings(valueWarnings);
329
- const choices = canTrim ? [
330
- { name: "Leave as is", value: "c" },
331
- { name: "Re-enter", value: "r" },
332
- { name: "Trim whitespace", value: "t" }
333
- ] : [
334
- { name: "Leave as is", value: "c" },
335
- { name: "Re-enter", value: "r" }
336
- ];
337
- const action = await opts.selectAction(choices);
338
- if (action === "c") {
339
- valueAccepted = true;
340
- if (valueWarnings.some((w) => w.requiresConfirmation)) {
341
- alreadyConfirmed = true;
342
- }
343
- } else if (action === "t") {
344
- finalValue = trimValue(finalValue);
345
- opts.showLog("Trimmed whitespace");
346
- } else {
347
- finalValue = await opts.promptForValue();
348
- }
349
- }
350
- } else {
351
- const valueWarnings = getEnvValueWarnings(finalValue);
352
- const warningMessage = formatWarnings(valueWarnings);
353
- if (warningMessage) {
354
- opts.showWarning(warningMessage);
355
- }
356
- }
357
- return { finalValue, alreadyConfirmed };
358
- }
359
- function getEnvKeyWarnings(key) {
360
- const warnings = [];
361
- const matchingPrefix = getPublicPrefix(key);
362
- if (matchingPrefix) {
363
- const sensitiveMatch = SENSITIVE_PATTERN.exec(key);
364
- const nameWithoutPrefix = key.slice(matchingPrefix.length);
365
- if (sensitiveMatch) {
366
- warnings.push({
367
- message: `The ${matchingPrefix} prefix will make ${nameWithoutPrefix} visible to anyone visiting your site`,
368
- requiresConfirmation: true
369
- });
370
- } else {
371
- warnings.push({
372
- message: `${matchingPrefix} variables can be seen by anyone visiting your site`,
373
- requiresConfirmation: false
374
- });
375
- }
376
- }
377
- return warnings;
378
- }
379
-
380
239
  // src/util/telemetry/commands/env/add.ts
381
240
  var EnvAddTelemetryClient = class extends TelemetryClient {
382
241
  trackCliArgumentName(name) {
@@ -429,6 +288,15 @@ var EnvAddTelemetryClient = class extends TelemetryClient {
429
288
  });
430
289
  }
431
290
  }
291
+ trackCliOptionType(type) {
292
+ if (type) {
293
+ const validTypes = ["config", "secret"];
294
+ this.trackCliOption({
295
+ option: "type",
296
+ value: validTypes.includes(type) ? type : this.redactedValue
297
+ });
298
+ }
299
+ }
432
300
  trackCliFlagSensitive(sensitive) {
433
301
  if (sensitive) {
434
302
  this.trackCliFlag("sensitive");
@@ -459,100 +327,42 @@ var EnvAddTelemetryClient = class extends TelemetryClient {
459
327
  // src/commands/env/add.ts
460
328
  import { determineAgent } from "@vercel/detect-agent";
461
329
 
462
- // src/util/env/env-var-config-secret-ui.ts
463
- function formatVisibilityLabel(visibility, type) {
464
- const resolved = visibility ?? visibilityFromEnvType(type);
465
- if (resolved === "config") {
466
- return "Config";
467
- }
468
- if (resolved === "secret") {
469
- return "Secret";
470
- }
471
- return void 0;
330
+ // src/util/env/secret-storage-guidance.ts
331
+ function includesDevelopment(targets) {
332
+ return targets.length === 0 || targets.includes("development");
472
333
  }
473
- function visibilityFromEnvType(type) {
474
- if (type === "sensitive") {
475
- return "secret";
334
+ function getProductionSecretPolicyErrorKind(message) {
335
+ if (/production secrets?.*different value|different value.*production secrets?/i.test(
336
+ message
337
+ )) {
338
+ return "different-values";
476
339
  }
477
- if (type === "plain" || type === "encrypted") {
478
- return "config";
340
+ if (/production secrets?.*(?:own environment group|separat)|(?:own environment group|separat).*production secrets?/i.test(
341
+ message
342
+ )) {
343
+ return "separate-environments";
479
344
  }
480
- return void 0;
481
- }
482
- function hasNonDevelopmentTarget(envTargets) {
483
- return envTargets.some((target) => target !== "development");
345
+ return null;
484
346
  }
485
- function getPublicPrefixSecretVisibilityError(key, options) {
486
- const publicPrefix = getPublicPrefix(key);
487
- if (!publicPrefix) {
488
- return null;
489
- }
490
- const wouldBeSecret = options.visibility === "secret" || options.type === "sensitive";
491
- if (!wouldBeSecret) {
492
- return null;
493
- }
494
- const prefixLabel = publicPrefix.replace(/_$/, "");
495
- if (hasNonDevelopmentTarget(options.envTargets)) {
496
- return `Environment variables with a public framework prefix (${prefixLabel}) cannot use secret visibility on Production or Preview. Target Development only, rename to remove the public prefix, or use \`--visibility config\` with \`--no-sensitive\` on Development.`;
497
- }
498
- return `Environment variables with a public framework prefix (${prefixLabel}) cannot use secret visibility. Rename to remove the public prefix or use \`--visibility config\` with \`--no-sensitive\`.`;
347
+ function getProductionSecretPolicyRecovery(kind) {
348
+ return kind === "different-values" ? "Use different Secret values for Production and non-Production." : "Create separate Production and non-Production variables with different values.";
499
349
  }
500
- function shouldOmitInferredVisibility(key, envTargets, teamSensitivePolicyOn) {
501
- if (!getPublicPrefix(key)) {
502
- return false;
503
- }
504
- if (!hasNonDevelopmentTarget(envTargets)) {
505
- return false;
506
- }
507
- return teamSensitivePolicyOn;
350
+ function getSecretStorageChoice(targets, recommendedReason) {
351
+ const availability = includesDevelopment(targets) ? "hidden in the dashboard; Development values can be pulled" : "hidden in the dashboard and unavailable to pulls";
352
+ const recommendation = recommendedReason ? `; recommended ${recommendedReason}` : "";
353
+ return `Secret (${availability}${recommendation})`;
508
354
  }
509
- function resolveEnvVarVisibility(options) {
510
- if (options.explicitVisibility !== void 0) {
511
- if (options.explicitVisibility !== "config" && options.explicitVisibility !== "secret") {
512
- return {
513
- error: "The `--visibility` flag must be either `config` or `secret`."
514
- };
515
- }
516
- const publicPrefixError2 = getPublicPrefixSecretVisibilityError(
517
- options.key,
518
- {
519
- visibility: options.explicitVisibility,
520
- type: options.type,
521
- envTargets: options.envTargets
522
- }
523
- );
524
- if (publicPrefixError2) {
525
- return { error: publicPrefixError2 };
526
- }
527
- return { visibility: options.explicitVisibility };
528
- }
529
- const inferred = visibilityFromEnvType(options.type);
530
- if (inferred === void 0) {
531
- return {};
532
- }
533
- if (shouldOmitInferredVisibility(
534
- options.key,
535
- options.envTargets,
536
- options.teamSensitivePolicyOn
537
- )) {
538
- return {};
539
- }
540
- const publicPrefixError = getPublicPrefixSecretVisibilityError(options.key, {
541
- visibility: inferred,
542
- type: options.type,
543
- envTargets: options.envTargets
544
- });
545
- if (publicPrefixError) {
546
- return { error: publicPrefixError };
355
+ function getDefaultSecretStorageGuidance(targets) {
356
+ if (includesDevelopment(targets)) {
357
+ return "Stored as Secret by default. This value is hidden in the dashboard; Development values can be pulled. Use `--type config` for other values you need to read later.";
547
358
  }
548
- return { visibility: inferred };
359
+ return "Stored as Secret by default. This value is hidden in the dashboard and unavailable to pulls; use `--type config` for values you need to read later.";
549
360
  }
550
361
 
551
362
  // src/commands/env/add.ts
552
- var SENSITIVE_VALUE_HINT = "Sensitive values cannot be read later";
553
- var SENSITIVE_SECRET_PROMPT = `Store as sensitive? ${import_chalk.default.dim(
554
- SENSITIVE_VALUE_HINT
555
- )}`;
363
+ function looksLikeCredentialName(key, publicPrefix = getPublicPrefix(key)) {
364
+ return looksLikeSecret(publicPrefix ? key.slice(publicPrefix.length) : key);
365
+ }
556
366
  function filterEnvChoicesForSensitivity(choices, opts) {
557
367
  if (opts.policyOn) {
558
368
  return choices.filter((c) => c.value === "development");
@@ -583,19 +393,13 @@ function resolveFinalType(envTargets, isSensitive, opts) {
583
393
  }
584
394
  function fillEnvAddTemplate(template, opts) {
585
395
  const targetPlaceholder = getEnvTargetPlaceholder();
586
- return template.replace(/<name>/g, opts.envName ?? "<name>").split(targetPlaceholder).join(opts.envTargetArg ?? targetPlaceholder).replace(/<git-branch>/g, opts.envGitBranch ?? "<git-branch>").replace(/<gitbranch>/g, opts.envGitBranch ?? "<gitbranch>").replace(/<value>/g, "<value>");
587
- }
588
- function redactEnvValueArgs(argv) {
589
- const redacted = [...argv];
590
- for (let i = 0; i < redacted.length; i++) {
591
- if (redacted[i] === "--value" && i + 1 < redacted.length) {
592
- redacted[i + 1] = '"<value>"';
593
- i++;
594
- } else if (redacted[i].startsWith("--value=")) {
595
- redacted[i] = '--value="<value>"';
596
- }
597
- }
598
- return redacted;
396
+ return template.replace(/<name>/g, opts.envName ? quoteArg(opts.envName) : "<name>").split(targetPlaceholder).join(opts.envTargetArg ? quoteArg(opts.envTargetArg) : targetPlaceholder).replace(
397
+ /<git-branch>/g,
398
+ opts.envGitBranch ? quoteArg(opts.envGitBranch) : "<git-branch>"
399
+ ).replace(
400
+ /<gitbranch>/g,
401
+ opts.envGitBranch ? quoteArg(opts.envGitBranch) : "<gitbranch>"
402
+ ).replace(/<value>/g, "<value>");
599
403
  }
600
404
  function multiTargetSuggestion(argv, envName, targets, addNoSensitive) {
601
405
  const flag = addNoSensitive ? " --no-sensitive" : "";
@@ -628,9 +432,6 @@ function formatEnvironmentTarget(target, customEnvironments) {
628
432
  function formatEnvironmentTargets(envTargets, customEnvironments) {
629
433
  return envTargets.map((target) => formatEnvironmentTarget(target, customEnvironments)).join(", ");
630
434
  }
631
- function typeLabel(type) {
632
- return type === "sensitive" ? "Sensitive" : "Non-sensitive";
633
- }
634
435
  function printEnvAddResult(link, envName, envTargets, envGitBranch, customEnvironments, finalType, force, visibility) {
635
436
  output_manager_default.print("\n");
636
437
  printAlignedLabel(force ? "Overrode" : "Added", envName, { gutter: "\u2713" });
@@ -642,10 +443,9 @@ function printEnvAddResult(link, envName, envTargets, envGitBranch, customEnviro
642
443
  if (envGitBranch) {
643
444
  printAlignedLabel("Branch", envGitBranch);
644
445
  }
645
- printAlignedLabel("Type", typeLabel(finalType));
646
446
  const visibilityLabel = formatVisibilityLabel(visibility, finalType);
647
447
  if (visibilityLabel) {
648
- printAlignedLabel("Visibility", visibilityLabel);
448
+ printAlignedLabel("Type", visibilityLabel);
649
449
  }
650
450
  }
651
451
  function printEnvAddWarning(message) {
@@ -658,6 +458,13 @@ function promptEnvValue(client, opts) {
658
458
  ...opts.isSensitive ? { transformer: (value) => "*".repeat(value.length) } : {}
659
459
  });
660
460
  }
461
+ function buildHumanEnvAddCommand(argv, commandTemplate) {
462
+ const globalFlags = getGlobalFlagsFromArgs(argv.slice(2), {
463
+ preserveProject: true
464
+ }).filter((flag) => !flag.startsWith("--non-interactive"));
465
+ const suffix = globalFlags.length > 0 ? ` ${globalFlags.map(quoteArg).join(" ")}` : "";
466
+ return getCommandNamePlain(`${commandTemplate}${suffix}`);
467
+ }
661
468
  async function add(client, argv) {
662
469
  let parsedArgs;
663
470
  const flagsSpecification = getFlagsSpecification(addSubcommand.options);
@@ -685,6 +492,14 @@ async function add(client, argv) {
685
492
  const positionalGitBranch = args[2];
686
493
  const optionGitBranch = typeof opts["--git-branch"] === "string" ? opts["--git-branch"] : void 0;
687
494
  let envGitBranch = optionGitBranch ?? positionalGitBranch;
495
+ const forceSensitive = Boolean(opts["--sensitive"]);
496
+ const forceEncrypted = Boolean(opts["--no-sensitive"]);
497
+ const typeOption = resolveEnvVarTypeOption({
498
+ type: typeof opts["--type"] === "string" ? opts["--type"] : void 0,
499
+ visibility: typeof opts["--visibility"] === "string" ? opts["--visibility"] : void 0
500
+ });
501
+ let explicitType = typeOption.explicitVisibility;
502
+ let typeSource = explicitType || forceSensitive || forceEncrypted ? "argv" : void 0;
688
503
  const telemetryClient = new EnvAddTelemetryClient({
689
504
  opts: {
690
505
  store: client.telemetryEventStore
@@ -702,10 +517,47 @@ async function add(client, argv) {
702
517
  telemetryClient.trackCliFlagForce(opts["--force"]);
703
518
  telemetryClient.trackCliFlagGuidance(opts["--guidance"]);
704
519
  telemetryClient.trackCliFlagYes(opts["--yes"]);
520
+ telemetryClient.trackCliOptionType(
521
+ typeof opts["--type"] === "string" ? opts["--type"] : void 0
522
+ );
705
523
  telemetryClient.trackCliOptionVisibility(
706
524
  typeof opts["--visibility"] === "string" ? opts["--visibility"] : void 0
707
525
  );
708
526
  telemetryClient.trackCliOptionProject(opts["--project"]);
527
+ if (typeOption.error) {
528
+ if (client.nonInteractive) {
529
+ outputAgentError(
530
+ client,
531
+ {
532
+ status: "error",
533
+ reason: typeOption.errorReason ?? "invalid_type",
534
+ message: typeOption.error
535
+ },
536
+ 1
537
+ );
538
+ }
539
+ output_manager_default.fatal(typeOption.error);
540
+ return 1;
541
+ }
542
+ if (typeOption.usedDeprecatedVisibility) {
543
+ printEnvAddWarning(ENV_VISIBILITY_DEPRECATION_MESSAGE);
544
+ }
545
+ const typeConflictMessage = forceSensitive ? forceEncrypted ? "`--sensitive` and `--no-sensitive` cannot be used together. Pick one." : explicitType === "config" ? "`--type config` cannot be used with `--sensitive`. Pick one." : null : forceEncrypted && explicitType === "secret" ? "`--type secret` cannot be used with `--no-sensitive`. Pick one." : null;
546
+ if (typeConflictMessage) {
547
+ if (client.nonInteractive) {
548
+ outputAgentError(
549
+ client,
550
+ {
551
+ status: "error",
552
+ reason: "conflicting_type_flags",
553
+ message: typeConflictMessage
554
+ },
555
+ 1
556
+ );
557
+ }
558
+ output_manager_default.fatal(typeConflictMessage);
559
+ return 1;
560
+ }
709
561
  if (positionalGitBranch && optionGitBranch) {
710
562
  output_manager_default.error(
711
563
  "Git branch was provided twice. Use either `--git-branch <git-branch>` or the legacy third argument."
@@ -729,6 +581,7 @@ async function add(client, argv) {
729
581
  return 1;
730
582
  }
731
583
  let envTargets = envTargetArg ? parseEnvTargetArg(envTargetArg) : [];
584
+ let resolvedLink;
732
585
  if (client.nonInteractive) {
733
586
  const link2 = await resolveProjectContext({
734
587
  client,
@@ -779,9 +632,9 @@ async function add(client, argv) {
779
632
  {
780
633
  status: "error",
781
634
  reason: "not_linked",
782
- message: `Your codebase isn't linked to a project on Vercel. Run ${getCommandNamePlain(
635
+ message: `Your codebase isn't linked to a project on Vercel. Run \`${getCommandNamePlain(
783
636
  "link"
784
- )} to begin. Use --yes for non-interactive; use --scope or --project to specify team or project. Then run your env add command.`,
637
+ )}\` to begin. Use \`--yes\` for non-interactive mode; use \`--scope\` or \`--project\` to specify a team or project. Then run your \`env add\` command.`,
785
638
  next: [
786
639
  { command: buildCommandWithYes(linkArgv) },
787
640
  { command: buildCommandWithYes(envAddRetryArgv) }
@@ -792,6 +645,7 @@ async function add(client, argv) {
792
645
  }
793
646
  if (link2.status !== "linked")
794
647
  return 1;
648
+ resolvedLink = link2;
795
649
  const { project: project2 } = link2;
796
650
  const org = link2.org;
797
651
  client.config.currentTeam = org.type === "team" ? org.id : void 0;
@@ -913,7 +767,7 @@ async function add(client, argv) {
913
767
  status: "action_required",
914
768
  reason: "missing_requirements",
915
769
  missing,
916
- message: `Provide all required inputs for non-interactive mode: ${parts.join("; ")}. Example: ${filledTemplate}`,
770
+ message: `Provide all required inputs for non-interactive mode: ${parts.join("; ")}. Example: \`${filledTemplate}\``,
917
771
  next
918
772
  },
919
773
  1
@@ -926,147 +780,246 @@ async function add(client, argv) {
926
780
  validate: (val) => val ? true : "Name cannot be empty"
927
781
  });
928
782
  }
929
- const skipConfirm = opts["--yes"] || !!stdInput || valueFromFlag !== void 0;
930
- if (!skipConfirm) {
931
- let keyAccepted = false;
932
- while (!keyAccepted) {
933
- const keyWarnings = getEnvKeyWarnings(envName);
934
- const sensitiveWarning = keyWarnings.find((w) => w.requiresConfirmation);
935
- if (!sensitiveWarning) {
936
- for (const w of keyWarnings) {
937
- printEnvAddWarning(w.message);
938
- }
939
- keyAccepted = true;
940
- break;
783
+ if (!resolvedLink) {
784
+ const link2 = await resolveProjectContext({
785
+ client,
786
+ projectNameOrId: opts["--project"]
787
+ });
788
+ if (link2.status === "error") {
789
+ return link2.exitCode;
790
+ } else if (link2.status === "not_linked") {
791
+ if (client.nonInteractive) {
792
+ const preserved = getPreservedArgsForEnvAdd(client.argv);
793
+ const linkPreserved = preserved.filter((a, i) => {
794
+ if (a === "--value")
795
+ return false;
796
+ if (a.startsWith("--value="))
797
+ return false;
798
+ if (i > 0 && preserved[i - 1] === "--value")
799
+ return false;
800
+ return true;
801
+ });
802
+ const linkArgv = [
803
+ ...client.argv.slice(0, 2),
804
+ "link",
805
+ "--scope",
806
+ "<scope>",
807
+ ...linkPreserved
808
+ ];
809
+ outputAgentError(
810
+ client,
811
+ {
812
+ status: "error",
813
+ reason: "not_linked",
814
+ message: `Your codebase isn't linked to a project on Vercel. Run ${getCommandNamePlain(
815
+ "link"
816
+ )} to begin. Use --yes for non-interactive; use --scope or --project to specify team or project. Then run your env add command.`,
817
+ next: [
818
+ { command: buildCommandWithYes(linkArgv) },
819
+ { command: buildCommandWithYes(redactEnvValueArgs(client.argv)) }
820
+ ]
821
+ },
822
+ 1
823
+ );
824
+ } else {
825
+ output_manager_default.error(
826
+ `Your codebase isn\u2019t linked to a project on Vercel. Run ${getCommandName(
827
+ "link"
828
+ )} to begin.`
829
+ );
941
830
  }
831
+ return 1;
832
+ }
833
+ resolvedLink = link2;
834
+ }
835
+ const link = resolvedLink;
836
+ client.config.currentTeam = link.org.type === "team" ? link.org.id : void 0;
837
+ const { project } = link;
838
+ if (explicitType === "secret" || forceSensitive) {
839
+ const publicPrefixError = getPublicPrefixSecretVisibilityError(envName, {
840
+ visibility: explicitType === "secret" ? "secret" : void 0,
841
+ type: "sensitive",
842
+ context: "add"
843
+ });
844
+ if (publicPrefixError) {
845
+ if (client.nonInteractive) {
846
+ outputAgentError(
847
+ client,
848
+ {
849
+ status: "error",
850
+ reason: "invalid_type",
851
+ message: publicPrefixError
852
+ },
853
+ 1
854
+ );
855
+ }
856
+ output_manager_default.fatal(publicPrefixError);
857
+ return 1;
858
+ }
859
+ }
860
+ let keyAccepted = false;
861
+ while (!keyAccepted) {
862
+ const apiPublicPrefix2 = getApiPublicPrefix(envName);
863
+ const frameworkPublicPrefix = getFrameworkPublicPrefix(
864
+ project.framework,
865
+ envName
866
+ );
867
+ const globallyKnownPrefix = getPublicPrefix(envName);
868
+ const deferFrameworkSecretError = frameworkPublicPrefix !== null && (explicitType === "secret" || forceSensitive);
869
+ const keyWarnings = deferFrameworkSecretError || globallyKnownPrefix !== null && apiPublicPrefix2 === null && frameworkPublicPrefix === null ? [] : getEnvKeyWarnings(envName);
870
+ const sensitiveWarning = keyWarnings.find((w) => w.requiresConfirmation);
871
+ if (!sensitiveWarning) {
872
+ for (const warning of keyWarnings) {
873
+ printEnvAddWarning(warning.message);
874
+ }
875
+ keyAccepted = true;
876
+ break;
877
+ }
878
+ const nameWithoutPrefix = removePublicPrefix(envName);
879
+ const publicPrefix = getPublicPrefix(envName);
880
+ if (typeSource === "argv") {
881
+ for (const warning of keyWarnings) {
882
+ printEnvAddWarning(warning.message);
883
+ }
884
+ keyAccepted = true;
885
+ break;
886
+ }
887
+ const privateCommand = buildEnvAddCommandWithPreservedArgs(
888
+ client.argv,
889
+ `env add ${nameWithoutPrefix} ${envTargetArg ?? getEnvTargetPlaceholder()} --type secret --value "<value>" --yes`
890
+ );
891
+ const publicCommand = buildEnvAddCommandWithPreservedArgs(
892
+ client.argv,
893
+ `env add ${envName} ${envTargetArg ?? getEnvTargetPlaceholder()} --type config --value "<value>" --yes`
894
+ );
895
+ const humanTargetArg = envTargetArg ? ` ${envTargetArg}` : "";
896
+ const privateHumanCommand = buildHumanEnvAddCommand(
897
+ client.argv,
898
+ `env add ${nameWithoutPrefix}${humanTargetArg} --type secret`
899
+ );
900
+ const publicHumanCommand = buildHumanEnvAddCommand(
901
+ client.argv,
902
+ `env add ${envName}${humanTargetArg} --type config`
903
+ );
904
+ const message = `\`${envName}\` looks like a credential, and \`${publicPrefix}\` exposes its value to anyone visiting your site. Choose explicitly: rename to \`${nameWithoutPrefix}\` with \`--type secret\` to keep it private, or keep the name with \`--type config\` to expose it.`;
905
+ if (client.nonInteractive || opts["--yes"] || !!stdInput) {
942
906
  if (client.nonInteractive) {
943
- const nameWithoutPrefix2 = removePublicPrefix(envName);
944
907
  outputActionRequired(client, {
945
908
  status: "action_required",
946
- reason: "env_key_sensitive",
947
- message: `Key ${envName} may expose sensitive data (public prefix). Use --yes to keep as is, or rename to ${nameWithoutPrefix2}.`,
909
+ reason: "public_prefix_requires_type",
910
+ message,
948
911
  choices: [
949
- { id: "keep", name: "Leave as is (use --yes)" },
950
- { id: "rename", name: `Rename to ${nameWithoutPrefix2}` }
912
+ {
913
+ id: "private",
914
+ name: `Keep private: rename to ${nameWithoutPrefix} and use Secret`
915
+ },
916
+ {
917
+ id: "public",
918
+ name: `Expose publicly: keep ${envName} as Config`
919
+ }
951
920
  ],
952
921
  next: [
953
922
  {
954
- command: buildEnvAddCommandWithPreservedArgs(
955
- client.argv,
956
- `env add ${envName} ${getEnvTargetPlaceholder()} --value "<value>" --yes`
957
- ),
958
- when: "Leave as is"
923
+ command: privateCommand,
924
+ when: "Keep it private; replace <value> before running"
959
925
  },
960
926
  {
961
- command: buildEnvAddCommandWithPreservedArgs(
962
- client.argv,
963
- `env add ${nameWithoutPrefix2} ${getEnvTargetPlaceholder()} --value "<value>" --yes`
964
- ),
965
- when: "Rename"
927
+ command: publicCommand,
928
+ when: "Expose it publicly; replace <value> before running"
966
929
  }
967
930
  ]
968
931
  });
969
932
  }
970
- for (const w of keyWarnings) {
971
- printEnvAddWarning(w.message);
972
- }
973
- const nameWithoutPrefix = removePublicPrefix(envName);
974
- const choices2 = [
975
- { name: `Keep ${envName}`, value: "c" },
976
- { name: `Rename to ${nameWithoutPrefix}`, value: "p" },
977
- { name: "Re-enter name", value: "r" }
978
- ];
979
- const action = await client.input.select({
980
- message: "Variable name?",
981
- choices: choices2
982
- });
983
- if (action === "c") {
984
- keyAccepted = true;
985
- } else if (action === "p") {
986
- envName = nameWithoutPrefix;
987
- output_manager_default.log(`Renamed to ${envName}`);
988
- } else {
989
- envName = await client.input.text({
990
- message: `Name?`,
991
- validate: (val) => val ? true : "Name cannot be empty"
992
- });
993
- }
933
+ output_manager_default.fatal(message);
934
+ output_manager_default.print(` Keep it private:
935
+ ${privateHumanCommand}
936
+ `);
937
+ output_manager_default.print(` Expose it publicly:
938
+ ${publicHumanCommand}
939
+ `);
940
+ return 1;
994
941
  }
995
- } else {
996
- const keyWarnings = getEnvKeyWarnings(envName);
997
- for (const w of keyWarnings) {
998
- printEnvAddWarning(w.message);
942
+ for (const warning of keyWarnings) {
943
+ printEnvAddWarning(warning.message);
944
+ }
945
+ const action = await client.input.select({
946
+ message: "How should this variable be stored?",
947
+ choices: [
948
+ {
949
+ name: `Keep private: rename to ${nameWithoutPrefix} and use Secret`,
950
+ value: "p"
951
+ },
952
+ {
953
+ name: `Expose to anyone visiting your site: keep ${envName} as Config`,
954
+ value: "c"
955
+ },
956
+ { name: "Enter a different name", value: "r" }
957
+ ]
958
+ });
959
+ if (action === "p") {
960
+ envName = nameWithoutPrefix;
961
+ explicitType = "secret";
962
+ typeSource = "prompt";
963
+ output_manager_default.log(`Renamed to ${envName}`);
964
+ } else if (action === "c") {
965
+ explicitType = "config";
966
+ typeSource = "prompt";
967
+ keyAccepted = true;
968
+ } else {
969
+ envName = await client.input.text({
970
+ message: `Name?`,
971
+ validate: (val) => val ? true : "Name cannot be empty"
972
+ });
999
973
  }
1000
974
  }
1001
- const link = await resolveProjectContext({
1002
- client,
1003
- projectNameOrId: opts["--project"]
1004
- });
1005
- if (link.status === "error") {
1006
- return link.exitCode;
1007
- } else if (link.status === "not_linked") {
975
+ let customSveltePublicPrefix;
976
+ const apiPublicPrefix = getApiPublicPrefix(envName);
977
+ const matchingFrameworkPublicPrefix = getFrameworkPublicPrefix(
978
+ project.framework,
979
+ envName
980
+ );
981
+ if (matchingFrameworkPublicPrefix !== null && (explicitType === "secret" || forceSensitive)) {
982
+ const message = `\`${matchingFrameworkPublicPrefix}\` exposes this value to anyone visiting your site, so \`${envName}\` cannot be kept private as a Secret. Rename the variable without the framework's public prefix to keep it private, or use \`--type config\` only if the value is safe to expose.`;
1008
983
  if (client.nonInteractive) {
1009
- const preserved = getPreservedArgsForEnvAdd(client.argv);
1010
- const linkPreserved = preserved.filter((a, i) => {
1011
- if (a === "--value")
1012
- return false;
1013
- if (a.startsWith("--value="))
1014
- return false;
1015
- if (i > 0 && preserved[i - 1] === "--value")
1016
- return false;
1017
- return true;
1018
- });
1019
- const linkArgv = [
1020
- ...client.argv.slice(0, 2),
1021
- "link",
1022
- ...link.status === "not_linked" ? ["--scope", "<scope>"] : [],
1023
- ...linkPreserved
1024
- ];
1025
- let envAddRetryArgv = redactEnvValueArgs(client.argv);
1026
- if (envTargetArg === "preview" && envGitBranch === void 0) {
1027
- const argvArgs = client.argv.slice(2);
1028
- const addIdx = argvArgs.indexOf("add");
1029
- if (addIdx !== -1) {
1030
- let pos = addIdx + 1;
1031
- let positionals = 0;
1032
- while (pos < argvArgs.length && positionals < 3 && !argvArgs[pos].startsWith("-")) {
1033
- positionals++;
1034
- pos++;
1035
- }
1036
- const insertAt = 2 + pos;
1037
- envAddRetryArgv = redactEnvValueArgs([
1038
- ...client.argv.slice(0, insertAt),
1039
- "<gitbranch>",
1040
- ...client.argv.slice(insertAt)
1041
- ]);
1042
- }
1043
- }
1044
984
  outputAgentError(
1045
985
  client,
1046
- {
1047
- status: "error",
1048
- reason: "not_linked",
1049
- message: `Your codebase isn't linked to a project on Vercel. Run ${getCommandNamePlain(
1050
- "link"
1051
- )} to begin. Use --yes for non-interactive; use --scope or --project to specify team or project. Then run your env add command.`,
1052
- next: [
1053
- { command: buildCommandWithYes(linkArgv) },
1054
- { command: buildCommandWithYes(envAddRetryArgv) }
1055
- ]
1056
- },
986
+ { status: "error", reason: "invalid_type", message },
1057
987
  1
1058
988
  );
1059
- } else {
1060
- output_manager_default.error(
1061
- `Your codebase isn\u2019t linked to a project on Vercel. Run ${getCommandName(
1062
- "link"
1063
- )} to begin.`
989
+ }
990
+ output_manager_default.fatal(message);
991
+ return 1;
992
+ }
993
+ if (project.framework === "sveltekit" || project.framework === "sveltekit-1" || project.framework === "sveltekit-2") {
994
+ const localPublicPrefixes = await getLocalSvelteKitPublicPrefixes(
995
+ link.repoRoot ?? client.cwd,
996
+ project.rootDirectory
997
+ );
998
+ const matchingLocalPrefix = localPublicPrefixes?.find(
999
+ (prefix) => envName.startsWith(prefix)
1000
+ );
1001
+ if (matchingLocalPrefix !== void 0 && apiPublicPrefix === null && matchingFrameworkPublicPrefix === null) {
1002
+ customSveltePublicPrefix = matchingLocalPrefix;
1003
+ }
1004
+ }
1005
+ if (customSveltePublicPrefix !== void 0 && (explicitType === "secret" || forceSensitive)) {
1006
+ const message = customSveltePublicPrefix === "" ? "This SvelteKit project uses an empty `publicPrefix`, so every Environment Variable is exposed to the browser and cannot be kept private as a Secret. Change the SvelteKit `publicPrefix`, or use `--type config` only if the value is safe to expose." : `\`${customSveltePublicPrefix}\` exposes this value to anyone visiting your site, so \`${envName}\` cannot be kept private as a Secret. Rename the variable without the configured public prefix, or use \`--type config\` only if the value is safe to expose.`;
1007
+ if (client.nonInteractive) {
1008
+ outputAgentError(
1009
+ client,
1010
+ { status: "error", reason: "invalid_type", message },
1011
+ 1
1064
1012
  );
1065
1013
  }
1014
+ output_manager_default.fatal(message);
1066
1015
  return 1;
1067
1016
  }
1068
- client.config.currentTeam = link.org.type === "team" ? link.org.id : void 0;
1069
- const { project } = link;
1017
+ if (customSveltePublicPrefix !== void 0) {
1018
+ printEnvAddWarning(
1019
+ customSveltePublicPrefix === "" ? "This SvelteKit project uses an empty `publicPrefix`, so every Environment Variable is exposed to the browser." : `\`${customSveltePublicPrefix}\` variables are exposed to the browser by this SvelteKit project.`
1020
+ );
1021
+ }
1022
+ const skipConfirm = opts["--yes"] || !!stdInput || valueFromFlag !== void 0;
1070
1023
  const [{ envs }, customEnvironments] = await Promise.all([
1071
1024
  getEnvRecords(client, project.id, "vercel-cli:env:add"),
1072
1025
  getCustomEnvironments(client, project.id)
@@ -1154,50 +1107,54 @@ async function add(client, argv) {
1154
1107
  );
1155
1108
  return 1;
1156
1109
  }
1157
- const forceSensitive = Boolean(opts["--sensitive"]);
1158
- const forceEncrypted = Boolean(opts["--no-sensitive"]);
1159
- if (forceSensitive && forceEncrypted) {
1160
- output_manager_default.error(
1161
- `--sensitive and --no-sensitive cannot be used together. Pick one.`
1162
- );
1163
- return 1;
1164
- }
1165
- const explicitVisibility = typeof opts["--visibility"] === "string" ? opts["--visibility"] : void 0;
1166
- if (explicitVisibility === "secret" && forceEncrypted) {
1167
- output_manager_default.error(
1168
- "`--visibility secret` cannot be used with `--no-sensitive`. Pick one."
1169
- );
1170
- return 1;
1171
- }
1172
- if (explicitVisibility === "config" && forceSensitive) {
1173
- output_manager_default.error(
1174
- "`--visibility config` cannot be used with `--sensitive`. Pick one."
1175
- );
1176
- return 1;
1177
- }
1178
1110
  const policyOn = false;
1179
1111
  let teamSensitivePolicyOn = false;
1112
+ let disjunctiveProductionSecretPolicyOn = false;
1180
1113
  if (link.org.type === "team") {
1181
1114
  try {
1182
1115
  const team = await getTeamById(client, link.org.id);
1183
1116
  teamSensitivePolicyOn = team?.sensitiveEnvironmentVariablePolicy === "on";
1117
+ disjunctiveProductionSecretPolicyOn = team?.disjunctiveProductionSecretPolicy === "on";
1184
1118
  } catch {
1185
1119
  }
1186
1120
  }
1121
+ const userWasExplicit = forceSensitive || forceEncrypted || !!explicitType;
1122
+ const skipSensitivePrompt = userWasExplicit || client.nonInteractive || skipConfirm;
1187
1123
  const isDevelopmentOnlyTarget = envTargets.length === 1 && envTargets[0] === "development";
1188
- const userWasExplicit = forceSensitive || forceEncrypted;
1189
- const skipSensitivePrompt = userWasExplicit || client.nonInteractive || skipConfirm || isDevelopmentOnlyTarget;
1190
1124
  let isSensitive;
1191
1125
  if (forceSensitive) {
1192
1126
  isSensitive = true;
1193
1127
  } else if (forceEncrypted) {
1194
1128
  isSensitive = false;
1129
+ } else if (explicitType) {
1130
+ isSensitive = explicitType === "secret";
1131
+ } else if (apiPublicPrefix || matchingFrameworkPublicPrefix || customSveltePublicPrefix !== void 0) {
1132
+ isSensitive = false;
1133
+ explicitType = "config";
1134
+ typeSource = "inferred";
1195
1135
  } else if (isDevelopmentOnlyTarget) {
1196
1136
  isSensitive = false;
1137
+ typeSource = "inferred";
1197
1138
  } else if (skipSensitivePrompt) {
1198
1139
  isSensitive = true;
1140
+ typeSource = "default";
1199
1141
  } else {
1200
- isSensitive = await client.input.confirm(SENSITIVE_SECRET_PROMPT, true);
1142
+ const selectedType = await client.input.select({
1143
+ message: "Environment Variable type?",
1144
+ choices: [
1145
+ {
1146
+ name: getSecretStorageChoice(
1147
+ envTargets,
1148
+ looksLikeCredentialName(envName) ? "because this name looks like a credential" : void 0
1149
+ ),
1150
+ value: "secret"
1151
+ },
1152
+ { name: "Config (can be revealed after saving)", value: "config" }
1153
+ ]
1154
+ });
1155
+ isSensitive = selectedType === "secret";
1156
+ explicitType = selectedType;
1157
+ typeSource = "prompt";
1201
1158
  }
1202
1159
  if (envTargets.length > 0) {
1203
1160
  const compatibilityError = getTargetCompatibilityError(
@@ -1277,7 +1234,7 @@ async function add(client, argv) {
1277
1234
  }
1278
1235
  envValue = await promptEnvValue(client, { isSensitive });
1279
1236
  }
1280
- const { finalValue } = await validateEnvValue({
1237
+ let { finalValue } = await validateEnvValue({
1281
1238
  envName,
1282
1239
  initialValue: envValue,
1283
1240
  skipConfirm,
@@ -1398,13 +1355,189 @@ async function add(client, argv) {
1398
1355
  finalType = "sensitive";
1399
1356
  }
1400
1357
  }
1358
+ while (finalType === "encrypted" && (looksLikeCredentialName(envName, customSveltePublicPrefix) || looksLikeSecretValue(finalValue))) {
1359
+ printEnvAddWarning(
1360
+ "This name or value looks like a credential. Config values can be revealed after saving."
1361
+ );
1362
+ const publicPrefix = getApiPublicPrefix(envName) ?? getFrameworkPublicPrefix(project.framework, envName) ?? customSveltePublicPrefix;
1363
+ if (publicPrefix !== void 0 && typeSource === "inferred") {
1364
+ const privateName = envName.slice(publicPrefix.length);
1365
+ const privateCommand = buildEnvAddCommandWithPreservedArgs(
1366
+ client.argv,
1367
+ `env add ${privateName} ${envTargets.join(
1368
+ ","
1369
+ )} --type secret --value "<value>" --yes`
1370
+ );
1371
+ const publicCommand = buildEnvAddCommandWithPreservedArgs(
1372
+ client.argv,
1373
+ `env add ${envName} ${envTargets.join(
1374
+ ","
1375
+ )} --type config --value "<value>" --yes`
1376
+ );
1377
+ const privateHumanCommand = buildHumanEnvAddCommand(
1378
+ client.argv,
1379
+ `env add ${privateName} ${envTargets.join(",")} --type secret`
1380
+ );
1381
+ const publicHumanCommand = buildHumanEnvAddCommand(
1382
+ client.argv,
1383
+ `env add ${envName} ${envTargets.join(",")} --type config`
1384
+ );
1385
+ const message = publicPrefix === "" ? `\`${envName}\` looks like a credential, and this SvelteKit project exposes every Environment Variable to the browser. Change the SvelteKit \`publicPrefix\` to keep it private, or use \`--type config\` only if the value is safe to expose.` : `\`${envName}\` looks like a credential, and \`${publicPrefix}\` exposes its value to anyone visiting your site. Choose explicitly: rename to \`${privateName}\` with \`--type secret\` to keep it private, or keep the name with \`--type config\` to expose it.`;
1386
+ if (client.nonInteractive) {
1387
+ outputActionRequired(client, {
1388
+ status: "action_required",
1389
+ reason: "public_prefix_requires_type",
1390
+ message,
1391
+ next: [
1392
+ ...publicPrefix === "" ? [] : [
1393
+ {
1394
+ command: privateCommand,
1395
+ when: "Keep it private; replace <value> before running"
1396
+ }
1397
+ ],
1398
+ {
1399
+ command: publicCommand,
1400
+ when: "Expose it publicly; replace <value> before running"
1401
+ }
1402
+ ]
1403
+ });
1404
+ }
1405
+ if (opts["--yes"]) {
1406
+ output_manager_default.fatal(message);
1407
+ if (publicPrefix !== "") {
1408
+ output_manager_default.print(` Keep it private:
1409
+ ${privateHumanCommand}
1410
+ `);
1411
+ }
1412
+ output_manager_default.print(` Expose it publicly:
1413
+ ${publicHumanCommand}
1414
+ `);
1415
+ return 1;
1416
+ }
1417
+ const selectedAction = await client.input.select({
1418
+ message: "How should this variable be stored?",
1419
+ choices: [
1420
+ ...publicPrefix === "" ? [] : [
1421
+ {
1422
+ name: `Keep private: rename to ${privateName} and use Secret`,
1423
+ value: "private"
1424
+ }
1425
+ ],
1426
+ {
1427
+ name: `Expose to anyone visiting your site: keep ${envName} as Config`,
1428
+ value: "public"
1429
+ },
1430
+ { name: "Enter a different value", value: "reenter" }
1431
+ ]
1432
+ });
1433
+ if (selectedAction === "private") {
1434
+ envName = privateName;
1435
+ finalType = "sensitive";
1436
+ explicitType = "secret";
1437
+ typeSource = "prompt";
1438
+ output_manager_default.log(`Renamed to ${envName}`);
1439
+ break;
1440
+ }
1441
+ if (selectedAction === "reenter") {
1442
+ const reenteredValue = await promptEnvValue(client, {
1443
+ isSensitive: false
1444
+ });
1445
+ const validated = await validateEnvValue({
1446
+ envName,
1447
+ initialValue: reenteredValue,
1448
+ skipConfirm: false,
1449
+ promptForValue: () => promptEnvValue(client, { isSensitive: false }),
1450
+ selectAction: (choices2) => client.input.select({ message: "Value?", choices: choices2 }),
1451
+ showWarning: (msg) => printEnvAddWarning(msg),
1452
+ showLog: (msg) => output_manager_default.log(msg)
1453
+ });
1454
+ finalValue = validated.finalValue;
1455
+ continue;
1456
+ }
1457
+ } else if (typeSource !== "argv" && typeSource !== "prompt" && !opts["--yes"] && !client.nonInteractive) {
1458
+ const selectedType = await client.input.select({
1459
+ message: "Store this value as?",
1460
+ choices: [
1461
+ {
1462
+ name: getSecretStorageChoice(envTargets, "for this value"),
1463
+ value: "secret"
1464
+ },
1465
+ {
1466
+ name: "Config (can be revealed after saving)",
1467
+ value: "config"
1468
+ }
1469
+ ]
1470
+ });
1471
+ if (selectedType === "secret") {
1472
+ finalType = "sensitive";
1473
+ explicitType = "secret";
1474
+ typeSource = "prompt";
1475
+ }
1476
+ }
1477
+ break;
1478
+ }
1479
+ if (finalType === "sensitive" && customSveltePublicPrefix !== void 0 && envName.startsWith(customSveltePublicPrefix)) {
1480
+ printEnvAddWarning(
1481
+ "This SvelteKit project exposes this variable to the browser; the Secret type does not prevent that. Rename the variable without the configured public prefix to keep it private."
1482
+ );
1483
+ }
1484
+ if (isFlagsSecretNeedingSplit({
1485
+ key: envName,
1486
+ type: finalType,
1487
+ targets: envTargets.filter(isValidEnvTarget),
1488
+ customEnvironmentIds: envTargets.filter(
1489
+ (target) => !isValidEnvTarget(target)
1490
+ )
1491
+ })) {
1492
+ printEnvAddWarning(
1493
+ "FLAGS_SECRET should use a separate value for each environment so Development overrides cannot affect Preview or Production."
1494
+ );
1495
+ }
1496
+ const hasProduction = envTargets.includes("production");
1497
+ const hasNonProduction = envTargets.some((target) => target !== "production");
1498
+ if (finalType === "sensitive" && disjunctiveProductionSecretPolicyOn && hasProduction && hasNonProduction) {
1499
+ const message = "Your team requires Production and non-Production Secrets to be stored separately with different values. Run one command for Production and another for the remaining environments.";
1500
+ if (client.nonInteractive) {
1501
+ outputAgentError(
1502
+ client,
1503
+ {
1504
+ status: "error",
1505
+ reason: "production_secret_must_be_separate",
1506
+ message,
1507
+ next: [
1508
+ {
1509
+ command: buildEnvAddCommandWithPreservedArgs(
1510
+ client.argv,
1511
+ `env add ${envName} production --type secret --value "<production-value>" --yes`
1512
+ ),
1513
+ when: "Set the Production Secret"
1514
+ },
1515
+ {
1516
+ command: buildEnvAddCommandWithPreservedArgs(
1517
+ client.argv,
1518
+ `env add ${envName} ${envTargets.filter((target) => target !== "production").join(
1519
+ ","
1520
+ )} --type secret --value "<non-production-value>" --yes`
1521
+ ),
1522
+ when: "Set the non-Production Secret"
1523
+ }
1524
+ ]
1525
+ },
1526
+ 1
1527
+ );
1528
+ }
1529
+ output_manager_default.fatal(message);
1530
+ return 1;
1531
+ }
1401
1532
  const upsert = opts["--force"] ? "true" : "";
1402
1533
  const { visibility, error: visibilityError } = resolveEnvVarVisibility({
1403
- explicitVisibility,
1534
+ explicitVisibility: explicitType,
1535
+ explicitOptionSource: typeOption.source,
1404
1536
  type: finalType,
1405
1537
  key: envName,
1406
1538
  envTargets,
1407
- teamSensitivePolicyOn
1539
+ teamSensitivePolicyOn,
1540
+ context: "add"
1408
1541
  });
1409
1542
  if (visibilityError) {
1410
1543
  if (client.nonInteractive) {
@@ -1412,13 +1545,13 @@ async function add(client, argv) {
1412
1545
  client,
1413
1546
  {
1414
1547
  status: "error",
1415
- reason: "invalid_visibility",
1548
+ reason: "invalid_type",
1416
1549
  message: visibilityError
1417
1550
  },
1418
1551
  1
1419
1552
  );
1420
1553
  }
1421
- output_manager_default.error(visibilityError);
1554
+ output_manager_default.fatal(visibilityError);
1422
1555
  return 1;
1423
1556
  }
1424
1557
  try {
@@ -1436,13 +1569,18 @@ async function add(client, argv) {
1436
1569
  );
1437
1570
  } catch (err) {
1438
1571
  if (client.nonInteractive && isAPIError(err)) {
1439
- const reason = err.slug || (err.serverMessage?.toLowerCase().includes("branch") ? "branch_not_found" : "api_error");
1572
+ const productionSecretPolicyError = getProductionSecretPolicyErrorKind(
1573
+ err.serverMessage
1574
+ );
1575
+ const reason = productionSecretPolicyError ? productionSecretPolicyError === "different-values" ? "production_secret_requires_different_value" : "production_secret_must_be_separate" : err.slug || (err.serverMessage?.toLowerCase().includes("branch") ? "branch_not_found" : "api_error");
1440
1576
  outputAgentError(
1441
1577
  client,
1442
1578
  {
1443
1579
  status: "error",
1444
1580
  reason,
1445
- message: err.serverMessage
1581
+ message: productionSecretPolicyError ? `${err.serverMessage} ${getProductionSecretPolicyRecovery(
1582
+ productionSecretPolicyError
1583
+ )}` : err.serverMessage
1446
1584
  },
1447
1585
  1
1448
1586
  );
@@ -1463,13 +1601,30 @@ async function add(client, argv) {
1463
1601
  Boolean(opts["--force"]),
1464
1602
  visibility
1465
1603
  );
1466
- const { isAgent } = await determineAgent();
1467
- const guidanceMode = parsedArgs.flags["--guidance"] ?? isAgent;
1604
+ if (typeSource === "default") {
1605
+ output_manager_default.print(
1606
+ ` ${import_chalk.default.dim(getDefaultSecretStorageGuidance(envTargets))}
1607
+ `
1608
+ );
1609
+ }
1610
+ const { isAgent } = await determineAgent();
1611
+ const guidanceMode = isGuidanceEnabled(
1612
+ client,
1613
+ parsedArgs.flags["--guidance"],
1614
+ isAgent
1615
+ );
1468
1616
  if (guidanceMode) {
1469
- const projectFlag = opts["--project"] ? ` --project ${opts["--project"]}` : "";
1470
1617
  suggestNextCommands([
1471
- getCommandName(`env ls${projectFlag}`),
1472
- getCommandName(`env pull${projectFlag}`)
1618
+ {
1619
+ description: "List Environment Variables",
1620
+ command: withGlobalFlags(client, "env ls", { preserveProject: true })
1621
+ },
1622
+ {
1623
+ description: "Pull Development Environment Variables into .env.local",
1624
+ command: withGlobalFlags(client, "env pull", {
1625
+ preserveProject: true
1626
+ })
1627
+ }
1473
1628
  ]);
1474
1629
  }
1475
1630
  return 0;
@@ -1597,7 +1752,7 @@ async function ls(client, argv) {
1597
1752
  const jsonOutput = {
1598
1753
  envs: envs.map((env) => ({
1599
1754
  key: env.key,
1600
- value: isSensitiveEnvironmentVariable(env) ? void 0 : env.value,
1755
+ value: isSecretEnvVar(env) ? void 0 : env.value,
1601
1756
  type: env.type,
1602
1757
  visibility: env.visibility,
1603
1758
  target: env.target,
@@ -1622,13 +1777,31 @@ async function ls(client, argv) {
1622
1777
  }
1623
1778
  if (!asJson) {
1624
1779
  const { isAgent } = await determineAgent2();
1625
- const guidanceMode = parsedArgs.flags["--guidance"] ?? isAgent;
1780
+ const guidanceMode = isGuidanceEnabled(
1781
+ client,
1782
+ parsedArgs.flags["--guidance"],
1783
+ isAgent
1784
+ );
1626
1785
  if (guidanceMode) {
1627
- const projectFlag = projectName ? ` --project ${projectName}` : "";
1628
1786
  suggestNextCommands([
1629
- getCommandName(`env add${projectFlag}`),
1630
- getCommandName(`env rm${projectFlag}`),
1631
- getCommandName(`env pull${projectFlag}`)
1787
+ {
1788
+ description: "Add an Environment Variable",
1789
+ command: withGlobalFlags(client, "env add", {
1790
+ preserveProject: true
1791
+ })
1792
+ },
1793
+ {
1794
+ description: "Remove an Environment Variable",
1795
+ command: withGlobalFlags(client, "env rm", {
1796
+ preserveProject: true
1797
+ })
1798
+ },
1799
+ {
1800
+ description: "Pull Development Environment Variables into .env.local",
1801
+ command: withGlobalFlags(client, "env pull", {
1802
+ preserveProject: true
1803
+ })
1804
+ }
1632
1805
  ]);
1633
1806
  }
1634
1807
  }
@@ -1649,7 +1822,7 @@ function getTable(link, records, customEnvironments) {
1649
1822
  }
1650
1823
  function getRow(link, env, customEnvironments) {
1651
1824
  let value;
1652
- if (isSensitiveEnvironmentVariable(env)) {
1825
+ if (isSecretEnvVar(env)) {
1653
1826
  value = import_chalk2.default.gray.italic("Hidden");
1654
1827
  } else if (env.type === "system") {
1655
1828
  value = import_chalk2.default.gray.italic(env.value);
@@ -1666,14 +1839,14 @@ function getRow(link, env, customEnvironments) {
1666
1839
  env.createdAt ? `${(0, import_ms.default)(now - env.createdAt)} ago` : ""
1667
1840
  ];
1668
1841
  }
1669
- function isSensitiveEnvironmentVariable(env) {
1670
- return env.type === "sensitive" || env.visibility === "secret";
1671
- }
1672
1842
  function getEnvironmentVariableTypeLabel(env) {
1673
- if (isSensitiveEnvironmentVariable(env)) {
1674
- return "Sensitive";
1843
+ if (isSecretEnvVar(env)) {
1844
+ return "Secret";
1845
+ }
1846
+ if (env.type === "system") {
1847
+ return "System";
1675
1848
  }
1676
- return env.type === "system" ? "System" : "Non-sensitive";
1849
+ return "Config";
1677
1850
  }
1678
1851
 
1679
1852
  // src/commands/env/rm.ts
@@ -1724,6 +1897,10 @@ var EnvRmTelemetryClient = class extends TelemetryClient {
1724
1897
  };
1725
1898
 
1726
1899
  // src/commands/env/rm.ts
1900
+ function printEnvRmWarning(message) {
1901
+ output_manager_default.print(`${import_chalk3.default.yellow("!")} ${message}
1902
+ `);
1903
+ }
1727
1904
  async function rm(client, argv) {
1728
1905
  const telemetryClient = new EnvRmTelemetryClient({
1729
1906
  opts: {
@@ -1757,9 +1934,9 @@ async function rm(client, argv) {
1757
1934
  {
1758
1935
  status: "error",
1759
1936
  reason: "invalid_arguments",
1760
- message: `Invalid number of arguments. Usage: ${getCommandNamePlain(
1937
+ message: `Invalid number of arguments. Usage: \`${getCommandNamePlain(
1761
1938
  `env rm <name> ${getEnvTargetPlaceholder()} <gitbranch>`
1762
- )}`
1939
+ )}\``
1763
1940
  },
1764
1941
  1
1765
1942
  );
@@ -1800,9 +1977,9 @@ async function rm(client, argv) {
1800
1977
  {
1801
1978
  status: "error",
1802
1979
  reason: "not_linked",
1803
- message: `Your codebase isn't linked to a project on Vercel. Run ${getCommandNamePlain(
1980
+ message: `Your codebase isn't linked to a project on Vercel. Run \`${getCommandNamePlain(
1804
1981
  "link"
1805
- )} to begin. Use --yes for non-interactive; use --scope or --project to specify team or project.`,
1982
+ )}\` to begin. Use \`--yes\` for non-interactive; use \`--scope\` or \`--project\` to specify team or project.`,
1806
1983
  next: [
1807
1984
  { command: buildCommandWithYes(linkArgv) },
1808
1985
  { command: buildCommandWithYes(client.argv) }
@@ -1828,7 +2005,7 @@ async function rm(client, argv) {
1828
2005
  {
1829
2006
  status: "action_required",
1830
2007
  reason: "missing_name",
1831
- message: "Provide the variable name as an argument. Example: vercel env rm <name> --yes",
2008
+ message: "Provide the variable name as an argument. Example: `vercel env rm <name> --yes`",
1832
2009
  next: [
1833
2010
  {
1834
2011
  command: buildEnvRmCommandWithPreservedArgs(
@@ -1903,6 +2080,15 @@ async function rm(client, argv) {
1903
2080
  envs = envs.filter((env2) => env2.id === id);
1904
2081
  }
1905
2082
  const env = envs[0];
2083
+ const shouldWarnAboutRotation = shouldConfirmRotationBeforeDelete({
2084
+ key: env.key,
2085
+ type: env.type,
2086
+ hasPublicPrefix: getPublicPrefix(env.key) !== null
2087
+ });
2088
+ const rotationWarning = "Removing this variable from Vercel does not revoke the credential. Rotate or disable it at its provider.";
2089
+ if (shouldWarnAboutRotation) {
2090
+ printEnvRmWarning(rotationWarning);
2091
+ }
1906
2092
  const skipConfirmation = opts["--yes"];
1907
2093
  if (!skipConfirmation) {
1908
2094
  if (client.nonInteractive) {
@@ -1911,18 +2097,18 @@ async function rm(client, argv) {
1911
2097
  {
1912
2098
  status: "action_required",
1913
2099
  reason: "confirmation_required",
1914
- message: `Removing Environment Variable ${env.key}. Use --yes to confirm.`,
2100
+ message: `Removing Environment Variable ${env.key}. ${shouldWarnAboutRotation ? `${rotationWarning} ` : ""}Use --yes to confirm.`,
1915
2101
  next: [{ command: buildCommandWithYes(client.argv) }]
1916
2102
  },
1917
2103
  1
1918
2104
  );
1919
2105
  }
1920
2106
  if (!await client.input.confirm(
1921
- `Removing Environment Variable ${param(env.key)} from ${formatEnvironments(
2107
+ `Remove ${param(env.key)} from ${formatEnvironments(
1922
2108
  link,
1923
2109
  env,
1924
2110
  customEnvironments
1925
- )} in Project ${import_chalk3.default.bold(project.name)}. Are you sure?`,
2111
+ )} in Project ${import_chalk3.default.bold(project.name)}?`,
1926
2112
  false
1927
2113
  )) {
1928
2114
  output_manager_default.log("Canceled");
@@ -1964,7 +2150,21 @@ async function rm(client, argv) {
1964
2150
 
1965
2151
  // src/commands/env/run.ts
1966
2152
  var import_env = __toESM(require_dist3(), 1);
2153
+ var import_chalk4 = __toESM(require_source(), 1);
1967
2154
  var import_execa = __toESM(require_execa(), 1);
2155
+ function printEnvRunWarning(message) {
2156
+ output_manager_default.print(`${import_chalk4.default.yellow("!")} ${message}
2157
+ `);
2158
+ }
2159
+ function omitUnavailableSecretPlaceholders(localEnv, secretKeys) {
2160
+ const safeLocalEnv = { ...localEnv };
2161
+ for (const key of secretKeys) {
2162
+ if (safeLocalEnv[key] === SENSITIVE_ENV_VALUE_PLACEHOLDER) {
2163
+ delete safeLocalEnv[key];
2164
+ }
2165
+ }
2166
+ return safeLocalEnv;
2167
+ }
1968
2168
  function parseRunArgs(argv) {
1969
2169
  const argvIndex = argv.indexOf("--");
1970
2170
  const hasDoubleDash = argvIndex !== -1;
@@ -1993,6 +2193,16 @@ async function run(client, telemetry) {
1993
2193
  return 1;
1994
2194
  }
1995
2195
  if (userCommand.length === 0) {
2196
+ outputActionRequired(
2197
+ client,
2198
+ {
2199
+ status: "action_required",
2200
+ reason: "missing_command",
2201
+ message: "No command provided. Use `--` to separate Vercel flags from your command.",
2202
+ next: [{ command: getCommandNamePlain("env run -- <command>") }]
2203
+ },
2204
+ 1
2205
+ );
1996
2206
  output_manager_default.error(
1997
2207
  `No command provided. Use \`--\` to separate vercel flags from your command.`
1998
2208
  );
@@ -2007,6 +2217,16 @@ async function run(client, telemetry) {
2007
2217
  if (link.status === "error") {
2008
2218
  return link.exitCode;
2009
2219
  } else if (link.status === "not_linked") {
2220
+ outputActionRequired(
2221
+ client,
2222
+ {
2223
+ status: "action_required",
2224
+ reason: "not_linked",
2225
+ message: "Your codebase isn't linked to a project on Vercel. Run `vercel link`, then retry this command.",
2226
+ next: [{ command: getCommandNamePlain("link") }]
2227
+ },
2228
+ 1
2229
+ );
2010
2230
  output_manager_default.error(
2011
2231
  `Your codebase isn't linked to a project on Vercel. Run ${getCommandName(
2012
2232
  "link"
@@ -2040,6 +2260,45 @@ async function run(client, telemetry) {
2040
2260
  } catch (err) {
2041
2261
  output_manager_default.debug(`Failed to load local env files: ${err}`);
2042
2262
  }
2263
+ const localPlaceholderKeys = Object.entries(localEnv).filter(([, value]) => value === SENSITIVE_ENV_VALUE_PLACEHOLDER).map(([key]) => key);
2264
+ const safeLocalEnv = omitUnavailableSecretPlaceholders(
2265
+ localEnv,
2266
+ localPlaceholderKeys
2267
+ );
2268
+ const processPlaceholderKeys = Object.keys(records.env).filter(
2269
+ (key) => process.env[key] === SENSITIVE_ENV_VALUE_PLACEHOLDER
2270
+ );
2271
+ const safeProcessEnv = omitUnavailableSecretPlaceholders(
2272
+ process.env,
2273
+ processPlaceholderKeys
2274
+ );
2275
+ const unavailableCandidateKeys = new Set(
2276
+ Object.entries(records.env).filter(
2277
+ ([key, value]) => !value && !safeLocalEnv[key] && !safeProcessEnv[key]
2278
+ ).map(([key]) => key)
2279
+ );
2280
+ if (unavailableCandidateKeys.size > 0) {
2281
+ try {
2282
+ const { envs } = await getEnvRecords(
2283
+ client,
2284
+ link.project.id,
2285
+ "vercel-cli:env:run",
2286
+ { target: environment, gitBranch }
2287
+ );
2288
+ const unavailableSecretKeys = envs.filter(
2289
+ (env) => isSecretEnvVar(env) && unavailableCandidateKeys.has(env.key)
2290
+ );
2291
+ if (unavailableSecretKeys.length > 0) {
2292
+ printEnvRunWarning(
2293
+ `${getUnavailableSecretValuesMessage(
2294
+ environment,
2295
+ unavailableSecretKeys.length
2296
+ )}${getLocalSecretFallbackMessage(unavailableSecretKeys.length)}`
2297
+ );
2298
+ }
2299
+ } catch {
2300
+ }
2301
+ }
2043
2302
  try {
2044
2303
  const result = await (0, import_execa.default)(userCommand[0], userCommand.slice(1), {
2045
2304
  cwd: client.cwd,
@@ -2047,8 +2306,8 @@ async function run(client, telemetry) {
2047
2306
  reject: false,
2048
2307
  env: {
2049
2308
  ...records.env,
2050
- ...localEnv,
2051
- ...process.env
2309
+ ...safeLocalEnv,
2310
+ ...safeProcessEnv
2052
2311
  }
2053
2312
  });
2054
2313
  if (result instanceof Error && typeof result.exitCode !== "number") {
@@ -2063,10 +2322,10 @@ async function run(client, telemetry) {
2063
2322
  }
2064
2323
 
2065
2324
  // src/commands/env/update.ts
2066
- var import_chalk4 = __toESM(require_source(), 1);
2325
+ var import_chalk5 = __toESM(require_source(), 1);
2067
2326
 
2068
2327
  // src/util/env/update-env-record.ts
2069
- var import_constants2 = __toESM(require_dist2(), 1);
2328
+ var import_constants3 = __toESM(require_dist2(), 1);
2070
2329
  async function updateEnvRecord(client, projectId, envId, type, key, value, targets, gitBranch, visibility) {
2071
2330
  output_manager_default.debug(
2072
2331
  `Updating ${type} Environment Variable ${key} in ${targets.length} targets`
@@ -2074,7 +2333,7 @@ async function updateEnvRecord(client, projectId, envId, type, key, value, targe
2074
2333
  const target = [];
2075
2334
  const customEnvironmentIds = [];
2076
2335
  for (const t of targets) {
2077
- const arr = import_constants2.PROJECT_ENV_TARGET.includes(t) ? target : customEnvironmentIds;
2336
+ const arr = import_constants3.PROJECT_ENV_TARGET.includes(t) ? target : customEnvironmentIds;
2078
2337
  arr.push(t);
2079
2338
  }
2080
2339
  const body = {
@@ -2150,9 +2409,51 @@ var EnvUpdateTelemetryClient = class extends TelemetryClient {
2150
2409
  });
2151
2410
  }
2152
2411
  }
2412
+ trackCliOptionType(type) {
2413
+ if (type) {
2414
+ const validTypes = ["config", "secret"];
2415
+ this.trackCliOption({
2416
+ option: "type",
2417
+ value: validTypes.includes(type) ? type : this.redactedValue
2418
+ });
2419
+ }
2420
+ }
2153
2421
  };
2154
2422
 
2155
2423
  // src/commands/env/update.ts
2424
+ function looksLikeCredentialName2(key, publicPrefix = getPublicPrefix(key)) {
2425
+ return looksLikeSecret(publicPrefix ? key.slice(publicPrefix.length) : key);
2426
+ }
2427
+ function printEnvUpdateWarning(message) {
2428
+ output_manager_default.print(`${import_chalk5.default.yellow("!")} ${message}
2429
+ `);
2430
+ }
2431
+ function omitEnvValueArgs(argv) {
2432
+ const out = [];
2433
+ for (let i = 0; i < argv.length; i++) {
2434
+ if (argv[i] === "--value") {
2435
+ i++;
2436
+ continue;
2437
+ }
2438
+ if (argv[i].startsWith("--value="))
2439
+ continue;
2440
+ out.push(argv[i]);
2441
+ }
2442
+ return out;
2443
+ }
2444
+ function formatTargetArg(targets, customEnvironments) {
2445
+ return targets.map(
2446
+ (target) => customEnvironments.find(
2447
+ (environment) => environment.id === target || environment.slug === target
2448
+ )?.slug ?? target
2449
+ ).join(",");
2450
+ }
2451
+ function promptEnvUpdateValue(client, envName, isSecret) {
2452
+ return client.input.text({
2453
+ message: `What's the new value of ${envName}?`,
2454
+ ...isSecret ? { transformer: (value) => "*".repeat(value.length) } : {}
2455
+ });
2456
+ }
2156
2457
  async function update(client, argv) {
2157
2458
  let parsedArgs;
2158
2459
  const flagsSpecification = getFlagsSpecification(updateSubcommand.options);
@@ -2177,6 +2478,12 @@ async function update(client, argv) {
2177
2478
  const valueFromFlag = typeof opts["--value"] === "string" ? opts["--value"] : void 0;
2178
2479
  const stdInput = await readStandardInput(client.stdin);
2179
2480
  let [envName, envTargetArg, envGitBranch] = args;
2481
+ const typeOption = resolveEnvVarTypeOption({
2482
+ type: typeof opts["--type"] === "string" ? opts["--type"] : void 0,
2483
+ visibility: typeof opts["--visibility"] === "string" ? opts["--visibility"] : void 0
2484
+ });
2485
+ let explicitType = typeOption.explicitVisibility;
2486
+ const typeWasExplicit = explicitType !== void 0 || Boolean(opts["--sensitive"]);
2180
2487
  const telemetryClient = new EnvUpdateTelemetryClient({
2181
2488
  opts: {
2182
2489
  store: client.telemetryEventStore
@@ -2187,10 +2494,49 @@ async function update(client, argv) {
2187
2494
  telemetryClient.trackCliArgumentGitBranch(envGitBranch);
2188
2495
  telemetryClient.trackCliFlagSensitive(opts["--sensitive"]);
2189
2496
  telemetryClient.trackCliFlagYes(opts["--yes"]);
2190
- telemetryClient.trackCliOptionValue(valueFromFlag);
2497
+ telemetryClient.trackCliOptionValue(
2498
+ valueFromFlag === void 0 ? void 0 : "<redacted>"
2499
+ );
2500
+ telemetryClient.trackCliOptionType(
2501
+ typeof opts["--type"] === "string" ? opts["--type"] : void 0
2502
+ );
2191
2503
  telemetryClient.trackCliOptionVisibility(
2192
2504
  typeof opts["--visibility"] === "string" ? opts["--visibility"] : void 0
2193
2505
  );
2506
+ if (typeOption.error) {
2507
+ if (client.nonInteractive) {
2508
+ outputAgentError(
2509
+ client,
2510
+ {
2511
+ status: "error",
2512
+ reason: typeOption.errorReason ?? "invalid_type",
2513
+ message: typeOption.error
2514
+ },
2515
+ 1
2516
+ );
2517
+ }
2518
+ output_manager_default.fatal(typeOption.error);
2519
+ return 1;
2520
+ }
2521
+ if (typeOption.usedDeprecatedVisibility) {
2522
+ printEnvUpdateWarning(ENV_VISIBILITY_DEPRECATION_MESSAGE);
2523
+ }
2524
+ if (explicitType === "config" && opts["--sensitive"]) {
2525
+ const message = "`--type config` cannot be used with `--sensitive`. Pick one.";
2526
+ if (client.nonInteractive) {
2527
+ outputAgentError(
2528
+ client,
2529
+ {
2530
+ status: "error",
2531
+ reason: "conflicting_type_flags",
2532
+ message
2533
+ },
2534
+ 1
2535
+ );
2536
+ }
2537
+ output_manager_default.fatal(message);
2538
+ return 1;
2539
+ }
2194
2540
  if (args.length > 3) {
2195
2541
  if (client.nonInteractive) {
2196
2542
  outputAgentError(
@@ -2198,9 +2544,9 @@ async function update(client, argv) {
2198
2544
  {
2199
2545
  status: "error",
2200
2546
  reason: "invalid_arguments",
2201
- message: `Invalid number of arguments. Usage: ${getCommandNamePlain(
2547
+ message: `Invalid number of arguments. Usage: \`${getCommandNamePlain(
2202
2548
  `env update <name> ${getEnvTargetPlaceholder()} <gitbranch>`
2203
- )}`
2549
+ )}\``
2204
2550
  },
2205
2551
  1
2206
2552
  );
@@ -2292,9 +2638,9 @@ async function update(client, argv) {
2292
2638
  return link.exitCode;
2293
2639
  } else if (link.status === "not_linked") {
2294
2640
  if (client.nonInteractive) {
2295
- const preserved = getPreservedArgsForEnvUpdate(client.argv).filter(
2296
- (a) => a !== "--yes" && a !== "-y"
2297
- );
2641
+ const preserved = omitEnvValueArgs(
2642
+ getPreservedArgsForEnvUpdate(client.argv)
2643
+ ).filter((a) => a !== "--yes" && a !== "-y");
2298
2644
  const linkArgv = [
2299
2645
  ...client.argv.slice(0, 2),
2300
2646
  "link",
@@ -2312,7 +2658,9 @@ async function update(client, argv) {
2312
2658
  )} to begin. Use --yes for non-interactive; use --scope or --project to specify team or project.`,
2313
2659
  next: [
2314
2660
  { command: buildCommandWithYes(linkArgv) },
2315
- { command: buildCommandWithYes(client.argv) }
2661
+ {
2662
+ command: buildCommandWithYes(redactEnvValueArgs(client.argv))
2663
+ }
2316
2664
  ]
2317
2665
  },
2318
2666
  1
@@ -2395,7 +2743,7 @@ async function update(client, argv) {
2395
2743
  {
2396
2744
  command: buildEnvUpdateCommandWithPreservedArgs(
2397
2745
  client.argv,
2398
- `env update ${envName} ${getEnvTargetPlaceholder()} <gitbranch>`
2746
+ `env update ${envName} ${getEnvTargetPlaceholder()} <gitbranch> --value "<value>" --yes`
2399
2747
  )
2400
2748
  }
2401
2749
  ]
@@ -2430,7 +2778,7 @@ async function update(client, argv) {
2430
2778
  {
2431
2779
  command: buildEnvUpdateCommandWithPreservedArgs(
2432
2780
  client.argv,
2433
- `env update ${envName} ${getEnvTargetPlaceholder()} <gitbranch>`
2781
+ `env update ${envName} ${getEnvTargetPlaceholder()} <gitbranch> --value "<value>" --yes`
2434
2782
  )
2435
2783
  }
2436
2784
  ]
@@ -2451,15 +2799,178 @@ async function update(client, argv) {
2451
2799
  });
2452
2800
  selectedEnv = matchingEnvs[selectedIndex];
2453
2801
  }
2802
+ let customSveltePublicPrefix;
2803
+ const apiPublicPrefix = getApiPublicPrefix(envName);
2804
+ const frameworkPublicPrefix = getFrameworkPublicPrefix(
2805
+ project.framework,
2806
+ envName
2807
+ );
2808
+ if (project.framework === "sveltekit" || project.framework === "sveltekit-1" || project.framework === "sveltekit-2") {
2809
+ const localPublicPrefixes = await getLocalSvelteKitPublicPrefixes(
2810
+ link.repoRoot ?? client.cwd,
2811
+ project.rootDirectory
2812
+ );
2813
+ const matchingLocalPrefix = localPublicPrefixes?.find(
2814
+ (prefix) => envName.startsWith(prefix)
2815
+ );
2816
+ if (matchingLocalPrefix !== void 0 && apiPublicPrefix === null && frameworkPublicPrefix === null) {
2817
+ customSveltePublicPrefix = matchingLocalPrefix;
2818
+ }
2819
+ }
2820
+ const targets = Array.isArray(selectedEnv.target) ? selectedEnv.target : [selectedEnv.target].filter(
2821
+ (r) => Boolean(r)
2822
+ );
2823
+ const allTargets = [...targets, ...selectedEnv.customEnvironmentIds || []];
2824
+ const selectedEnvIsSecret = isSecretEnvVar(selectedEnv);
2825
+ if (explicitType === "config" && selectedEnvIsSecret) {
2826
+ const removeTargetArg = envTargetArg || targets[0] || allTargets[0] || getEnvTargetPlaceholder();
2827
+ const addTargetArg = formatTargetArg(allTargets, customEnvironments) || removeTargetArg;
2828
+ const removeBranchArg = selectedEnv.gitBranch ? ` ${quoteArg(selectedEnv.gitBranch)}` : "";
2829
+ const addBranchArg = selectedEnv.gitBranch ? ` --git-branch ${quoteArg(selectedEnv.gitBranch)}` : "";
2830
+ const globalFlags = getGlobalFlagsFromArgs(client.argv.slice(2), {
2831
+ preserveProject: true
2832
+ });
2833
+ const humanGlobalFlags = globalFlags.filter(
2834
+ (flag) => !flag.startsWith("--non-interactive")
2835
+ );
2836
+ const globalSuffix = globalFlags.length > 0 ? ` ${globalFlags.map(quoteArg).join(" ")}` : "";
2837
+ const humanGlobalSuffix = humanGlobalFlags.length > 0 ? ` ${humanGlobalFlags.map(quoteArg).join(" ")}` : "";
2838
+ const removeCommand = getCommandNamePlain(
2839
+ `env rm ${envName} ${removeTargetArg}${removeBranchArg} --yes${globalSuffix}`
2840
+ );
2841
+ const addCommand = getCommandNamePlain(
2842
+ `env add ${envName} ${addTargetArg}${addBranchArg} --type config --value "<value>" --yes${globalSuffix}`
2843
+ );
2844
+ const removeHumanCommand = getCommandNamePlain(
2845
+ `env rm ${envName} ${removeTargetArg}${removeBranchArg}${humanGlobalSuffix}`
2846
+ );
2847
+ const addHumanCommand = getCommandNamePlain(
2848
+ `env add ${envName} ${addTargetArg}${addBranchArg} --type config${humanGlobalSuffix}`
2849
+ );
2850
+ const message = "A Secret cannot be changed to Config. To store this value as Config, remove the variable and add it again with `--type config`.";
2851
+ if (client.nonInteractive) {
2852
+ outputAgentError(
2853
+ client,
2854
+ {
2855
+ status: "error",
2856
+ reason: "secret_cannot_become_config",
2857
+ message,
2858
+ next: [
2859
+ {
2860
+ command: removeCommand,
2861
+ when: "Remove the Secret from all of its environments"
2862
+ },
2863
+ {
2864
+ command: addCommand,
2865
+ when: "Add it again as Config; replace <value> before running"
2866
+ }
2867
+ ]
2868
+ },
2869
+ 1
2870
+ );
2871
+ }
2872
+ output_manager_default.fatal(
2873
+ `A Secret cannot be changed to Config. Remove the variable, then add it again as Config. ${param(envName)} will be unavailable to new builds between these commands.`
2874
+ );
2875
+ output_manager_default.print(` Remove:
2876
+ ${removeHumanCommand}
2877
+ `);
2878
+ output_manager_default.print(
2879
+ ` Add as Config (prompts for the value):
2880
+ ${addHumanCommand}
2881
+ `
2882
+ );
2883
+ return 1;
2884
+ }
2885
+ if (explicitType === "secret" || opts["--sensitive"]) {
2886
+ const knownPublicPrefix = apiPublicPrefix ?? frameworkPublicPrefix;
2887
+ const publicPrefix = knownPublicPrefix ?? customSveltePublicPrefix;
2888
+ const apiPublicPrefixError = apiPublicPrefix ? getPublicPrefixSecretVisibilityError(envName, {
2889
+ visibility: explicitType === "secret" ? "secret" : void 0,
2890
+ type: "sensitive",
2891
+ context: "update"
2892
+ }) : null;
2893
+ const publicPrefixError = apiPublicPrefixError ? apiPublicPrefixError : knownPublicPrefix ? `\`${knownPublicPrefix}\` exposes this value to anyone visiting your site, so \`${envName}\` cannot be kept private as a Secret. Add a new Secret without the public prefix, then remove this Config.` : customSveltePublicPrefix === "" ? "This SvelteKit project uses an empty `publicPrefix`, so every Environment Variable is exposed to the browser and cannot be kept private as a Secret. Change the SvelteKit `publicPrefix`, or keep this variable as Config only if the value is safe to expose." : customSveltePublicPrefix !== void 0 ? `\`${customSveltePublicPrefix}\` exposes this value to anyone visiting your site, so \`${envName}\` cannot be kept private as a Secret. Add a new Secret without the configured public prefix, then remove this Config.` : null;
2894
+ if (publicPrefixError) {
2895
+ const privateName = publicPrefix === void 0 ? envName : envName.slice(publicPrefix.length);
2896
+ const removeTargetArg = envTargetArg || targets[0] || allTargets[0] || getEnvTargetPlaceholder();
2897
+ const addTargetArg = formatTargetArg(allTargets, customEnvironments) || removeTargetArg;
2898
+ const removeBranchArg = selectedEnv.gitBranch ? ` ${quoteArg(selectedEnv.gitBranch)}` : "";
2899
+ const addBranchArg = selectedEnv.gitBranch ? ` --git-branch ${quoteArg(selectedEnv.gitBranch)}` : "";
2900
+ const globalFlags = getGlobalFlagsFromArgs(client.argv.slice(2), {
2901
+ preserveProject: true
2902
+ });
2903
+ const humanGlobalFlags = globalFlags.filter(
2904
+ (flag) => !flag.startsWith("--non-interactive")
2905
+ );
2906
+ const globalSuffix = globalFlags.length > 0 ? ` ${globalFlags.map(quoteArg).join(" ")}` : "";
2907
+ const humanGlobalSuffix = humanGlobalFlags.length > 0 ? ` ${humanGlobalFlags.map(quoteArg).join(" ")}` : "";
2908
+ const addCommand = publicPrefix === "" ? void 0 : getCommandNamePlain(
2909
+ `env add ${privateName} ${addTargetArg}${addBranchArg} --type secret --value "<value>" --yes${globalSuffix}`
2910
+ );
2911
+ const removeCommand = getCommandNamePlain(
2912
+ `env rm ${envName} ${removeTargetArg}${removeBranchArg} --yes${globalSuffix}`
2913
+ );
2914
+ const addHumanCommand = publicPrefix === "" ? void 0 : getCommandNamePlain(
2915
+ `env add ${privateName} ${addTargetArg}${addBranchArg} --type secret${humanGlobalSuffix}`
2916
+ );
2917
+ const removeHumanCommand = getCommandNamePlain(
2918
+ `env rm ${envName} ${removeTargetArg}${removeBranchArg}${humanGlobalSuffix}`
2919
+ );
2920
+ if (client.nonInteractive) {
2921
+ outputAgentError(
2922
+ client,
2923
+ {
2924
+ status: "error",
2925
+ reason: "invalid_type",
2926
+ message: publicPrefixError,
2927
+ next: addCommand ? [
2928
+ {
2929
+ command: addCommand,
2930
+ when: "Add the private Secret; replace <value> before running"
2931
+ },
2932
+ {
2933
+ command: removeCommand,
2934
+ when: "Remove the public Config after the Secret is available"
2935
+ }
2936
+ ] : []
2937
+ },
2938
+ 1
2939
+ );
2940
+ }
2941
+ output_manager_default.fatal(publicPrefixError);
2942
+ if (addHumanCommand) {
2943
+ output_manager_default.print(
2944
+ ` Add the private Secret (prompts for the value):
2945
+ ${addHumanCommand}
2946
+ `
2947
+ );
2948
+ output_manager_default.print(
2949
+ ` Remove the public Config:
2950
+ ${removeHumanCommand}
2951
+ `
2952
+ );
2953
+ }
2954
+ return 1;
2955
+ }
2956
+ }
2957
+ if (customSveltePublicPrefix !== void 0) {
2958
+ printEnvUpdateWarning(
2959
+ customSveltePublicPrefix === "" ? "This SvelteKit project uses an empty `publicPrefix`, so every Environment Variable is exposed to the browser." : `\`${customSveltePublicPrefix}\` variables are exposed to the browser by this SvelteKit project.`
2960
+ );
2961
+ }
2454
2962
  let teamSensitivePolicyOn = false;
2963
+ let disjunctiveProductionSecretPolicyOn = false;
2455
2964
  if (link.org.type === "team") {
2456
2965
  try {
2457
2966
  const team = await getTeamById(client, link.org.id);
2458
2967
  teamSensitivePolicyOn = team?.sensitiveEnvironmentVariablePolicy === "on";
2968
+ disjunctiveProductionSecretPolicyOn = team?.disjunctiveProductionSecretPolicy === "on";
2459
2969
  } catch {
2460
2970
  }
2461
2971
  }
2462
2972
  let envValue;
2973
+ const shouldMaskValue = Boolean(opts["--sensitive"]) || explicitType === "secret" || explicitType === void 0 && selectedEnvIsSecret;
2463
2974
  if (stdInput) {
2464
2975
  const normalizedStdinValue = normalizeStdinEnvValue(stdInput);
2465
2976
  envValue = normalizedStdinValue.value;
@@ -2477,7 +2988,7 @@ async function update(client, argv) {
2477
2988
  {
2478
2989
  status: "action_required",
2479
2990
  reason: "missing_value",
2480
- message: "In non-interactive mode provide the new value via --value or stdin. Example: vercel env update <name> <environment> --value 'value' --yes",
2991
+ message: 'In non-interactive mode, provide the new value with `--value` or stdin. Example: `vercel env update <name> <environment> --value "<value>" --yes`',
2481
2992
  next: [
2482
2993
  {
2483
2994
  command: buildEnvUpdateCommandWithPreservedArgs(
@@ -2490,85 +3001,205 @@ async function update(client, argv) {
2490
3001
  1
2491
3002
  );
2492
3003
  }
2493
- envValue = await client.input.text({
2494
- message: `What's the new value of ${envName}?`
2495
- });
3004
+ envValue = await promptEnvUpdateValue(client, envName, shouldMaskValue);
2496
3005
  }
2497
3006
  const skipConfirm = opts["--yes"] || !!stdInput || valueFromFlag !== void 0;
2498
- const { finalValue, alreadyConfirmed } = await validateEnvValue({
3007
+ const { finalValue } = await validateEnvValue({
2499
3008
  envName,
2500
3009
  initialValue: envValue,
2501
3010
  skipConfirm,
2502
- promptForValue: () => client.input.text({ message: `What's the new value of ${envName}?` }),
3011
+ promptForValue: () => promptEnvUpdateValue(client, envName, shouldMaskValue),
2503
3012
  selectAction: (choices) => client.input.select({ message: "How to proceed?", choices }),
2504
- showWarning: (msg) => output_manager_default.warn(msg),
3013
+ showWarning: printEnvUpdateWarning,
2505
3014
  showLog: (msg) => output_manager_default.log(msg)
2506
3015
  });
2507
- if (!opts["--yes"] && !alreadyConfirmed) {
3016
+ let type = opts["--sensitive"] || explicitType === "secret" ? "sensitive" : explicitType === "config" ? "encrypted" : selectedEnv.type;
3017
+ const isFinalSecret = () => type === "sensitive" || explicitType === void 0 && selectedEnvIsSecret;
3018
+ if (!isFinalSecret() && (type === "plain" || type === "encrypted") && (looksLikeCredentialName2(envName, customSveltePublicPrefix) || looksLikeSecretValue(finalValue))) {
3019
+ printEnvUpdateWarning(
3020
+ "This name or value looks like a credential. Config values can be revealed after saving."
3021
+ );
3022
+ const publicPrefix = apiPublicPrefix ?? frameworkPublicPrefix ?? customSveltePublicPrefix;
3023
+ if (publicPrefix !== null && publicPrefix !== void 0) {
3024
+ printEnvUpdateWarning(
3025
+ publicPrefix === "" ? "This SvelteKit project exposes every Environment Variable to the browser. Keep Config only if the value is safe to expose." : `\`${publicPrefix}\` exposes this value to anyone visiting your site. Keep Config only if the value is safe to expose.`
3026
+ );
3027
+ if (!typeWasExplicit && (opts["--yes"] || client.nonInteractive)) {
3028
+ const message = publicPrefix === "" ? "This SvelteKit project exposes every Environment Variable to the browser. To keep this value private, change the configured public prefix before storing it as Secret. If the value is safe to expose, rerun with `--type config`." : `\`${publicPrefix}\` exposes \`${envName}\` to anyone visiting your site. To keep this value private, add \`${envName.slice(
3029
+ publicPrefix.length
3030
+ )}\` as Secret, then remove \`${envName}\`. If the value is safe to expose, rerun with \`--type config\`.`;
3031
+ if (client.nonInteractive) {
3032
+ outputAgentError(
3033
+ client,
3034
+ {
3035
+ status: "error",
3036
+ reason: "unsafe_public_config",
3037
+ message
3038
+ },
3039
+ 1
3040
+ );
3041
+ }
3042
+ output_manager_default.fatal(message);
3043
+ return 1;
3044
+ }
3045
+ if (publicPrefix !== "" && !typeWasExplicit && !opts["--yes"] && !client.nonInteractive) {
3046
+ const privateName = envName.slice(publicPrefix.length);
3047
+ const removeTargetArg = envTargetArg || targets[0] || allTargets[0] || getEnvTargetPlaceholder();
3048
+ const addTargetArg = formatTargetArg(allTargets, customEnvironments) || removeTargetArg;
3049
+ const removeBranchArg = selectedEnv.gitBranch ? ` ${quoteArg(selectedEnv.gitBranch)}` : "";
3050
+ const addBranchArg = selectedEnv.gitBranch ? ` --git-branch ${quoteArg(selectedEnv.gitBranch)}` : "";
3051
+ const humanGlobalFlags = getGlobalFlagsFromArgs(client.argv.slice(2), {
3052
+ preserveProject: true
3053
+ }).filter((flag) => !flag.startsWith("--non-interactive"));
3054
+ const humanGlobalSuffix = humanGlobalFlags.length > 0 ? ` ${humanGlobalFlags.map(quoteArg).join(" ")}` : "";
3055
+ const addPrivateCommand = getCommandNamePlain(
3056
+ `env add ${privateName} ${addTargetArg}${addBranchArg} --type secret${humanGlobalSuffix}`
3057
+ );
3058
+ const removePublicCommand = getCommandNamePlain(
3059
+ `env rm ${envName} ${removeTargetArg}${removeBranchArg}${humanGlobalSuffix}`
3060
+ );
3061
+ const selectedAction = await client.input.select({
3062
+ message: "How should this variable be stored?",
3063
+ choices: [
3064
+ {
3065
+ name: `Keep private: add ${privateName} as Secret, then remove ${envName}`,
3066
+ value: "private"
3067
+ },
3068
+ {
3069
+ name: `Expose to anyone visiting your site: keep ${envName} as Config`,
3070
+ value: "config"
3071
+ }
3072
+ ]
3073
+ });
3074
+ if (selectedAction === "private") {
3075
+ output_manager_default.print(" Add the private Secret (prompts for the value):\n");
3076
+ output_manager_default.print(` ${addPrivateCommand}
3077
+ `);
3078
+ output_manager_default.print(" Remove the public Config:\n");
3079
+ output_manager_default.print(` ${removePublicCommand}
3080
+ `);
3081
+ return 1;
3082
+ }
3083
+ }
3084
+ } else if (!typeWasExplicit && !opts["--yes"] && !client.nonInteractive) {
3085
+ const selectedType = await client.input.select({
3086
+ message: "Store this value as?",
3087
+ choices: [
3088
+ {
3089
+ name: getSecretStorageChoice(targets, "for this value"),
3090
+ value: "secret"
3091
+ },
3092
+ {
3093
+ name: "Config (can be revealed after saving)",
3094
+ value: "config"
3095
+ }
3096
+ ]
3097
+ });
3098
+ if (selectedType === "secret") {
3099
+ type = "sensitive";
3100
+ explicitType = "secret";
3101
+ }
3102
+ } else if (!typeWasExplicit) {
3103
+ printEnvUpdateWarning("Re-run with `--type secret` to protect it.");
3104
+ }
3105
+ }
3106
+ if (isFinalSecret() && !selectedEnvIsSecret) {
3107
+ printEnvUpdateWarning(
3108
+ "The previous value was readable as Config and may have been exposed. If this variable still holds the same credential, rotate it at its provider and update this variable again."
3109
+ );
3110
+ }
3111
+ const finalPublicPrefix = apiPublicPrefix ?? frameworkPublicPrefix ?? customSveltePublicPrefix;
3112
+ if (isFinalSecret() && finalPublicPrefix !== null && finalPublicPrefix !== void 0) {
3113
+ printEnvUpdateWarning(
3114
+ finalPublicPrefix === "" ? "This SvelteKit project exposes every Environment Variable to the browser; the Secret type does not prevent that. Change the configured public prefix to keep values private." : `\`${finalPublicPrefix}\` exposes this variable to the browser; the Secret type does not prevent that. Rename the variable without the public prefix to keep it private.`
3115
+ );
3116
+ }
3117
+ if (isFinalSecret() && disjunctiveProductionSecretPolicyOn && targets.includes("production") && allTargets.some((target) => target !== "production")) {
3118
+ const message = "Your team requires Production and non-Production Secrets to be stored separately with different values. Create separate variables with different values before converting this one.";
2508
3119
  if (client.nonInteractive) {
2509
- outputActionRequired(
3120
+ outputAgentError(
2510
3121
  client,
2511
3122
  {
2512
- status: "action_required",
2513
- reason: "confirmation_required",
2514
- message: `Updating Environment Variable ${envName}. Use --yes to confirm.`,
2515
- next: [{ command: buildCommandWithYes(client.argv) }]
3123
+ status: "error",
3124
+ reason: "production_secret_must_be_separate",
3125
+ message
2516
3126
  },
2517
3127
  1
2518
3128
  );
2519
3129
  }
2520
- const currentTargets = formatEnvironments(
2521
- link,
2522
- selectedEnv,
2523
- customEnvironments
2524
- );
2525
- const confirmed = await client.input.confirm(
2526
- `Updating Environment Variable ${param(envName)} in ${currentTargets} in Project ${import_chalk4.default.bold(project.name)}. Are you sure?`,
2527
- false
2528
- );
2529
- if (!confirmed) {
2530
- output_manager_default.log("Canceled");
2531
- return 0;
2532
- }
2533
- }
2534
- const type = opts["--sensitive"] ? "sensitive" : selectedEnv.type;
2535
- const explicitVisibility = typeof opts["--visibility"] === "string" ? opts["--visibility"] : void 0;
2536
- if (explicitVisibility === "config" && opts["--sensitive"]) {
2537
- output_manager_default.error(
2538
- "`--visibility config` cannot be used with `--sensitive`. Pick one."
2539
- );
3130
+ output_manager_default.fatal(message);
2540
3131
  return 1;
2541
3132
  }
2542
- const targets = Array.isArray(selectedEnv.target) ? selectedEnv.target : [selectedEnv.target].filter(
2543
- (r) => Boolean(r)
2544
- );
2545
- const allTargets = [...targets, ...selectedEnv.customEnvironmentIds || []];
2546
- const { visibility, error: visibilityError } = resolveEnvVarVisibility({
2547
- explicitVisibility,
3133
+ const preserveExistingVisibility = explicitType === void 0 && selectedEnv.visibility === "secret" && type !== "sensitive";
3134
+ const { visibility: resolvedVisibility, error: visibilityError } = resolveEnvVarVisibility({
3135
+ explicitVisibility: typeOption.source ? explicitType : void 0,
3136
+ explicitOptionSource: typeOption.source,
2548
3137
  type,
2549
3138
  key: envName,
2550
3139
  envTargets: allTargets,
2551
- teamSensitivePolicyOn
3140
+ teamSensitivePolicyOn,
3141
+ context: "update"
2552
3142
  });
3143
+ const visibility = preserveExistingVisibility ? void 0 : resolvedVisibility;
3144
+ const displayVisibility = preserveExistingVisibility ? selectedEnv.visibility : visibility;
2553
3145
  if (visibilityError) {
2554
3146
  if (client.nonInteractive) {
2555
3147
  outputAgentError(
2556
3148
  client,
2557
3149
  {
2558
3150
  status: "error",
2559
- reason: "invalid_visibility",
3151
+ reason: "invalid_type",
2560
3152
  message: visibilityError
2561
3153
  },
2562
3154
  1
2563
3155
  );
2564
3156
  }
2565
- output_manager_default.error(visibilityError);
3157
+ output_manager_default.fatal(visibilityError);
2566
3158
  return 1;
2567
3159
  }
2568
- const updateStamp = stamp_default();
3160
+ if (!opts["--yes"]) {
3161
+ const visibilityLabel2 = formatVisibilityLabel(displayVisibility, type);
3162
+ if (client.nonInteractive) {
3163
+ outputActionRequired(
3164
+ client,
3165
+ {
3166
+ status: "action_required",
3167
+ reason: "confirmation_required",
3168
+ message: `Update ${envName} as ${visibilityLabel2} in ${formatEnvironments(
3169
+ link,
3170
+ selectedEnv,
3171
+ customEnvironments
3172
+ )}? Use --yes to confirm.`,
3173
+ next: [
3174
+ {
3175
+ command: buildCommandWithYes(redactEnvValueArgs(client.argv))
3176
+ }
3177
+ ]
3178
+ },
3179
+ 1
3180
+ );
3181
+ }
3182
+ output_manager_default.print("\n");
3183
+ printAlignedLabel("Project", `${link.org.slug}/${project.name}`);
3184
+ printAlignedLabel(
3185
+ "Environments",
3186
+ formatEnvironments(link, selectedEnv, customEnvironments)
3187
+ );
3188
+ if (visibilityLabel2) {
3189
+ printAlignedLabel("Type", visibilityLabel2);
3190
+ }
3191
+ const confirmed = await client.input.confirm(
3192
+ "Update this Environment Variable?",
3193
+ false
3194
+ );
3195
+ if (!confirmed) {
3196
+ output_manager_default.log("Canceled");
3197
+ return 0;
3198
+ }
3199
+ }
2569
3200
  try {
2570
3201
  output_manager_default.spinner("Updating");
2571
- const keyToUpdate = type === "sensitive" ? void 0 : envName;
3202
+ const keyToUpdate = isFinalSecret() ? void 0 : envName;
2572
3203
  await updateEnvRecord(
2573
3204
  client,
2574
3205
  project.id,
@@ -2582,13 +3213,18 @@ async function update(client, argv) {
2582
3213
  );
2583
3214
  } catch (err) {
2584
3215
  if (client.nonInteractive && isAPIError(err)) {
2585
- const reason = err.slug || (err.serverMessage?.toLowerCase().includes("branch") ? "branch_not_found" : "api_error");
3216
+ const productionSecretPolicyError = getProductionSecretPolicyErrorKind(
3217
+ err.serverMessage
3218
+ );
3219
+ const reason = productionSecretPolicyError ? productionSecretPolicyError === "different-values" ? "production_secret_requires_different_value" : "production_secret_must_be_separate" : err.slug || (err.serverMessage?.toLowerCase().includes("branch") ? "branch_not_found" : "api_error");
2586
3220
  outputAgentError(
2587
3221
  client,
2588
3222
  {
2589
3223
  status: "error",
2590
3224
  reason,
2591
- message: err.serverMessage
3225
+ message: productionSecretPolicyError ? `${err.serverMessage} ${getProductionSecretPolicyRecovery(
3226
+ productionSecretPolicyError
3227
+ )}` : err.serverMessage
2592
3228
  },
2593
3229
  1
2594
3230
  );
@@ -2599,18 +3235,16 @@ async function update(client, argv) {
2599
3235
  }
2600
3236
  throw err;
2601
3237
  }
2602
- output_manager_default.print(
2603
- `${prependEmoji(
2604
- `Updated Environment Variable ${import_chalk4.default.bold(envName)} in Project ${import_chalk4.default.bold(
2605
- project.name
2606
- )} ${import_chalk4.default.gray(updateStamp())}`,
2607
- emoji("success")
2608
- )}
2609
- `
3238
+ output_manager_default.print("\n");
3239
+ printAlignedLabel("Updated", envName, { gutter: "\u2713" });
3240
+ printAlignedLabel("Project", `${link.org.slug}/${project.name}`);
3241
+ printAlignedLabel(
3242
+ "Environments",
3243
+ formatEnvironments(link, selectedEnv, customEnvironments)
2610
3244
  );
2611
- const visibilityLabel = formatVisibilityLabel(visibility, type);
3245
+ const visibilityLabel = formatVisibilityLabel(displayVisibility, type);
2612
3246
  if (visibilityLabel) {
2613
- printAlignedLabel("Visibility", visibilityLabel);
3247
+ printAlignedLabel("Type", visibilityLabel);
2614
3248
  }
2615
3249
  return 0;
2616
3250
  }