windmill-components 1.695.1 → 1.699.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/dist/sharedUtils/assets/tokens/colorTokensConfig.d.ts +2 -0
  2. package/dist/sharedUtils/base.d.ts +1 -0
  3. package/dist/sharedUtils/cloud.d.ts +1 -0
  4. package/dist/sharedUtils/common.d.ts +111 -0
  5. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/count.d.ts +5 -0
  6. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/delete.d.ts +5 -0
  7. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/insert.d.ts +5 -0
  8. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/select.d.ts +13 -0
  9. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/update.d.ts +11 -0
  10. package/dist/sharedUtils/components/apps/components/display/dbtable/utils.d.ts +95 -0
  11. package/dist/sharedUtils/components/apps/editor/appPolicy.d.ts +6 -0
  12. package/dist/sharedUtils/components/apps/editor/appUtilsCore.d.ts +7 -0
  13. package/dist/sharedUtils/components/apps/editor/appUtilsS3.d.ts +33 -0
  14. package/dist/sharedUtils/components/apps/editor/commonAppUtils.d.ts +10 -0
  15. package/dist/sharedUtils/components/apps/editor/component/components.d.ts +5371 -0
  16. package/dist/sharedUtils/components/apps/editor/component/default-codes.d.ts +3 -0
  17. package/dist/sharedUtils/components/apps/editor/component/index.d.ts +3 -0
  18. package/dist/sharedUtils/components/apps/editor/component/sets.d.ts +7 -0
  19. package/dist/sharedUtils/components/apps/editor/componentsPanel/componentDefaultProps.d.ts +3 -0
  20. package/dist/sharedUtils/components/apps/gridUtils.d.ts +14 -0
  21. package/dist/sharedUtils/components/apps/inputType.d.ts +178 -0
  22. package/dist/sharedUtils/components/apps/rx.d.ts +29 -0
  23. package/dist/sharedUtils/components/apps/sharedTypes.d.ts +21 -0
  24. package/dist/sharedUtils/components/apps/types.d.ts +274 -0
  25. package/dist/sharedUtils/components/assets/lib.d.ts +25 -0
  26. package/dist/sharedUtils/components/common/alert/model.d.ts +2 -0
  27. package/dist/sharedUtils/components/common/badge/model.d.ts +8 -0
  28. package/dist/sharedUtils/components/common/button/model.d.ts +45 -0
  29. package/dist/sharedUtils/components/common/fileInput/model.d.ts +1 -0
  30. package/dist/sharedUtils/components/common/index.d.ts +24 -0
  31. package/dist/sharedUtils/components/common/skeleton/model.d.ts +21 -0
  32. package/dist/sharedUtils/components/dbTypes.d.ts +14 -0
  33. package/dist/sharedUtils/components/diff_drawer.d.ts +26 -0
  34. package/dist/sharedUtils/components/ducklake.d.ts +1 -0
  35. package/dist/sharedUtils/components/flows/scheduleUtils.d.ts +7 -0
  36. package/dist/sharedUtils/components/icons/index.d.ts +101 -0
  37. package/dist/sharedUtils/components/random_positive_adjetive.d.ts +1 -0
  38. package/dist/sharedUtils/components/raw_apps/rawAppPolicy.d.ts +10 -0
  39. package/dist/sharedUtils/components/raw_apps/utils.d.ts +15 -0
  40. package/dist/sharedUtils/components/triggers/email/utils.d.ts +4 -0
  41. package/dist/sharedUtils/components/triggers/gcp/utils.d.ts +2 -0
  42. package/dist/sharedUtils/components/triggers/http/utils.d.ts +11 -0
  43. package/dist/sharedUtils/components/triggers/kafka/utils.d.ts +2 -0
  44. package/dist/sharedUtils/components/triggers/mqtt/utils.d.ts +2 -0
  45. package/dist/sharedUtils/components/triggers/nats/utils.d.ts +2 -0
  46. package/dist/sharedUtils/components/triggers/postgres/utils.d.ts +8 -0
  47. package/dist/sharedUtils/components/triggers/sqs/utils.d.ts +2 -0
  48. package/dist/sharedUtils/components/triggers/triggers.svelte.d.ts +32 -0
  49. package/dist/sharedUtils/components/triggers/utils.d.ts +80 -0
  50. package/dist/sharedUtils/components/triggers/websocket/utils.d.ts +2 -0
  51. package/dist/sharedUtils/components/triggers.d.ts +20 -0
  52. package/dist/sharedUtils/gen/core/ApiError.d.ts +10 -0
  53. package/dist/sharedUtils/gen/core/ApiRequestOptions.d.ts +13 -0
  54. package/dist/sharedUtils/gen/core/ApiResult.d.ts +7 -0
  55. package/dist/sharedUtils/gen/core/CancelablePromise.d.ts +26 -0
  56. package/dist/sharedUtils/gen/core/OpenAPI.d.ts +27 -0
  57. package/dist/sharedUtils/gen/core/request.d.ts +29 -0
  58. package/dist/sharedUtils/gen/index.d.ts +6 -0
  59. package/dist/sharedUtils/gen/schemas.gen.d.ts +7036 -0
  60. package/dist/sharedUtils/gen/services.gen.d.ts +6047 -0
  61. package/dist/sharedUtils/gen/types.gen.d.ts +21881 -0
  62. package/dist/sharedUtils/history.svelte.d.ts +9 -0
  63. package/dist/sharedUtils/hub.d.ts +49 -0
  64. package/dist/sharedUtils/jsr.json +6 -0
  65. package/dist/sharedUtils/lib.d.ts +5 -0
  66. package/dist/sharedUtils/lib.es.js +1588 -0
  67. package/dist/sharedUtils/package.json +12 -0
  68. package/dist/sharedUtils/schema.d.ts +3 -0
  69. package/dist/sharedUtils/stores.d.ts +97 -0
  70. package/dist/sharedUtils/svelte5Utils.svelte.d.ts +80 -0
  71. package/dist/sharedUtils/toast.d.ts +8 -0
  72. package/dist/sharedUtils/utils.d.ts +265 -0
  73. package/package/components/AppConnectInner.svelte +38 -5
  74. package/package/components/CompareWorkspaces.svelte +142 -486
  75. package/package/components/DisplayResult.svelte +39 -19
  76. package/package/components/Editor.svelte +5 -4
  77. package/package/components/Editor.svelte.d.ts +1 -0
  78. package/package/components/FilterSearchbar.svelte +3 -1
  79. package/package/components/FilterSearchbar.svelte.d.ts +1 -0
  80. package/package/components/FlowStatusViewerInner.svelte +23 -9
  81. package/package/components/ForkWorkspaceBanner.svelte +16 -0
  82. package/package/components/HistoricInputs.svelte +2 -1
  83. package/package/components/InstanceSetting.svelte +47 -5
  84. package/package/components/LogViewer.svelte +101 -71
  85. package/package/components/OnBehalfOfSelector.svelte +10 -7
  86. package/package/components/ParqetCsvTableRenderer.svelte +9 -4
  87. package/package/components/Path.svelte +10 -0
  88. package/package/components/ResourceEditor.svelte +198 -311
  89. package/package/components/ResourceEditor.svelte.d.ts +3 -3
  90. package/package/components/ResourceEditorDrawer.svelte +17 -6
  91. package/package/components/ResourceForm.svelte +235 -0
  92. package/package/components/ResourceForm.svelte.d.ts +25 -0
  93. package/package/components/RunsPage.svelte +1 -0
  94. package/package/components/S3FilePickerInner.svelte +22 -8
  95. package/package/components/ScriptBuilder.svelte +1 -0
  96. package/package/components/ScriptEditor.svelte +44 -7
  97. package/package/components/ScriptEditor.svelte.d.ts +1 -0
  98. package/package/components/ShareModal.svelte.d.ts +1 -1
  99. package/package/components/TaggedTextInput.svelte +4 -1
  100. package/package/components/TaggedTextInput.svelte.d.ts +2 -0
  101. package/package/components/VariableEditor.svelte +177 -199
  102. package/package/components/VariableEditor.svelte.d.ts +1 -2
  103. package/package/components/VariableForm.svelte +133 -0
  104. package/package/components/VariableForm.svelte.d.ts +22 -0
  105. package/package/components/WsSpecificVersions.svelte +39 -0
  106. package/package/components/WsSpecificVersions.svelte.d.ts +9 -0
  107. package/package/components/apps/editor/AppEditorHeaderDeploy.svelte.d.ts +1 -1
  108. package/package/components/common/fileDownload/FileDownload.svelte +16 -6
  109. package/package/components/common/table/AppRow.svelte +2 -1
  110. package/package/components/common/table/AppRow.svelte.d.ts +1 -0
  111. package/package/components/common/table/FlowRow.svelte +2 -1
  112. package/package/components/common/table/FlowRow.svelte.d.ts +1 -0
  113. package/package/components/common/table/RawAppRow.svelte +2 -1
  114. package/package/components/common/table/RawAppRow.svelte.d.ts +1 -0
  115. package/package/components/common/table/Row.svelte +11 -3
  116. package/package/components/common/table/Row.svelte.d.ts +2 -1
  117. package/package/components/common/table/RowIcon.svelte +18 -2
  118. package/package/components/common/table/RowIcon.svelte.d.ts +1 -1
  119. package/package/components/common/table/ScriptRow.svelte +2 -1
  120. package/package/components/common/table/ScriptRow.svelte.d.ts +1 -0
  121. package/package/components/copilot/autocomplete/Autocompletor.d.ts +3 -1
  122. package/package/components/copilot/autocomplete/Autocompletor.js +5 -2
  123. package/package/components/copilot/autocomplete/request.d.ts +1 -0
  124. package/package/components/copilot/autocomplete/request.js +1 -1
  125. package/package/components/copilot/chat/AIChatManager.svelte.js +14 -4
  126. package/package/components/copilot/chat/AiChatLayout.svelte +2 -0
  127. package/package/components/copilot/chat/ContextManager.svelte.d.ts +1 -0
  128. package/package/components/copilot/chat/CreatedResourceActionDrawers.svelte +129 -0
  129. package/package/components/copilot/chat/CreatedResourceActionDrawers.svelte.d.ts +4 -0
  130. package/package/components/copilot/chat/ToolExecutionDisplay.svelte +14 -6
  131. package/package/components/copilot/chat/ToolMessageActions.svelte +73 -0
  132. package/package/components/copilot/chat/ToolMessageActions.svelte.d.ts +7 -0
  133. package/package/components/copilot/chat/createdResourceActions.svelte.d.ts +6 -0
  134. package/package/components/copilot/chat/createdResourceActions.svelte.js +29 -0
  135. package/package/components/copilot/chat/script/core.d.ts +6 -2
  136. package/package/components/copilot/chat/script/core.js +13 -7
  137. package/package/components/copilot/chat/script/wacPrompt.test.d.ts +1 -0
  138. package/package/components/copilot/chat/script/wacPrompt.test.js +25 -0
  139. package/package/components/copilot/chat/shared.d.ts +12 -0
  140. package/package/components/copilot/chat/shared.test.js +23 -2
  141. package/package/components/copilot/chat/workspaceTools.js +34 -4
  142. package/package/components/flows/content/ScriptEditorDrawer.svelte +1 -0
  143. package/package/components/flows/idUtils.js +4 -1
  144. package/package/components/flows/stepsInputArgs.svelte.js +6 -1
  145. package/package/components/graph/wacToFlow.js +1 -1
  146. package/package/components/graph/wacToFlow.test.d.ts +1 -0
  147. package/package/components/graph/wacToFlow.test.js +17 -0
  148. package/package/components/home/Item.svelte +5 -1
  149. package/package/components/home/Item.svelte.d.ts +1 -0
  150. package/package/components/home/ItemsList.svelte +260 -3
  151. package/package/components/instanceSettings/SecretBackendConfig.svelte +492 -98
  152. package/package/components/propertyPicker/ObjectViewer.svelte +10 -4
  153. package/package/components/runs/runsFilter.d.ts +1 -1
  154. package/package/components/runs/useJobsLoader.svelte.d.ts +1 -0
  155. package/package/components/runs/useJobsLoader.svelte.js +8 -12
  156. package/package/components/scriptEditor/LogPanel.svelte +4 -1
  157. package/package/components/scriptEditor/LogPanel.svelte.d.ts +1 -0
  158. package/package/components/settings/WorkspaceOperatorSettings.svelte +1 -1
  159. package/package/components/sidebar/SidebarContent.svelte +40 -2
  160. package/package/components/sidebar/WorkspaceMenu.svelte +19 -5
  161. package/package/externalDomain.d.ts +2 -0
  162. package/package/externalDomain.js +16 -0
  163. package/package/gen/core/OpenAPI.js +1 -1
  164. package/package/gen/schemas.gen.d.ts +33 -4
  165. package/package/gen/schemas.gen.js +33 -4
  166. package/package/gen/services.gen.d.ts +20 -1
  167. package/package/gen/services.gen.js +40 -0
  168. package/package/gen/types.gen.d.ts +70 -3
  169. package/package/hubPaths.json +2 -2
  170. package/package/system_prompts/index.d.ts +1 -1
  171. package/package/system_prompts/index.js +22 -3
  172. package/package/system_prompts/prompts.d.ts +2 -2
  173. package/package/system_prompts/prompts.js +7 -4
  174. package/package/utils/downloadFile.d.ts +11 -0
  175. package/package/utils/downloadFile.js +48 -0
  176. package/package/utils_deployable.d.ts +162 -638
  177. package/package/utils_deployable.js +75 -143
  178. package/package/utils_workspace_deploy.d.ts +10 -4
  179. package/package/utils_workspace_deploy.js +167 -42
  180. package/package.json +7 -3
@@ -42,7 +42,8 @@ let vaultDisabled = $derived(!$enterpriseLicense);
42
42
  function setBackendType(type) {
43
43
  if (!type)
44
44
  return;
45
- if ((type === 'HashiCorpVault' || type === 'AzureKeyVault' || type === 'AwsSecretsManager') && vaultDisabled)
45
+ if ((type === 'HashiCorpVault' || type === 'AzureKeyVault' || type === 'AwsSecretsManager') &&
46
+ vaultDisabled)
46
47
  return;
47
48
  if (type === 'Database') {
48
49
  $values['secret_backend'] = { type: 'Database' };
@@ -53,6 +54,7 @@ function setBackendType(type) {
53
54
  address: $values['secret_backend']?.address ?? '',
54
55
  mount_path: $values['secret_backend']?.mount_path ?? 'windmill',
55
56
  jwt_role: $values['secret_backend']?.jwt_role ?? 'windmill-secrets',
57
+ jwt_mount_path: $values['secret_backend']?.jwt_mount_path ?? null,
56
58
  namespace: $values['secret_backend']?.namespace ?? null,
57
59
  token: $values['secret_backend']?.token ?? null,
58
60
  skip_ssl_verify: $values['secret_backend']?.skip_ssl_verify ?? false
@@ -80,13 +82,23 @@ function setBackendType(type) {
80
82
  }
81
83
  }
82
84
  function setAuthMethod(method) {
83
- if (!method || !$values['secret_backend'] || $values['secret_backend'].type !== 'HashiCorpVault')
85
+ if (!method ||
86
+ !$values['secret_backend'] ||
87
+ $values['secret_backend'].type !== 'HashiCorpVault')
84
88
  return;
85
89
  if (method === 'token') {
86
- $values['secret_backend'] = { ...$values['secret_backend'], jwt_role: null, token: $values['secret_backend'].token ?? '' };
90
+ $values['secret_backend'] = {
91
+ ...$values['secret_backend'],
92
+ jwt_role: null,
93
+ token: $values['secret_backend'].token ?? ''
94
+ };
87
95
  }
88
96
  else if (method === 'jwt') {
89
- $values['secret_backend'] = { ...$values['secret_backend'], token: null, jwt_role: $values['secret_backend'].jwt_role ?? 'windmill-secrets' };
97
+ $values['secret_backend'] = {
98
+ ...$values['secret_backend'],
99
+ token: null,
100
+ jwt_role: $values['secret_backend'].jwt_role ?? 'windmill-secrets'
101
+ };
90
102
  }
91
103
  }
92
104
  function getVaultSettings() {
@@ -94,6 +106,7 @@ function getVaultSettings() {
94
106
  address: $values['secret_backend'].address,
95
107
  mount_path: $values['secret_backend'].mount_path,
96
108
  jwt_role: $values['secret_backend'].jwt_role,
109
+ jwt_mount_path: $values['secret_backend'].jwt_mount_path || undefined,
97
110
  namespace: $values['secret_backend'].namespace || undefined,
98
111
  token: $values['secret_backend'].token || undefined,
99
112
  skip_ssl_verify: $values['secret_backend'].skip_ssl_verify || undefined
@@ -138,7 +151,9 @@ async function migrateSecretsToDatabase() {
138
151
  return;
139
152
  migratingToDatabase = true;
140
153
  try {
141
- const report = await SettingService.migrateSecretsToDatabase({ requestBody: getVaultSettings() });
154
+ const report = await SettingService.migrateSecretsToDatabase({
155
+ requestBody: getVaultSettings()
156
+ });
142
157
  if (report.failed_count > 0)
143
158
  sendUserToast(`Migration: ${report.migrated_count}/${report.total_secrets} migrated, ${report.failed_count} failed`, true);
144
159
  else
@@ -190,7 +205,9 @@ async function migrateSecretsToAzureKv() {
190
205
  return;
191
206
  migratingToAzureKv = true;
192
207
  try {
193
- const report = await SettingService.migrateSecretsToAzureKv({ requestBody: getAzureKvSettings() });
208
+ const report = await SettingService.migrateSecretsToAzureKv({
209
+ requestBody: getAzureKvSettings()
210
+ });
194
211
  if (report.failed_count > 0)
195
212
  sendUserToast(`Migration: ${report.migrated_count}/${report.total_secrets} migrated, ${report.failed_count} failed`, true);
196
213
  else
@@ -209,7 +226,9 @@ async function migrateSecretsFromAzureKv() {
209
226
  return;
210
227
  migratingFromAzureKv = true;
211
228
  try {
212
- const report = await SettingService.migrateSecretsFromAzureKv({ requestBody: getAzureKvSettings() });
229
+ const report = await SettingService.migrateSecretsFromAzureKv({
230
+ requestBody: getAzureKvSettings()
231
+ });
213
232
  if (report.failed_count > 0)
214
233
  sendUserToast(`Migration: ${report.migrated_count}/${report.total_secrets} migrated, ${report.failed_count} failed`, true);
215
234
  else
@@ -228,8 +247,7 @@ function isAzureKvConfigValid() {
228
247
  return false;
229
248
  return ($values['secret_backend'].vault_url?.trim() !== '' &&
230
249
  $values['secret_backend'].tenant_id?.trim() !== '' &&
231
- $values['secret_backend'].client_id?.trim() !== '' &&
232
- (!!$values['secret_backend'].client_secret?.trim() || !!$values['secret_backend'].token?.trim()));
250
+ $values['secret_backend'].client_id?.trim() !== '');
233
251
  }
234
252
  function getAwsSmSettings() {
235
253
  return {
@@ -279,7 +297,9 @@ async function migrateSecretsFromAwsSm() {
279
297
  return;
280
298
  migratingFromAwsSm = true;
281
299
  try {
282
- const report = await SettingService.migrateSecretsFromAwsSm({ requestBody: getAwsSmSettings() });
300
+ const report = await SettingService.migrateSecretsFromAwsSm({
301
+ requestBody: getAwsSmSettings()
302
+ });
283
303
  if (report.failed_count > 0)
284
304
  sendUserToast(`Migration: ${report.migrated_count}/${report.total_secrets} migrated, ${report.failed_count} failed`, true);
285
305
  else
@@ -299,16 +319,47 @@ function isAwsSmConfigValid() {
299
319
  return $values['secret_backend'].region?.trim() !== '';
300
320
  }
301
321
  let baseUrl = $derived($values['base_url'] ?? 'https://your-windmill-instance.com');
322
+ let jwtMount = $derived(($values['secret_backend']?.jwt_mount_path?.trim() || 'jwt'));
323
+ let vaultAudience = $derived(($values['secret_backend']?.address?.trim() || 'https://vault.example.com:8200'));
302
324
  </script>
303
325
 
304
326
  <div class="space-y-6">
305
327
  <div class="flex flex-col gap-2 mt-1">
306
328
  <ToggleButtonGroup selected={selectedType} onSelected={(v) => setBackendType(v)}>
307
329
  {#snippet children({ item: toggleButton })}
308
- <ToggleButton value="Database" label="Database" tooltip="Store secrets encrypted in the database (default)" item={toggleButton} />
309
- <ToggleButton value="HashiCorpVault" label="HashiCorp Vault (Beta)" tooltip={vaultDisabled ? 'Requires Enterprise Edition' : 'Store secrets in HashiCorp Vault'} item={toggleButton} disabled={vaultDisabled} />
310
- <ToggleButton value="AzureKeyVault" label="Azure Key Vault" tooltip={vaultDisabled ? 'Requires Enterprise Edition' : 'Store secrets in Azure Key Vault'} item={toggleButton} disabled={vaultDisabled} />
311
- <ToggleButton value="AwsSecretsManager" label="AWS Secrets Manager (Beta)" tooltip={vaultDisabled ? 'Requires Enterprise Edition' : 'Store secrets in AWS Secrets Manager'} item={toggleButton} disabled={vaultDisabled} />
330
+ <ToggleButton
331
+ value="Database"
332
+ label="Database"
333
+ tooltip="Store secrets encrypted in the database (default)"
334
+ item={toggleButton}
335
+ />
336
+ <ToggleButton
337
+ value="HashiCorpVault"
338
+ label="HashiCorp Vault (Beta)"
339
+ tooltip={vaultDisabled
340
+ ? 'Requires Enterprise Edition'
341
+ : 'Store secrets in HashiCorp Vault'}
342
+ item={toggleButton}
343
+ disabled={vaultDisabled}
344
+ />
345
+ <ToggleButton
346
+ value="AzureKeyVault"
347
+ label="Azure Key Vault"
348
+ tooltip={vaultDisabled
349
+ ? 'Requires Enterprise Edition'
350
+ : 'Store secrets in Azure Key Vault'}
351
+ item={toggleButton}
352
+ disabled={vaultDisabled}
353
+ />
354
+ <ToggleButton
355
+ value="AwsSecretsManager"
356
+ label="AWS Secrets Manager (Beta)"
357
+ tooltip={vaultDisabled
358
+ ? 'Requires Enterprise Edition'
359
+ : 'Store secrets in AWS Secrets Manager'}
360
+ item={toggleButton}
361
+ disabled={vaultDisabled}
362
+ />
312
363
  {/snippet}
313
364
  </ToggleButtonGroup>
314
365
  {#if vaultDisabled}
@@ -323,7 +374,10 @@ let baseUrl = $derived($values['base_url'] ?? 'https://your-windmill-instance.co
323
374
  <Database class="text-primary" size={20} />
324
375
  <div>
325
376
  <p class="text-sm font-medium text-emphasis">Database Storage (Default)</p>
326
- <p class="text-xs text-secondary">Secrets are encrypted using workspace-specific keys and stored in the PostgreSQL database.</p>
377
+ <p class="text-xs text-secondary"
378
+ >Secrets are encrypted using workspace-specific keys and stored in the PostgreSQL
379
+ database.</p
380
+ >
327
381
  </div>
328
382
  </div>
329
383
  {:else if selectedType === 'HashiCorpVault'}
@@ -331,100 +385,221 @@ let baseUrl = $derived($values['base_url'] ?? 'https://your-windmill-instance.co
331
385
  <div class="flex items-center gap-2 mb-4">
332
386
  <Lock class="text-primary" size={20} />
333
387
  <div>
334
- <p class="text-sm font-medium text-emphasis">HashiCorp Vault Configuration <span class="ml-2 px-1.5 py-0.5 text-2xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 rounded">Beta</span></p>
335
- <p class="text-xs text-secondary">Store secrets in an external HashiCorp Vault instance.</p>
388
+ <p class="text-sm font-medium text-emphasis"
389
+ >HashiCorp Vault Configuration <span
390
+ class="ml-2 px-1.5 py-0.5 text-2xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 rounded"
391
+ >Beta</span
392
+ ></p
393
+ >
394
+ <p class="text-xs text-secondary"
395
+ >Store secrets in an external HashiCorp Vault instance.</p
396
+ >
336
397
  </div>
337
398
  </div>
338
399
  <div class="grid grid-cols-1 gap-4">
339
400
  <div class="flex flex-col gap-1">
340
- <label for="vault_address" class="block text-xs font-semibold text-emphasis">Vault Address</label>
341
- <TextInput inputProps={{ type: 'text', id: 'vault_address', placeholder: 'https://vault.company.com:8200', disabled }} bind:value={$values['secret_backend'].address} />
401
+ <label for="vault_address" class="block text-xs font-semibold text-emphasis"
402
+ >Vault Address</label
403
+ >
404
+ <TextInput
405
+ inputProps={{
406
+ type: 'text',
407
+ id: 'vault_address',
408
+ placeholder: 'https://vault.company.com:8200',
409
+ disabled
410
+ }}
411
+ bind:value={$values['secret_backend'].address}
412
+ />
342
413
  </div>
343
414
  <div class="flex flex-col gap-1">
344
- <label for="vault_mount_path" class="block text-xs font-semibold text-emphasis">KV Mount Path</label>
415
+ <label for="vault_mount_path" class="block text-xs font-semibold text-emphasis"
416
+ >KV Mount Path</label
417
+ >
345
418
  <span class="text-2xs text-secondary">The KV v2 secrets engine mount path in Vault</span>
346
- <TextInput inputProps={{ type: 'text', id: 'vault_mount_path', placeholder: 'windmill', disabled }} bind:value={$values['secret_backend'].mount_path} />
419
+ <TextInput
420
+ inputProps={{ type: 'text', id: 'vault_mount_path', placeholder: 'windmill', disabled }}
421
+ bind:value={$values['secret_backend'].mount_path}
422
+ />
347
423
  </div>
348
424
  <div class="flex flex-col gap-2">
349
425
  <span class="block text-xs font-semibold text-emphasis">Authentication Method</span>
350
426
  <ToggleButtonGroup selected={authMethod} onSelected={(v) => setAuthMethod(v)}>
351
427
  {#snippet children({ item: toggleButton })}
352
- <ToggleButton value="jwt" label="JWT Auth" tooltip="Authenticate using Windmill-signed JWTs" item={toggleButton} {disabled} />
353
- <ToggleButton value="token" label="Static Token" tooltip="Use a static Vault token" item={toggleButton} {disabled} />
428
+ <ToggleButton
429
+ value="jwt"
430
+ label="JWT Auth"
431
+ tooltip="Authenticate using Windmill-signed JWTs"
432
+ item={toggleButton}
433
+ {disabled}
434
+ />
435
+ <ToggleButton
436
+ value="token"
437
+ label="Static Token"
438
+ tooltip="Use a static Vault token"
439
+ item={toggleButton}
440
+ {disabled}
441
+ />
354
442
  {/snippet}
355
443
  </ToggleButtonGroup>
356
444
  </div>
357
445
  {#if authMethod === 'token'}
358
446
  <div class="flex flex-col gap-1 p-3 bg-surface-secondary rounded-lg">
359
- <label for="vault_token" class="block text-xs font-semibold text-emphasis">Vault Token</label>
360
- <span class="text-2xs text-secondary">Static token. Recommended only for testing/development.</span>
447
+ <label for="vault_token" class="block text-xs font-semibold text-emphasis"
448
+ >Vault Token</label
449
+ >
450
+ <span class="text-2xs text-secondary"
451
+ >Static token. Recommended only for testing/development.</span
452
+ >
361
453
  <Password bind:password={$values['secret_backend'].token} small {disabled} />
362
454
  </div>
363
455
  {:else}
364
456
  <div class="flex flex-col gap-2 p-3 bg-surface-secondary rounded-lg">
365
- <label for="vault_jwt_role" class="block text-xs font-semibold text-emphasis">JWT Auth Role</label>
366
- <span class="text-2xs text-secondary">The JWT authentication role configured in Vault.</span>
367
- <TextInput inputProps={{ type: 'text', id: 'vault_jwt_role', placeholder: 'windmill-secrets', disabled }} bind:value={$values['secret_backend'].jwt_role} />
457
+ <label for="vault_jwt_role" class="block text-xs font-semibold text-emphasis"
458
+ >JWT Auth Role</label
459
+ >
460
+ <span class="text-2xs text-secondary"
461
+ >The JWT authentication role configured in Vault.</span
462
+ >
463
+ <TextInput
464
+ inputProps={{
465
+ type: 'text',
466
+ id: 'vault_jwt_role',
467
+ placeholder: 'windmill-secrets',
468
+ disabled
469
+ }}
470
+ bind:value={$values['secret_backend'].jwt_role}
471
+ />
472
+ <label for="vault_jwt_mount_path" class="block text-xs font-semibold text-emphasis"
473
+ >JWT Auth Mount Path (optional)</label
474
+ >
475
+ <span class="text-2xs text-secondary"
476
+ >Mount path of the JWT auth method in Vault. Defaults to <code>jwt</code>. Set this
477
+ only if you mounted the JWT auth method at a non-default path (<code
478
+ >vault auth enable -path=&lt;mount&gt; jwt</code
479
+ >).</span
480
+ >
481
+ <TextInput
482
+ inputProps={{
483
+ type: 'text',
484
+ id: 'vault_jwt_mount_path',
485
+ placeholder: 'jwt',
486
+ disabled
487
+ }}
488
+ bind:value={$values['secret_backend'].jwt_mount_path}
489
+ />
368
490
  <details class="mt-2">
369
- <summary class="text-xs font-medium text-secondary cursor-pointer hover:text-primary">Vault JWT Setup Instructions</summary>
491
+ <summary class="text-xs font-medium text-secondary cursor-pointer hover:text-primary"
492
+ >Vault JWT Setup Instructions</summary
493
+ >
370
494
  <div class="mt-2 p-2 bg-surface rounded text-2xs text-secondary space-y-2">
371
495
  <p>Configure Vault to accept JWTs from Windmill:</p>
372
- <div class="bg-gray-100 dark:bg-gray-800 p-2 rounded font-mono text-2xs overflow-x-auto">
373
- <pre># Enable JWT auth method
374
- vault auth enable jwt
496
+ <div
497
+ class="bg-gray-100 dark:bg-gray-800 p-2 rounded font-mono text-2xs overflow-x-auto"
498
+ >
499
+ <pre
500
+ ># Enable JWT auth method{jwtMount === 'jwt'
501
+ ? ''
502
+ : ` at custom mount '${jwtMount}'`}
503
+ vault auth enable {jwtMount === 'jwt' ? 'jwt' : `-path=${jwtMount} jwt`}
375
504
 
376
505
  # Configure JWT auth with Windmill's JWKS endpoint
377
- vault write auth/jwt/config \
378
- jwks_url="{baseUrl}/.well-known/jwks.json" \
379
- bound_issuer="{baseUrl}"
506
+ vault write auth/{jwtMount}/config \
507
+ jwks_url="{baseUrl}/api/oidc/jwks" \
508
+ bound_issuer="{baseUrl}/api/oidc/"
380
509
 
381
510
  # Create a policy for Windmill secrets
382
511
  vault policy write windmill-secrets - &lt;&lt;EOF
383
- path "windmill/data/*" &#123;
512
+ path "{$values['secret_backend']?.mount_path ?? 'windmill'}/data/*" &#123;
384
513
  capabilities = ["create", "read", "update", "delete"]
385
514
  &#125;
386
- path "windmill/metadata/*" &#123;
515
+ path "{$values['secret_backend']?.mount_path ?? 'windmill'}/metadata/*" &#123;
387
516
  capabilities = ["list", "delete"]
388
517
  &#125;
389
518
  EOF
390
519
 
391
- # Create the JWT role
392
- vault write auth/jwt/role/windmill-secrets \
520
+ # Create the JWT role. bound_audiences must match the Vault server
521
+ # address Windmill signs the JWT with `aud` = your Vault address.
522
+ vault write auth/{jwtMount}/role/{$values['secret_backend']?.jwt_role || 'windmill-secrets'} \
393
523
  role_type="jwt" \
394
- bound_audiences="{baseUrl}" \
395
- user_claim="email" \
524
+ bound_audiences="{vaultAudience}" \
525
+ user_claim="sub" \
396
526
  policies="windmill-secrets" \
397
- ttl="1h"</pre>
527
+ ttl="1h"</pre
528
+ >
398
529
  </div>
399
530
  </div>
400
531
  </details>
401
532
  </div>
402
533
  {/if}
403
534
  <div class="flex flex-col gap-1">
404
- <label for="vault_namespace" class="block text-xs font-semibold text-emphasis">Namespace (optional)</label>
535
+ <label for="vault_namespace" class="block text-xs font-semibold text-emphasis"
536
+ >Namespace (optional)</label
537
+ >
405
538
  <span class="text-2xs text-secondary">Vault Enterprise namespace</span>
406
- <TextInput inputProps={{ type: 'text', id: 'vault_namespace', placeholder: 'admin/my-namespace', disabled }} bind:value={$values['secret_backend'].namespace} />
539
+ <TextInput
540
+ inputProps={{
541
+ type: 'text',
542
+ id: 'vault_namespace',
543
+ placeholder: 'admin/my-namespace',
544
+ disabled
545
+ }}
546
+ bind:value={$values['secret_backend'].namespace}
547
+ />
407
548
  </div>
408
549
  <div class="flex flex-col gap-1">
409
- <Toggle id="vault_skip_ssl_verify" {disabled} bind:checked={$values['secret_backend'].skip_ssl_verify} size="xs" options={{ right: 'Skip TLS certificate verification' }} />
410
- <span class="text-2xs text-secondary">Disables TLS verification when connecting to Vault. Only enable for self-signed certificates in development.</span>
550
+ <Toggle
551
+ id="vault_skip_ssl_verify"
552
+ {disabled}
553
+ bind:checked={$values['secret_backend'].skip_ssl_verify}
554
+ size="xs"
555
+ options={{ right: 'Skip TLS certificate verification' }}
556
+ />
557
+ <span class="text-2xs text-secondary"
558
+ >Disables TLS verification when connecting to Vault. Only enable for self-signed
559
+ certificates in development.</span
560
+ >
411
561
  </div>
412
562
  </div>
413
563
  <div class="flex flex-col gap-4 pt-4 border-t">
414
- <Button unifiedSize="md" variant="accent" onclick={testVaultConnection} disabled={disabled || !isVaultConfigValid() || testingConnection} loading={testingConnection} startIcon={{ icon: Server }}>Test Connection</Button>
564
+ <Button
565
+ unifiedSize="md"
566
+ variant="accent"
567
+ onclick={testVaultConnection}
568
+ disabled={disabled || !isVaultConfigValid() || testingConnection}
569
+ loading={testingConnection}
570
+ startIcon={{ icon: Server }}>Test Connection</Button
571
+ >
415
572
  <div class="flex flex-col gap-4 pt-4 border-t">
416
573
  <span class="block text-xs font-semibold text-emphasis">Secret Migration</span>
417
- <span class="text-2xs text-secondary">Original values are NOT deleted to allow for rollback.</span>
574
+ <span class="text-2xs text-secondary"
575
+ >Original values are NOT deleted to allow for rollback.</span
576
+ >
418
577
  <div class="flex gap-4">
419
578
  <div class="flex-1 p-3 border rounded-lg">
420
- <div class="flex items-center gap-2 mb-2"><Database size={16} /><ArrowRight size={16} /><Lock size={16} /></div>
579
+ <div class="flex items-center gap-2 mb-2"
580
+ ><Database size={16} /><ArrowRight size={16} /><Lock size={16} /></div
581
+ >
421
582
  <p class="text-xs font-medium mb-2">Database → Vault</p>
422
- <Button unifiedSize="sm" variant="default" onclick={() => (migrateToVaultModalOpen = true)} disabled={disabled || !isVaultConfigValid() || migratingToVault} startIcon={{ icon: ArrowRight }}>Migrate to Vault</Button>
583
+ <Button
584
+ unifiedSize="sm"
585
+ variant="default"
586
+ onclick={() => (migrateToVaultModalOpen = true)}
587
+ disabled={disabled || !isVaultConfigValid() || migratingToVault}
588
+ startIcon={{ icon: ArrowRight }}>Migrate to Vault</Button
589
+ >
423
590
  </div>
424
591
  <div class="flex-1 p-3 border rounded-lg">
425
- <div class="flex items-center gap-2 mb-2"><Lock size={16} /><ArrowLeft size={16} /><Database size={16} /></div>
592
+ <div class="flex items-center gap-2 mb-2"
593
+ ><Lock size={16} /><ArrowLeft size={16} /><Database size={16} /></div
594
+ >
426
595
  <p class="text-xs font-medium mb-2">Vault → Database</p>
427
- <Button unifiedSize="sm" variant="default" onclick={() => (migrateToDatabaseModalOpen = true)} disabled={disabled || !isVaultConfigValid() || migratingToDatabase} startIcon={{ icon: ArrowLeft }}>Migrate to Database</Button>
596
+ <Button
597
+ unifiedSize="sm"
598
+ variant="default"
599
+ onclick={() => (migrateToDatabaseModalOpen = true)}
600
+ disabled={disabled || !isVaultConfigValid() || migratingToDatabase}
601
+ startIcon={{ icon: ArrowLeft }}>Migrate to Database</Button
602
+ >
428
603
  </div>
429
604
  </div>
430
605
  </div>
@@ -441,42 +616,109 @@ vault write auth/jwt/role/windmill-secrets \
441
616
  </div>
442
617
  <div class="grid grid-cols-1 gap-4">
443
618
  <div class="flex flex-col gap-1">
444
- <label for="azure_vault_url" class="block text-xs font-semibold text-emphasis">Vault URL</label>
445
- <TextInput inputProps={{ type: 'text', id: 'azure_vault_url', placeholder: 'https://my-vault.vault.azure.net', disabled }} bind:value={$values['secret_backend'].vault_url} />
619
+ <label for="azure_vault_url" class="block text-xs font-semibold text-emphasis"
620
+ >Vault URL</label
621
+ >
622
+ <TextInput
623
+ inputProps={{
624
+ type: 'text',
625
+ id: 'azure_vault_url',
626
+ placeholder: 'https://my-vault.vault.azure.net',
627
+ disabled
628
+ }}
629
+ bind:value={$values['secret_backend'].vault_url}
630
+ />
446
631
  </div>
447
632
  <div class="flex flex-col gap-1">
448
- <label for="azure_tenant_id" class="block text-xs font-semibold text-emphasis">Tenant ID</label>
449
- <TextInput inputProps={{ type: 'text', id: 'azure_tenant_id', placeholder: '00000000-0000-0000-0000-000000000000', disabled }} bind:value={$values['secret_backend'].tenant_id} />
633
+ <label for="azure_tenant_id" class="block text-xs font-semibold text-emphasis"
634
+ >Tenant ID</label
635
+ >
636
+ <TextInput
637
+ inputProps={{
638
+ type: 'text',
639
+ id: 'azure_tenant_id',
640
+ placeholder: '00000000-0000-0000-0000-000000000000',
641
+ disabled
642
+ }}
643
+ bind:value={$values['secret_backend'].tenant_id}
644
+ />
450
645
  </div>
451
646
  <div class="flex flex-col gap-1">
452
- <label for="azure_client_id" class="block text-xs font-semibold text-emphasis">Client ID</label>
453
- <TextInput inputProps={{ type: 'text', id: 'azure_client_id', placeholder: '00000000-0000-0000-0000-000000000000', disabled }} bind:value={$values['secret_backend'].client_id} />
647
+ <label for="azure_client_id" class="block text-xs font-semibold text-emphasis"
648
+ >Client ID</label
649
+ >
650
+ <TextInput
651
+ inputProps={{
652
+ type: 'text',
653
+ id: 'azure_client_id',
654
+ placeholder: '00000000-0000-0000-0000-000000000000',
655
+ disabled
656
+ }}
657
+ bind:value={$values['secret_backend'].client_id}
658
+ />
454
659
  </div>
455
660
  <div class="flex flex-col gap-1 p-3 bg-surface-secondary rounded-lg">
456
- <label for="azure_client_secret" class="block text-xs font-semibold text-emphasis">Client Secret</label>
661
+ <label for="azure_client_secret" class="block text-xs font-semibold text-emphasis"
662
+ >Client Secret <span class="text-2xs font-normal text-secondary">(optional)</span
663
+ ></label
664
+ >
665
+ <span class="text-2xs text-secondary"
666
+ >Leave blank to use Azure Workload Identity. Requires
667
+ <code>AZURE_FEDERATED_TOKEN_FILE</code> on the Windmill process (auto-injected on AKS by
668
+ the workload-identity webhook; set manually on other Kubernetes clusters).</span
669
+ >
457
670
  <Password bind:password={$values['secret_backend'].client_secret} small {disabled} />
458
671
  </div>
459
672
  <div class="flex flex-col gap-1 p-3 bg-surface-secondary rounded-lg">
460
- <label for="azure_token" class="block text-xs font-semibold text-emphasis">Token (optional)</label>
461
- <span class="text-2xs text-secondary">Static Bearer token for testing. If provided, OAuth2 is skipped.</span>
673
+ <label for="azure_token" class="block text-xs font-semibold text-emphasis"
674
+ >Token (optional)</label
675
+ >
676
+ <span class="text-2xs text-secondary"
677
+ >Static Bearer token for testing. If provided, OAuth2 is skipped.</span
678
+ >
462
679
  <Password bind:password={$values['secret_backend'].token} small {disabled} />
463
680
  </div>
464
681
  </div>
465
682
  <div class="flex flex-col gap-4 pt-4 border-t">
466
- <Button unifiedSize="md" variant="accent" onclick={testAzureKvConnection} disabled={disabled || !isAzureKvConfigValid() || testingAzureKvConnection} loading={testingAzureKvConnection} startIcon={{ icon: Server }}>Test Connection</Button>
683
+ <Button
684
+ unifiedSize="md"
685
+ variant="accent"
686
+ onclick={testAzureKvConnection}
687
+ disabled={disabled || !isAzureKvConfigValid() || testingAzureKvConnection}
688
+ loading={testingAzureKvConnection}
689
+ startIcon={{ icon: Server }}>Test Connection</Button
690
+ >
467
691
  <div class="flex flex-col gap-4 pt-4 border-t">
468
692
  <span class="block text-xs font-semibold text-emphasis">Secret Migration</span>
469
- <span class="text-2xs text-secondary">Original values are NOT deleted to allow for rollback.</span>
693
+ <span class="text-2xs text-secondary"
694
+ >Original values are NOT deleted to allow for rollback.</span
695
+ >
470
696
  <div class="flex gap-4">
471
697
  <div class="flex-1 p-3 border rounded-lg">
472
- <div class="flex items-center gap-2 mb-2"><Database size={16} /><ArrowRight size={16} /><Cloud size={16} /></div>
698
+ <div class="flex items-center gap-2 mb-2"
699
+ ><Database size={16} /><ArrowRight size={16} /><Cloud size={16} /></div
700
+ >
473
701
  <p class="text-xs font-medium mb-2">Database → Azure Key Vault</p>
474
- <Button unifiedSize="sm" variant="default" onclick={() => (migrateToAzureKvModalOpen = true)} disabled={disabled || !isAzureKvConfigValid() || migratingToAzureKv} startIcon={{ icon: ArrowRight }}>Migrate to Azure KV</Button>
702
+ <Button
703
+ unifiedSize="sm"
704
+ variant="default"
705
+ onclick={() => (migrateToAzureKvModalOpen = true)}
706
+ disabled={disabled || !isAzureKvConfigValid() || migratingToAzureKv}
707
+ startIcon={{ icon: ArrowRight }}>Migrate to Azure KV</Button
708
+ >
475
709
  </div>
476
710
  <div class="flex-1 p-3 border rounded-lg">
477
- <div class="flex items-center gap-2 mb-2"><Cloud size={16} /><ArrowLeft size={16} /><Database size={16} /></div>
711
+ <div class="flex items-center gap-2 mb-2"
712
+ ><Cloud size={16} /><ArrowLeft size={16} /><Database size={16} /></div
713
+ >
478
714
  <p class="text-xs font-medium mb-2">Azure Key Vault → Database</p>
479
- <Button unifiedSize="sm" variant="default" onclick={() => (migrateFromAzureKvModalOpen = true)} disabled={disabled || !isAzureKvConfigValid() || migratingFromAzureKv} startIcon={{ icon: ArrowLeft }}>Migrate to Database</Button>
715
+ <Button
716
+ unifiedSize="sm"
717
+ variant="default"
718
+ onclick={() => (migrateFromAzureKvModalOpen = true)}
719
+ disabled={disabled || !isAzureKvConfigValid() || migratingFromAzureKv}
720
+ startIcon={{ icon: ArrowLeft }}>Migrate to Database</Button
721
+ >
480
722
  </div>
481
723
  </div>
482
724
  </div>
@@ -487,50 +729,118 @@ vault write auth/jwt/role/windmill-secrets \
487
729
  <div class="flex items-center gap-2 mb-4">
488
730
  <Cloud class="text-primary" size={20} />
489
731
  <div>
490
- <p class="text-sm font-medium text-emphasis">AWS Secrets Manager Configuration <span class="ml-2 px-1.5 py-0.5 text-2xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 rounded">Beta</span></p>
732
+ <p class="text-sm font-medium text-emphasis"
733
+ >AWS Secrets Manager Configuration <span
734
+ class="ml-2 px-1.5 py-0.5 text-2xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 rounded"
735
+ >Beta</span
736
+ ></p
737
+ >
491
738
  <p class="text-xs text-secondary">Store secrets in AWS Secrets Manager.</p>
492
739
  </div>
493
740
  </div>
494
741
  <div class="grid grid-cols-1 gap-4">
495
742
  <div class="flex flex-col gap-1">
496
- <label for="aws_sm_region" class="block text-xs font-semibold text-emphasis">Region</label>
497
- <TextInput inputProps={{ type: 'text', id: 'aws_sm_region', placeholder: 'us-east-1', disabled }} bind:value={$values['secret_backend'].region} />
743
+ <label for="aws_sm_region" class="block text-xs font-semibold text-emphasis">Region</label
744
+ >
745
+ <TextInput
746
+ inputProps={{ type: 'text', id: 'aws_sm_region', placeholder: 'us-east-1', disabled }}
747
+ bind:value={$values['secret_backend'].region}
748
+ />
498
749
  </div>
499
750
  <div class="flex flex-col gap-1">
500
- <label for="aws_sm_access_key_id" class="block text-xs font-semibold text-emphasis">Access Key ID (optional)</label>
501
- <span class="text-2xs text-secondary">If not provided, the default AWS credential chain is used (env vars, instance profile, EKS pod identity)</span>
502
- <TextInput inputProps={{ type: 'text', id: 'aws_sm_access_key_id', placeholder: 'AKIA...', disabled }} bind:value={$values['secret_backend'].access_key_id} />
751
+ <label for="aws_sm_access_key_id" class="block text-xs font-semibold text-emphasis"
752
+ >Access Key ID (optional)</label
753
+ >
754
+ <span class="text-2xs text-secondary"
755
+ >If not provided, the default AWS credential chain is used (env vars, instance profile,
756
+ EKS pod identity)</span
757
+ >
758
+ <TextInput
759
+ inputProps={{
760
+ type: 'text',
761
+ id: 'aws_sm_access_key_id',
762
+ placeholder: 'AKIA...',
763
+ disabled
764
+ }}
765
+ bind:value={$values['secret_backend'].access_key_id}
766
+ />
503
767
  </div>
504
768
  <div class="flex flex-col gap-1 p-3 bg-surface-secondary rounded-lg">
505
- <label for="aws_sm_secret_access_key" class="block text-xs font-semibold text-emphasis">Secret Access Key (optional)</label>
769
+ <label for="aws_sm_secret_access_key" class="block text-xs font-semibold text-emphasis"
770
+ >Secret Access Key (optional)</label
771
+ >
506
772
  <Password bind:password={$values['secret_backend'].secret_access_key} small {disabled} />
507
773
  </div>
508
774
  <div class="flex flex-col gap-1">
509
- <label for="aws_sm_prefix" class="block text-xs font-semibold text-emphasis">Secret Name Prefix (optional)</label>
510
- <span class="text-2xs text-secondary">Prefix for secret names in AWS Secrets Manager (default: windmill/)</span>
511
- <TextInput inputProps={{ type: 'text', id: 'aws_sm_prefix', placeholder: 'windmill/', disabled }} bind:value={$values['secret_backend'].prefix} />
775
+ <label for="aws_sm_prefix" class="block text-xs font-semibold text-emphasis"
776
+ >Secret Name Prefix (optional)</label
777
+ >
778
+ <span class="text-2xs text-secondary"
779
+ >Prefix for secret names in AWS Secrets Manager (default: windmill/)</span
780
+ >
781
+ <TextInput
782
+ inputProps={{ type: 'text', id: 'aws_sm_prefix', placeholder: 'windmill/', disabled }}
783
+ bind:value={$values['secret_backend'].prefix}
784
+ />
512
785
  </div>
513
786
  <div class="flex flex-col gap-1">
514
- <label for="aws_sm_endpoint_url" class="block text-xs font-semibold text-emphasis">Endpoint URL (optional)</label>
515
- <span class="text-2xs text-secondary">Custom endpoint for LocalStack or other compatible services</span>
516
- <TextInput inputProps={{ type: 'text', id: 'aws_sm_endpoint_url', placeholder: 'http://localhost:4566', disabled }} bind:value={$values['secret_backend'].endpoint_url} />
787
+ <label for="aws_sm_endpoint_url" class="block text-xs font-semibold text-emphasis"
788
+ >Endpoint URL (optional)</label
789
+ >
790
+ <span class="text-2xs text-secondary"
791
+ >Custom endpoint for LocalStack or other compatible services</span
792
+ >
793
+ <TextInput
794
+ inputProps={{
795
+ type: 'text',
796
+ id: 'aws_sm_endpoint_url',
797
+ placeholder: 'http://localhost:4566',
798
+ disabled
799
+ }}
800
+ bind:value={$values['secret_backend'].endpoint_url}
801
+ />
517
802
  </div>
518
803
  </div>
519
804
  <div class="flex flex-col gap-4 pt-4 border-t">
520
- <Button unifiedSize="md" variant="accent" onclick={testAwsSmConnection} disabled={disabled || !isAwsSmConfigValid() || testingAwsSmConnection} loading={testingAwsSmConnection} startIcon={{ icon: Server }}>Test Connection</Button>
805
+ <Button
806
+ unifiedSize="md"
807
+ variant="accent"
808
+ onclick={testAwsSmConnection}
809
+ disabled={disabled || !isAwsSmConfigValid() || testingAwsSmConnection}
810
+ loading={testingAwsSmConnection}
811
+ startIcon={{ icon: Server }}>Test Connection</Button
812
+ >
521
813
  <div class="flex flex-col gap-4 pt-4 border-t">
522
814
  <span class="block text-xs font-semibold text-emphasis">Secret Migration</span>
523
- <span class="text-2xs text-secondary">Original values are NOT deleted to allow for rollback.</span>
815
+ <span class="text-2xs text-secondary"
816
+ >Original values are NOT deleted to allow for rollback.</span
817
+ >
524
818
  <div class="flex gap-4">
525
819
  <div class="flex-1 p-3 border rounded-lg">
526
- <div class="flex items-center gap-2 mb-2"><Database size={16} /><ArrowRight size={16} /><Cloud size={16} /></div>
820
+ <div class="flex items-center gap-2 mb-2"
821
+ ><Database size={16} /><ArrowRight size={16} /><Cloud size={16} /></div
822
+ >
527
823
  <p class="text-xs font-medium mb-2">Database → AWS Secrets Manager</p>
528
- <Button unifiedSize="sm" variant="default" onclick={() => (migrateToAwsSmModalOpen = true)} disabled={disabled || !isAwsSmConfigValid() || migratingToAwsSm} startIcon={{ icon: ArrowRight }}>Migrate to AWS SM</Button>
824
+ <Button
825
+ unifiedSize="sm"
826
+ variant="default"
827
+ onclick={() => (migrateToAwsSmModalOpen = true)}
828
+ disabled={disabled || !isAwsSmConfigValid() || migratingToAwsSm}
829
+ startIcon={{ icon: ArrowRight }}>Migrate to AWS SM</Button
830
+ >
529
831
  </div>
530
832
  <div class="flex-1 p-3 border rounded-lg">
531
- <div class="flex items-center gap-2 mb-2"><Cloud size={16} /><ArrowLeft size={16} /><Database size={16} /></div>
833
+ <div class="flex items-center gap-2 mb-2"
834
+ ><Cloud size={16} /><ArrowLeft size={16} /><Database size={16} /></div
835
+ >
532
836
  <p class="text-xs font-medium mb-2">AWS Secrets Manager → Database</p>
533
- <Button unifiedSize="sm" variant="default" onclick={() => (migrateFromAwsSmModalOpen = true)} disabled={disabled || !isAwsSmConfigValid() || migratingFromAwsSm} startIcon={{ icon: ArrowLeft }}>Migrate to Database</Button>
837
+ <Button
838
+ unifiedSize="sm"
839
+ variant="default"
840
+ onclick={() => (migrateFromAwsSmModalOpen = true)}
841
+ disabled={disabled || !isAwsSmConfigValid() || migratingFromAwsSm}
842
+ startIcon={{ icon: ArrowLeft }}>Migrate to Database</Button
843
+ >
534
844
  </div>
535
845
  </div>
536
846
  </div>
@@ -539,21 +849,105 @@ vault write auth/jwt/role/windmill-secrets \
539
849
  {/if}
540
850
  </div>
541
851
 
542
- <ConfirmationModal title="Migrate to AWS Secrets Manager" confirmationText="Migrate" open={migrateToAwsSmModalOpen} loading={migratingToAwsSm} type="reload" onCanceled={() => { migrateToAwsSmModalOpen = false }} onConfirmed={migrateSecretsToAwsSm}>
543
- {#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets from the database to AWS Secrets Manager.</p><p class="text-yellow-600 dark:text-yellow-400 text-sm">Database values are NOT deleted automatically.</p></div>{/snippet}
852
+ <ConfirmationModal
853
+ title="Migrate to AWS Secrets Manager"
854
+ confirmationText="Migrate"
855
+ open={migrateToAwsSmModalOpen}
856
+ loading={migratingToAwsSm}
857
+ type="reload"
858
+ onCanceled={() => {
859
+ migrateToAwsSmModalOpen = false
860
+ }}
861
+ onConfirmed={migrateSecretsToAwsSm}
862
+ >
863
+ {#snippet children()}<div class="flex flex-col gap-2"
864
+ ><p>This will copy all secrets from the database to AWS Secrets Manager.</p><p
865
+ class="text-yellow-600 dark:text-yellow-400 text-sm"
866
+ >Database values are NOT deleted automatically.</p
867
+ ></div
868
+ >{/snippet}
544
869
  </ConfirmationModal>
545
- <ConfirmationModal title="Migrate to Database" confirmationText="Migrate" open={migrateFromAwsSmModalOpen} loading={migratingFromAwsSm} type="reload" onCanceled={() => { migrateFromAwsSmModalOpen = false }} onConfirmed={migrateSecretsFromAwsSm}>
546
- {#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets from AWS Secrets Manager back to the database.</p><p class="text-yellow-600 dark:text-yellow-400 text-sm">AWS Secrets Manager values are NOT deleted automatically.</p></div>{/snippet}
870
+ <ConfirmationModal
871
+ title="Migrate to Database"
872
+ confirmationText="Migrate"
873
+ open={migrateFromAwsSmModalOpen}
874
+ loading={migratingFromAwsSm}
875
+ type="reload"
876
+ onCanceled={() => {
877
+ migrateFromAwsSmModalOpen = false
878
+ }}
879
+ onConfirmed={migrateSecretsFromAwsSm}
880
+ >
881
+ {#snippet children()}<div class="flex flex-col gap-2"
882
+ ><p>This will copy all secrets from AWS Secrets Manager back to the database.</p><p
883
+ class="text-yellow-600 dark:text-yellow-400 text-sm"
884
+ >AWS Secrets Manager values are NOT deleted automatically.</p
885
+ ></div
886
+ >{/snippet}
547
887
  </ConfirmationModal>
548
- <ConfirmationModal title="Migrate to Azure Key Vault" confirmationText="Migrate" open={migrateToAzureKvModalOpen} loading={migratingToAzureKv} type="reload" onCanceled={() => { migrateToAzureKvModalOpen = false }} onConfirmed={migrateSecretsToAzureKv}>
549
- {#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets to Azure Key Vault.</p><p class="text-yellow-600 dark:text-yellow-400 text-sm">Database values are NOT deleted automatically.</p></div>{/snippet}
888
+ <ConfirmationModal
889
+ title="Migrate to Azure Key Vault"
890
+ confirmationText="Migrate"
891
+ open={migrateToAzureKvModalOpen}
892
+ loading={migratingToAzureKv}
893
+ type="reload"
894
+ onCanceled={() => {
895
+ migrateToAzureKvModalOpen = false
896
+ }}
897
+ onConfirmed={migrateSecretsToAzureKv}
898
+ >
899
+ {#snippet children()}<div class="flex flex-col gap-2"
900
+ ><p>This will copy all secrets to Azure Key Vault.</p><p
901
+ class="text-yellow-600 dark:text-yellow-400 text-sm"
902
+ >Database values are NOT deleted automatically.</p
903
+ ></div
904
+ >{/snippet}
550
905
  </ConfirmationModal>
551
- <ConfirmationModal title="Migrate to Database" confirmationText="Migrate" open={migrateFromAzureKvModalOpen} loading={migratingFromAzureKv} type="reload" onCanceled={() => { migrateFromAzureKvModalOpen = false }} onConfirmed={migrateSecretsFromAzureKv}>
552
- {#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets from Azure Key Vault back to the database.</p></div>{/snippet}
906
+ <ConfirmationModal
907
+ title="Migrate to Database"
908
+ confirmationText="Migrate"
909
+ open={migrateFromAzureKvModalOpen}
910
+ loading={migratingFromAzureKv}
911
+ type="reload"
912
+ onCanceled={() => {
913
+ migrateFromAzureKvModalOpen = false
914
+ }}
915
+ onConfirmed={migrateSecretsFromAzureKv}
916
+ >
917
+ {#snippet children()}<div class="flex flex-col gap-2"
918
+ ><p>This will copy all secrets from Azure Key Vault back to the database.</p></div
919
+ >{/snippet}
553
920
  </ConfirmationModal>
554
- <ConfirmationModal title="Migrate to Vault" confirmationText="Migrate" open={migrateToVaultModalOpen} loading={migratingToVault} type="reload" onCanceled={() => { migrateToVaultModalOpen = false }} onConfirmed={migrateSecretsToVault}>
555
- {#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets to HashiCorp Vault.</p><p class="text-yellow-600 dark:text-yellow-400 text-sm">Database values are NOT deleted automatically.</p></div>{/snippet}
921
+ <ConfirmationModal
922
+ title="Migrate to Vault"
923
+ confirmationText="Migrate"
924
+ open={migrateToVaultModalOpen}
925
+ loading={migratingToVault}
926
+ type="reload"
927
+ onCanceled={() => {
928
+ migrateToVaultModalOpen = false
929
+ }}
930
+ onConfirmed={migrateSecretsToVault}
931
+ >
932
+ {#snippet children()}<div class="flex flex-col gap-2"
933
+ ><p>This will copy all secrets to HashiCorp Vault.</p><p
934
+ class="text-yellow-600 dark:text-yellow-400 text-sm"
935
+ >Database values are NOT deleted automatically.</p
936
+ ></div
937
+ >{/snippet}
556
938
  </ConfirmationModal>
557
- <ConfirmationModal title="Migrate to Database" confirmationText="Migrate" open={migrateToDatabaseModalOpen} loading={migratingToDatabase} type="reload" onCanceled={() => { migrateToDatabaseModalOpen = false }} onConfirmed={migrateSecretsToDatabase}>
558
- {#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets from Vault back to the database.</p></div>{/snippet}
939
+ <ConfirmationModal
940
+ title="Migrate to Database"
941
+ confirmationText="Migrate"
942
+ open={migrateToDatabaseModalOpen}
943
+ loading={migratingToDatabase}
944
+ type="reload"
945
+ onCanceled={() => {
946
+ migrateToDatabaseModalOpen = false
947
+ }}
948
+ onConfirmed={migrateSecretsToDatabase}
949
+ >
950
+ {#snippet children()}<div class="flex flex-col gap-2"
951
+ ><p>This will copy all secrets from Vault back to the database.</p></div
952
+ >{/snippet}
559
953
  </ConfirmationModal>