@matthesketh/fleet 1.8.1 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/README.md +186 -16
  2. package/dist/bin/fleet-agent.d.ts +2 -0
  3. package/dist/bin/fleet-agent.js +7 -0
  4. package/dist/cli.d.ts +5 -0
  5. package/dist/cli.js +73 -31
  6. package/dist/commands/add.d.ts +2 -1
  7. package/dist/commands/add.js +66 -59
  8. package/dist/commands/audit.d.ts +1 -0
  9. package/dist/commands/audit.js +144 -0
  10. package/dist/commands/backup.d.ts +1 -0
  11. package/dist/commands/backup.js +510 -0
  12. package/dist/commands/boot-start.d.ts +3 -1
  13. package/dist/commands/boot-start.js +39 -47
  14. package/dist/commands/completions.d.ts +6 -0
  15. package/dist/commands/completions.js +83 -0
  16. package/dist/commands/config.d.ts +16 -0
  17. package/dist/commands/config.js +96 -0
  18. package/dist/commands/deploy.js +3 -2
  19. package/dist/commands/deps.js +5 -1
  20. package/dist/commands/doctor.d.ts +32 -0
  21. package/dist/commands/doctor.js +186 -0
  22. package/dist/commands/egress.d.ts +1 -1
  23. package/dist/commands/egress.js +13 -10
  24. package/dist/commands/freeze.d.ts +8 -4
  25. package/dist/commands/freeze.js +77 -59
  26. package/dist/commands/git.js +2 -2
  27. package/dist/commands/health.d.ts +2 -1
  28. package/dist/commands/health.js +38 -56
  29. package/dist/commands/init.d.ts +2 -1
  30. package/dist/commands/init.js +83 -73
  31. package/dist/commands/install-mcp.d.ts +3 -1
  32. package/dist/commands/install-mcp.js +53 -34
  33. package/dist/commands/list.d.ts +2 -1
  34. package/dist/commands/list.js +22 -19
  35. package/dist/commands/logs.js +1 -1
  36. package/dist/commands/patch-systemd.d.ts +7 -1
  37. package/dist/commands/patch-systemd.js +71 -31
  38. package/dist/commands/remove.d.ts +3 -1
  39. package/dist/commands/remove.js +37 -26
  40. package/dist/commands/restart.d.ts +4 -1
  41. package/dist/commands/restart.js +17 -20
  42. package/dist/commands/rollback.d.ts +4 -1
  43. package/dist/commands/rollback.js +33 -42
  44. package/dist/commands/secrets.js +157 -9
  45. package/dist/commands/start.d.ts +4 -1
  46. package/dist/commands/start.js +17 -20
  47. package/dist/commands/status.d.ts +1 -1
  48. package/dist/commands/status.js +21 -26
  49. package/dist/commands/stop.d.ts +4 -1
  50. package/dist/commands/stop.js +17 -20
  51. package/dist/commands/testflight.d.ts +1 -0
  52. package/dist/commands/testflight.js +193 -0
  53. package/dist/commands/update.d.ts +16 -0
  54. package/dist/commands/update.js +95 -0
  55. package/dist/core/audit/cache.d.ts +4 -0
  56. package/dist/core/audit/cache.js +37 -0
  57. package/dist/core/audit/config.d.ts +5 -0
  58. package/dist/core/audit/config.js +35 -0
  59. package/dist/core/audit/greenlight.d.ts +11 -0
  60. package/dist/core/audit/greenlight.js +81 -0
  61. package/dist/core/audit/reporters/cli.d.ts +3 -0
  62. package/dist/core/audit/reporters/cli.js +68 -0
  63. package/dist/core/audit/suppress.d.ts +6 -0
  64. package/dist/core/audit/suppress.js +37 -0
  65. package/dist/core/audit/target.d.ts +5 -0
  66. package/dist/core/audit/target.js +26 -0
  67. package/dist/core/audit/types.d.ts +54 -0
  68. package/dist/core/audit/types.js +5 -0
  69. package/dist/core/backup/browser-api.d.ts +66 -0
  70. package/dist/core/backup/browser-api.js +197 -0
  71. package/dist/core/backup/browser-server.d.ts +11 -0
  72. package/dist/core/backup/browser-server.js +241 -0
  73. package/dist/core/backup/browser-ui.d.ts +5 -0
  74. package/dist/core/backup/browser-ui.js +268 -0
  75. package/dist/core/backup/cloudflare.d.ts +7 -0
  76. package/dist/core/backup/cloudflare.js +82 -0
  77. package/dist/core/backup/config.d.ts +9 -0
  78. package/dist/core/backup/config.js +80 -0
  79. package/dist/core/backup/detect.d.ts +11 -0
  80. package/dist/core/backup/detect.js +71 -0
  81. package/dist/core/backup/dump.d.ts +11 -0
  82. package/dist/core/backup/dump.js +82 -0
  83. package/dist/core/backup/index.d.ts +9 -0
  84. package/dist/core/backup/index.js +9 -0
  85. package/dist/core/backup/repo.d.ts +71 -0
  86. package/dist/core/backup/repo.js +256 -0
  87. package/dist/core/backup/schedule.d.ts +17 -0
  88. package/dist/core/backup/schedule.js +90 -0
  89. package/dist/core/backup/sensitive.d.ts +5 -0
  90. package/dist/core/backup/sensitive.js +37 -0
  91. package/dist/core/backup/status.d.ts +3 -0
  92. package/dist/core/backup/status.js +29 -0
  93. package/dist/core/backup/statuspage.d.ts +23 -0
  94. package/dist/core/backup/statuspage.js +145 -0
  95. package/dist/core/backup/system.d.ts +24 -0
  96. package/dist/core/backup/system.js +209 -0
  97. package/dist/core/backup/totp.d.ts +16 -0
  98. package/dist/core/backup/totp.js +116 -0
  99. package/dist/core/backup/types.d.ts +70 -0
  100. package/dist/core/backup/types.js +7 -0
  101. package/dist/core/backup/unlock.d.ts +19 -0
  102. package/dist/core/backup/unlock.js +69 -0
  103. package/dist/core/boot-refresh.d.ts +1 -1
  104. package/dist/core/boot-refresh.js +10 -9
  105. package/dist/core/deps/actors/pr-creator.d.ts +5 -3
  106. package/dist/core/deps/actors/pr-creator.js +71 -18
  107. package/dist/core/deps/collectors/fetch-with-timeout.d.ts +7 -0
  108. package/dist/core/deps/collectors/fetch-with-timeout.js +16 -0
  109. package/dist/core/deps/collectors/npm.js +3 -1
  110. package/dist/core/deps/collectors/vulnerability.d.ts +8 -0
  111. package/dist/core/deps/collectors/vulnerability.js +31 -2
  112. package/dist/core/deps/config.js +6 -0
  113. package/dist/core/deps/scanner.js +1 -1
  114. package/dist/core/deps/types.d.ts +8 -0
  115. package/dist/core/env.d.ts +3 -0
  116. package/dist/core/env.js +11 -0
  117. package/dist/core/exec.d.ts +1 -0
  118. package/dist/core/exec.js +4 -0
  119. package/dist/core/file-lock.d.ts +18 -0
  120. package/dist/core/file-lock.js +44 -0
  121. package/dist/core/git-onboard.js +10 -13
  122. package/dist/core/github.d.ts +3 -1
  123. package/dist/core/github.js +10 -7
  124. package/dist/core/logs-policy.d.ts +5 -0
  125. package/dist/core/logs-policy.js +20 -1
  126. package/dist/core/operator.d.ts +21 -0
  127. package/dist/core/operator.js +54 -0
  128. package/dist/core/registry.d.ts +18 -0
  129. package/dist/core/registry.js +26 -0
  130. package/dist/core/routines/schema.d.ts +11 -11
  131. package/dist/core/routines/schema.js +14 -3
  132. package/dist/core/routines/store.d.ts +8 -8
  133. package/dist/core/secrets-ops.d.ts +31 -6
  134. package/dist/core/secrets-ops.js +208 -102
  135. package/dist/core/secrets-providers.js +2 -2
  136. package/dist/core/secrets-rotation.d.ts +1 -1
  137. package/dist/core/secrets-rotation.js +58 -52
  138. package/dist/core/secrets-v2-cleanup.d.ts +19 -0
  139. package/dist/core/secrets-v2-cleanup.js +94 -0
  140. package/dist/core/secrets-v2-creds.d.ts +9 -0
  141. package/dist/core/secrets-v2-creds.js +44 -0
  142. package/dist/core/secrets-v2-install.d.ts +13 -0
  143. package/dist/core/secrets-v2-install.js +76 -0
  144. package/dist/core/secrets-v2-keypair.d.ts +10 -0
  145. package/dist/core/secrets-v2-keypair.js +31 -0
  146. package/dist/core/secrets-v2-migrate.d.ts +29 -0
  147. package/dist/core/secrets-v2-migrate.js +395 -0
  148. package/dist/core/secrets-v2-ops.d.ts +36 -0
  149. package/dist/core/secrets-v2-ops.js +184 -0
  150. package/dist/core/secrets-v2-protocol.d.ts +19 -0
  151. package/dist/core/secrets-v2-protocol.js +60 -0
  152. package/dist/core/secrets-v2-snapshot.d.ts +36 -0
  153. package/dist/core/secrets-v2-snapshot.js +115 -0
  154. package/dist/core/secrets-v2.d.ts +21 -0
  155. package/dist/core/secrets-v2.js +249 -0
  156. package/dist/core/secrets.d.ts +39 -4
  157. package/dist/core/secrets.js +91 -11
  158. package/dist/core/self-update.d.ts +32 -11
  159. package/dist/core/self-update.js +52 -14
  160. package/dist/core/testflight/asc.d.ts +12 -0
  161. package/dist/core/testflight/asc.js +101 -0
  162. package/dist/core/testflight/credentials.d.ts +3 -0
  163. package/dist/core/testflight/credentials.js +35 -0
  164. package/dist/core/testflight/resolve.d.ts +6 -0
  165. package/dist/core/testflight/resolve.js +44 -0
  166. package/dist/core/testflight/types.d.ts +13 -0
  167. package/dist/core/testflight/types.js +3 -0
  168. package/dist/core/testflight/workflow.d.ts +17 -0
  169. package/dist/core/testflight/workflow.js +65 -0
  170. package/dist/core/validate.d.ts +1 -0
  171. package/dist/core/validate.js +8 -0
  172. package/dist/index.js +0 -0
  173. package/dist/mcp/audit-tools.d.ts +2 -0
  174. package/dist/mcp/audit-tools.js +94 -0
  175. package/dist/mcp/git-tools.js +1 -1
  176. package/dist/mcp/registry-bridge.d.ts +10 -0
  177. package/dist/mcp/registry-bridge.js +65 -0
  178. package/dist/mcp/secrets-tools.js +2 -2
  179. package/dist/mcp/server.js +16 -82
  180. package/dist/mcp/testflight-tools.d.ts +2 -0
  181. package/dist/mcp/testflight-tools.js +52 -0
  182. package/dist/registry/context.d.ts +7 -0
  183. package/dist/registry/context.js +37 -0
  184. package/dist/registry/index.d.ts +5 -0
  185. package/dist/registry/index.js +44 -0
  186. package/dist/registry/parse-args.d.ts +13 -0
  187. package/dist/registry/parse-args.js +74 -0
  188. package/dist/registry/registry.d.ts +24 -0
  189. package/dist/registry/registry.js +26 -0
  190. package/dist/registry/render.d.ts +3 -0
  191. package/dist/registry/render.js +29 -0
  192. package/dist/registry/types.d.ts +50 -0
  193. package/dist/registry/types.js +1 -0
  194. package/dist/templates/agent-unit.d.ts +5 -0
  195. package/dist/templates/agent-unit.js +40 -0
  196. package/dist/templates/app-unit-edit.d.ts +2 -0
  197. package/dist/templates/app-unit-edit.js +46 -0
  198. package/dist/templates/compose-edit.d.ts +2 -0
  199. package/dist/templates/compose-edit.js +156 -0
  200. package/dist/templates/nginx.js +11 -0
  201. package/dist/templates/systemd.js +6 -0
  202. package/dist/tui/components/ArgForm.d.ts +7 -0
  203. package/dist/tui/components/ArgForm.js +64 -0
  204. package/dist/tui/components/ArgForm.test.d.ts +1 -0
  205. package/dist/tui/components/ArgForm.test.js +19 -0
  206. package/dist/tui/components/KeyHint.js +5 -0
  207. package/dist/tui/hooks/use-secrets.d.ts +8 -8
  208. package/dist/tui/hooks/use-secrets.js +7 -7
  209. package/dist/tui/router.d.ts +1 -0
  210. package/dist/tui/router.js +26 -9
  211. package/dist/tui/router.test.d.ts +1 -0
  212. package/dist/tui/router.test.js +13 -0
  213. package/dist/tui/routines/components/SignalsGrid.test.js +2 -2
  214. package/dist/tui/routines/tabs/ScaffoldTab.js +1 -1
  215. package/dist/tui/tests/redaction-rerender.test.d.ts +1 -0
  216. package/dist/tui/tests/redaction-rerender.test.js +53 -0
  217. package/dist/tui/tests/scroll-flicker-proof.test.d.ts +1 -0
  218. package/dist/tui/tests/scroll-flicker-proof.test.js +145 -0
  219. package/dist/tui/types.d.ts +1 -1
  220. package/dist/tui/views/CommandPalette.d.ts +5 -0
  221. package/dist/tui/views/CommandPalette.js +90 -0
  222. package/dist/tui/views/CommandPalette.test.d.ts +1 -0
  223. package/dist/tui/views/CommandPalette.test.js +117 -0
  224. package/dist/tui/views/Dashboard.js +9 -6
  225. package/dist/tui/views/HealthView.js +9 -4
  226. package/dist/tui/views/SecretEdit.js +15 -16
  227. package/dist/tui/views/SecretEdit.test.d.ts +1 -0
  228. package/dist/tui/views/SecretEdit.test.js +82 -0
  229. package/dist/tui/views/SecretsView.js +26 -16
  230. package/package.json +8 -5
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render } from 'ink-testing-library';
3
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
4
+ import { InputDispatcher } from '@matthesketh/ink-input-dispatcher';
5
+ import { AppStateContext, AppDispatchContext, initialState } from '../state.js';
6
+ import { SecretEdit } from './SecretEdit.js';
7
+ // Mock useSecrets so the component doesn't try to touch the real vault.
8
+ vi.mock('../hooks/use-secrets.js', () => ({
9
+ useSecrets: () => ({
10
+ initialized: true,
11
+ sealed: false,
12
+ apps: [],
13
+ secrets: [],
14
+ revealedValues: {},
15
+ loading: false,
16
+ error: null,
17
+ refresh: () => { },
18
+ loadAppSecrets: () => { },
19
+ saveSecret: () => ({ ok: true }),
20
+ deleteSecret: () => ({ ok: true }),
21
+ revealSecret: () => { },
22
+ hideSecret: () => { },
23
+ unseal: () => ({ ok: true }),
24
+ seal: () => ({ ok: true }),
25
+ importEnv: () => ({ ok: true }),
26
+ }),
27
+ }));
28
+ function renderWithState(state) {
29
+ const dispatch = () => { };
30
+ return render(_jsx(AppStateContext.Provider, { value: state, children: _jsx(AppDispatchContext.Provider, { value: dispatch, children: _jsx(InputDispatcher, { globalHandler: () => false, children: _jsx(SecretEdit, {}) }) }) }));
31
+ }
32
+ describe('SecretEdit (security policy: never preload secret values)', () => {
33
+ beforeEach(() => {
34
+ vi.clearAllMocks();
35
+ });
36
+ it('Edit case: shows the existing key but the value field starts empty', () => {
37
+ // Policy: editing an existing secret means re-typing the value.
38
+ // The TUI must NOT decrypt the existing value into React state because
39
+ // mask="*" only affects rendering, not the underlying string.
40
+ const state = {
41
+ ...initialState,
42
+ selectedApp: 'my-app',
43
+ selectedSecret: 'API_KEY',
44
+ };
45
+ const { lastFrame } = renderWithState(state);
46
+ const frame = lastFrame();
47
+ expect(frame).toContain('Edit Secret');
48
+ expect(frame).toContain('API_KEY');
49
+ // Helper text must announce the policy.
50
+ expect(frame).toContain('Current value not displayed');
51
+ // Even though TextInput is rendered for the value, no plaintext or
52
+ // mask glyphs should appear for the value (it is empty).
53
+ // The "Value:" label is present, and any content after it on that
54
+ // line must not contain '*' characters from a preloaded masked value.
55
+ const valueLine = frame.split('\n').find(l => l.includes('Value:'));
56
+ expect(valueLine).not.toMatch(/\*/);
57
+ });
58
+ it('New case: prompts for key first and shows the new-secret helper text', () => {
59
+ const state = {
60
+ ...initialState,
61
+ selectedApp: 'my-app',
62
+ selectedSecret: null,
63
+ };
64
+ const { lastFrame } = renderWithState(state);
65
+ const frame = lastFrame();
66
+ expect(frame).toContain('Add Secret');
67
+ expect(frame).toContain('Adding new secret');
68
+ // Until the user enters a key, the value field shows the placeholder
69
+ // and is NOT yet active.
70
+ expect(frame).toContain('press Enter on key first');
71
+ });
72
+ it('does not import getSecret (no preload code path remains)', async () => {
73
+ // Static guard: the SecretEdit module must not import getCoreSecret
74
+ // from secrets-ops. If a future change re-introduces the preload,
75
+ // this test fails.
76
+ const fs = await import('node:fs');
77
+ const url = await import('node:url');
78
+ const source = fs.readFileSync(url.fileURLToPath(new URL('./SecretEdit.tsx', import.meta.url)), 'utf8');
79
+ expect(source).not.toMatch(/getSecret as getCoreSecret/);
80
+ expect(source).not.toMatch(/from '\.\.\/\.\.\/core\/secrets-ops/);
81
+ });
82
+ });
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useCallback } from 'react';
2
+ import { useEffect, useCallback, useMemo } from 'react';
3
3
  import { Box, Text } from 'ink';
4
4
  import { useRegisterHandler } from '@matthesketh/ink-input-dispatcher';
5
5
  import { ScrollableList } from '@matthesketh/ink-scrollable-list';
6
6
  import { useAvailableHeight } from '@matthesketh/ink-viewport';
7
- import { useAppState, useAppDispatch, useRedact } from '../state.js';
7
+ import { useAppState, useAppDispatch, useRedact, redactName } from '../state.js';
8
8
  import { useSecrets } from '../hooks/use-secrets.js';
9
9
  import { colors } from '../theme.js';
10
10
  export function SecretsView() {
@@ -14,6 +14,12 @@ export function SecretsView() {
14
14
  const secrets = useSecrets();
15
15
  const availableHeight = useAvailableHeight();
16
16
  const { secretsSubView: subView, secretsIndex: selectedIndex, selectedApp } = state;
17
+ const appItems = useMemo(() => secrets.apps.map(a => ({
18
+ ...a,
19
+ // same reasoning as the dashboard view — ScrollableList memoises rows by
20
+ // item identity, so the redacted label must live on the item itself.
21
+ displayApp: state.redacted ? redactName(a.app) : a.app,
22
+ })), [secrets.apps, state.redacted]);
17
23
  const refresh = secrets.refresh;
18
24
  useEffect(() => {
19
25
  refresh();
@@ -47,11 +53,14 @@ export function SecretsView() {
47
53
  return true;
48
54
  }
49
55
  if (input === 'l') {
50
- const result = secrets.seal();
51
- if (!result.ok) {
52
- dispatch({ type: 'SET_ERROR', error: result.error ?? 'Seal failed' });
53
- }
54
- secrets.refresh();
56
+ // Seal acquires a manifest lock and may take a moment; fire-and-forget
57
+ // from the input handler, dispatch errors / refresh on completion.
58
+ secrets.seal().then(result => {
59
+ if (!result.ok) {
60
+ dispatch({ type: 'SET_ERROR', error: result.error ?? 'Seal failed' });
61
+ }
62
+ secrets.refresh();
63
+ });
55
64
  return true;
56
65
  }
57
66
  }
@@ -89,14 +98,15 @@ export function SecretsView() {
89
98
  label: `Delete secret "${secretKey}"?`,
90
99
  description: `This will remove ${secretKey} from ${redact(appName)}'s vault.`,
91
100
  onConfirm: () => {
92
- const result = secrets.deleteSecret(appName, secretKey);
93
- if (result.ok) {
94
- secrets.loadAppSecrets(appName);
95
- secrets.refresh();
96
- }
97
- else {
98
- dispatch({ type: 'SET_ERROR', error: result.error ?? 'Delete failed' });
99
- }
101
+ secrets.deleteSecret(appName, secretKey).then(result => {
102
+ if (result.ok) {
103
+ secrets.loadAppSecrets(appName);
104
+ secrets.refresh();
105
+ }
106
+ else {
107
+ dispatch({ type: 'SET_ERROR', error: result.error ?? 'Delete failed' });
108
+ }
109
+ });
100
110
  },
101
111
  },
102
112
  });
@@ -117,7 +127,7 @@ export function SecretsView() {
117
127
  }, [subView, selectedIndex, selectedApp, secrets, dispatch, redact]);
118
128
  useRegisterHandler(handler);
119
129
  const listHeight = Math.max(5, availableHeight - 5);
120
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, paddingX: 1, gap: 2, children: [_jsx(Text, { bold: true, children: "Vault:" }), !secrets.initialized ? (_jsx(Text, { color: colors.error, children: "Not initialized" })) : secrets.sealed ? (_jsx(Text, { color: colors.warning, bold: true, children: "SEALED" })) : (_jsx(Text, { color: colors.success, bold: true, children: "UNSEALED" })), _jsxs(Text, { color: colors.muted, children: [secrets.apps.length, " apps | ", secrets.apps.reduce((sum, a) => sum + a.keyCount, 0), " keys"] })] }), secrets.error && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: colors.error, children: secrets.error }) })), subView === 'app-list' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Apps with secrets:" }), _jsx(ScrollableList, { items: secrets.apps, selectedIndex: Math.min(selectedIndex, secrets.apps.length - 1), maxVisible: listHeight, emptyText: " No secrets managed", renderItem: (app, selected) => (_jsxs(Box, { children: [_jsx(Text, { color: colors.primary, children: selected ? '> ' : ' ' }), _jsx(Text, { bold: selected, color: selected ? colors.primary : colors.text, children: redact(app.app).padEnd(24) }), _jsx(Text, { color: colors.muted, children: app.type.padEnd(14) }), _jsxs(Text, { children: [String(app.keyCount).padEnd(8), " keys"] })] })) })] })) : (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, color: colors.primary, children: redact(selectedApp ?? '') }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsx(ScrollableList, { items: secrets.secrets, selectedIndex: Math.min(selectedIndex, secrets.secrets.length - 1), maxVisible: listHeight, emptyText: " No secrets found", renderItem: (secret, selected) => {
130
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, paddingX: 1, gap: 2, children: [_jsx(Text, { bold: true, children: "Vault:" }), !secrets.initialized ? (_jsx(Text, { color: colors.error, children: "Not initialized" })) : secrets.sealed ? (_jsx(Text, { color: colors.warning, bold: true, children: "SEALED" })) : (_jsx(Text, { color: colors.success, bold: true, children: "UNSEALED" })), _jsxs(Text, { color: colors.muted, children: [secrets.apps.length, " apps | ", secrets.apps.reduce((sum, a) => sum + a.keyCount, 0), " keys"] })] }), secrets.error && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: colors.error, children: secrets.error }) })), subView === 'app-list' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Apps with secrets:" }), _jsx(ScrollableList, { items: appItems, selectedIndex: Math.min(selectedIndex, appItems.length - 1), maxVisible: listHeight, emptyText: " No secrets managed", renderItem: (app, selected) => (_jsxs(Box, { children: [_jsx(Text, { color: colors.primary, children: selected ? '> ' : ' ' }), _jsx(Text, { bold: selected, color: selected ? colors.primary : colors.text, children: app.displayApp.padEnd(24) }), _jsx(Text, { color: colors.muted, children: app.type.padEnd(14) }), _jsxs(Text, { children: [String(app.keyCount).padEnd(8), " keys"] })] })) })] })) : (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, color: colors.primary, children: redact(selectedApp ?? '') }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsx(ScrollableList, { items: secrets.secrets, selectedIndex: Math.min(selectedIndex, secrets.secrets.length - 1), maxVisible: listHeight, emptyText: " No secrets found", renderItem: (secret, selected) => {
121
131
  const revealed = secrets.revealedValues[secret.key];
122
132
  return (_jsxs(Box, { children: [_jsx(Text, { color: colors.primary, children: selected ? '> ' : ' ' }), _jsx(Text, { bold: selected, color: selected ? colors.primary : colors.text, children: secret.key.padEnd(30) }), _jsx(Text, { color: revealed ? colors.warning : colors.muted, children: revealed ?? secret.maskedValue })] }));
123
133
  } }) })] }))] }));
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@matthesketh/fleet",
3
- "version": "1.8.1",
3
+ "version": "1.11.1",
4
4
  "description": "Docker production management CLI + MCP server for Claude Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
- "fleet": "dist/index.js"
8
+ "fleet": "dist/index.js",
9
+ "fleet-agent": "dist/bin/fleet-agent.js"
9
10
  },
10
11
  "files": [
11
12
  "dist/",
@@ -15,9 +16,10 @@
15
16
  "README.md"
16
17
  ],
17
18
  "scripts": {
18
- "build": "tsc && tsc-alias",
19
+ "build": "tsc && tsc-alias --resolve-full-paths",
19
20
  "dev": "tsx src/index.ts",
20
21
  "test": "vitest run",
22
+ "changelog": "node scripts/gen-changelog.mjs > CHANGELOG.md",
21
23
  "prepublishOnly": "npm run build"
22
24
  },
23
25
  "keywords": [
@@ -68,7 +70,7 @@
68
70
  "@matthesketh/ink-task-list": "0.1.0",
69
71
  "@matthesketh/ink-timeline": "0.1.0",
70
72
  "@matthesketh/ink-toast": "^0.1.0",
71
- "@matthesketh/ink-viewport": "^0.1.0",
73
+ "@matthesketh/ink-viewport": "^0.1.1",
72
74
  "@modelcontextprotocol/sdk": "1.29.0",
73
75
  "better-sqlite3": "12.9.0",
74
76
  "chokidar": "5.0.0",
@@ -77,6 +79,7 @@
77
79
  "ink-text-input": "^6.0.0",
78
80
  "proper-lockfile": "4.1.2",
79
81
  "react": "^18.3.1",
82
+ "yaml": "2.8.4",
80
83
  "zod": "^3.24.0"
81
84
  },
82
85
  "devDependencies": {
@@ -90,4 +93,4 @@
90
93
  "typescript": "5.6.3",
91
94
  "vitest": "4.0.18"
92
95
  }
93
- }
96
+ }