@@ -69,7 +69,7 @@ struct RegisterCLIView: View {
6969 TextField ( " CLI name " , text: $name, prompt: Text ( " hcloud " ) )
7070 . accessibilityLabel ( " CLI name " )
7171 HStack ( alignment: . firstTextBaseline, spacing: 8 ) {
72- TextField ( " Executable path " , text: $targetPath, prompt : Text ( " /opt/homebrew/bin/hcloud " ) )
72+ TextField ( " Executable path " , text: $targetPath)
7373 . accessibilityLabel ( " Executable path " )
7474 Button {
7575 chooseExecutable ( )
@@ -90,27 +90,36 @@ struct RegisterCLIView: View {
9090 Text ( " Use the resolved executable path for the CLI you want Agentic Secrets to verify before delivery. " )
9191 . foregroundStyle ( . secondary)
9292 }
93- case . bindings:
94- Section ( " Environment bindings " ) {
95- ForEach ( $bindings) { $binding in
96- HStack {
97- TextField ( " ENV_NAME " , text: $binding. environmentName)
98- . accessibilityLabel ( " Environment variable name " )
99- Button {
100- bindings. removeAll { $0. id == binding. id }
101- if bindings. isEmpty { bindings. append ( SecretDraft ( ) ) }
102- } label: {
103- Image ( systemName: " minus.circle " )
104- }
105- . buttonStyle ( . borderless)
106- . help ( " Remove binding " )
107- . accessibilityLabel ( " Remove environment binding " )
93+ case . secrets:
94+ Section ( " Environment secrets " ) {
95+ Grid ( alignment: . leading, horizontalSpacing: 12 , verticalSpacing: 8 ) {
96+ GridRow {
97+ Text ( " ENV_NAME " )
98+ . font ( . caption. weight ( . semibold) )
99+ . foregroundStyle ( . secondary)
100+ Text ( " Value " )
101+ . font ( . caption. weight ( . semibold) )
102+ . foregroundStyle ( . secondary)
103+ Text ( " " )
104+ . accessibilityHidden ( true )
105+ }
106+ Divider ( )
107+ . gridCellColumns ( 3 )
108+ ForEach ( $bindings) { $binding in
109+ RegisterCLISecretRow (
110+ binding: $binding,
111+ canRemove: bindings. count > 1 ,
112+ remove: {
113+ bindings. removeAll { $0. id == binding. id }
114+ if bindings. isEmpty { bindings. append ( SecretDraft ( ) ) }
115+ }
116+ )
108117 }
109118 }
110119 Button {
111120 bindings. append ( SecretDraft ( ) )
112121 } label: {
113- Label ( " Add Environment Binding " , systemImage: " plus " )
122+ Label ( " Add Environment Secret " , systemImage: " plus " )
114123 }
115124 if RegisterCLIFormValidation . hasDuplicateEnvironmentNames ( bindings) {
116125 Text ( " Environment names must be unique. " )
@@ -120,13 +129,6 @@ struct RegisterCLIView: View {
120129 Text ( " Use shell-style names such as HCLOUD_TOKEN: letters, numbers, and underscores; do not start with a number. " )
121130 . foregroundStyle ( . red)
122131 }
123- }
124- case . secrets:
125- Section ( " Write-only secrets " ) {
126- ForEach ( $bindings) { $binding in
127- SecureField ( binding. environmentName. isEmpty ? " Secret value " : binding. environmentName, text: $binding. secretValue)
128- . accessibilityLabel ( " Secret value for \( binding. environmentName. isEmpty ? " environment binding " : binding. environmentName) " )
129- }
130132 if bindings. contains ( where: { !$0. secretValue. isEmpty && !SecretInputValidation. hasNonWhitespace ( $0. secretValue) } ) {
131133 Text ( " Secret values cannot be only whitespace. " )
132134 . foregroundStyle ( . red)
@@ -158,10 +160,6 @@ struct RegisterCLIView: View {
158160 !name. trimmingCharacters ( in: . whitespacesAndNewlines) . isEmpty
159161 && !targetPath. trimmingCharacters ( in: . whitespacesAndNewlines) . isEmpty
160162 && RegisterCLIFormValidation . isValidExecutablePath ( targetPath)
161- case . bindings:
162- bindings. contains { !$0. environmentName. trimmingCharacters ( in: . whitespacesAndNewlines) . isEmpty }
163- && !RegisterCLIFormValidation. hasDuplicateEnvironmentNames ( bindings)
164- && RegisterCLIFormValidation . invalidEnvironmentNames ( bindings) . isEmpty
165163 case . secrets:
166164 bindings. allSatisfy {
167165 !$0. environmentName. trimmingCharacters ( in: . whitespacesAndNewlines) . isEmpty
@@ -279,14 +277,12 @@ enum BitwardenBindingEditorDefaults {
279277
280278private enum RegisterCLIStep : Int , CaseIterable {
281279 case target
282- case bindings
283280 case secrets
284281 case review
285282
286283 var title : String {
287284 switch self {
288285 case . target: " Target "
289- case . bindings: " Bindings "
290286 case . secrets: " Secrets "
291287 case . review: " Review "
292288 }
@@ -295,8 +291,7 @@ private enum RegisterCLIStep: Int, CaseIterable {
295291 var subtitle : String {
296292 switch self {
297293 case . target: " Choose the CLI executable to verify. "
298- case . bindings: " Name the environment variables Agentic Secrets may deliver. "
299- case . secrets: " Enter secret material once; it will not be shown again. "
294+ case . secrets: " Add environment names and write-only values in one table. "
300295 case . review: " Confirm the target and write-only bindings. "
301296 }
302297 }
@@ -310,6 +305,30 @@ private enum RegisterCLIStep: Int, CaseIterable {
310305 }
311306}
312307
308+ private struct RegisterCLISecretRow : View {
309+ @Binding var binding : SecretDraft
310+ var canRemove : Bool
311+ var remove : ( ) -> Void
312+
313+ var body : some View {
314+ GridRow {
315+ TextField ( " HCLOUD_TOKEN " , text: $binding. environmentName)
316+ . textFieldStyle ( . roundedBorder)
317+ . accessibilityLabel ( " Environment variable name " )
318+ SecureField ( " Secret value " , text: $binding. secretValue)
319+ . textFieldStyle ( . roundedBorder)
320+ . accessibilityLabel ( " Secret value for \( binding. environmentName. isEmpty ? " environment variable " : binding. environmentName) " )
321+ Button ( action: remove) {
322+ Image ( systemName: " minus.circle " )
323+ }
324+ . buttonStyle ( . borderless)
325+ . disabled ( !canRemove)
326+ . help ( canRemove ? " Remove environment secret " : " At least one environment secret is required " )
327+ . accessibilityLabel ( " Remove environment secret " )
328+ }
329+ }
330+ }
331+
313332private struct RegisterCLIStepHeader : View {
314333 var step : RegisterCLIStep
315334
0 commit comments