@matthesketh/fleet 1.0.0 → 1.1.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.
- package/README.md +27 -4
- package/dist/cli.js +8 -0
- package/dist/commands/deps.d.ts +1 -0
- package/dist/commands/deps.js +223 -0
- package/dist/commands/motd.d.ts +1 -0
- package/dist/commands/motd.js +10 -0
- package/dist/core/deps/actors/pr-creator.d.ts +14 -0
- package/dist/core/deps/actors/pr-creator.js +103 -0
- package/dist/core/deps/cache.d.ts +5 -0
- package/dist/core/deps/cache.js +28 -0
- package/dist/core/deps/collectors/composer.d.ts +12 -0
- package/dist/core/deps/collectors/composer.js +70 -0
- package/dist/core/deps/collectors/docker-image.d.ts +18 -0
- package/dist/core/deps/collectors/docker-image.js +132 -0
- package/dist/core/deps/collectors/docker-running.d.ts +17 -0
- package/dist/core/deps/collectors/docker-running.js +55 -0
- package/dist/core/deps/collectors/eol.d.ts +16 -0
- package/dist/core/deps/collectors/eol.js +139 -0
- package/dist/core/deps/collectors/github-pr.d.ts +8 -0
- package/dist/core/deps/collectors/github-pr.js +40 -0
- package/dist/core/deps/collectors/npm.d.ts +12 -0
- package/dist/core/deps/collectors/npm.js +63 -0
- package/dist/core/deps/collectors/pip.d.ts +15 -0
- package/dist/core/deps/collectors/pip.js +94 -0
- package/dist/core/deps/collectors/vulnerability.d.ts +9 -0
- package/dist/core/deps/collectors/vulnerability.js +102 -0
- package/dist/core/deps/config.d.ts +6 -0
- package/dist/core/deps/config.js +55 -0
- package/dist/core/deps/reporters/cli.d.ts +4 -0
- package/dist/core/deps/reporters/cli.js +123 -0
- package/dist/core/deps/reporters/motd.d.ts +3 -0
- package/dist/core/deps/reporters/motd.js +64 -0
- package/dist/core/deps/reporters/telegram.d.ts +6 -0
- package/dist/core/deps/reporters/telegram.js +106 -0
- package/dist/core/deps/scanner.d.ts +4 -0
- package/dist/core/deps/scanner.js +89 -0
- package/dist/core/deps/severity.d.ts +6 -0
- package/dist/core/deps/severity.js +45 -0
- package/dist/core/deps/types.d.ts +64 -0
- package/dist/core/deps/types.js +1 -0
- package/dist/mcp/deps-tools.d.ts +2 -0
- package/dist/mcp/deps-tools.js +81 -0
- package/dist/mcp/server.js +2 -0
- package/dist/templates/motd.d.ts +1 -0
- package/dist/templates/motd.js +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { AppEntry } from '../registry.js';
|
|
2
|
+
export type CollectorType = 'npm' | 'composer' | 'pip' | 'docker-image' | 'docker-running' | 'eol' | 'vulnerability' | 'github-pr';
|
|
3
|
+
export type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
4
|
+
export type FindingCategory = 'outdated-dep' | 'image-update' | 'eol-warning' | 'vulnerability' | 'pending-pr';
|
|
5
|
+
export interface Finding {
|
|
6
|
+
appName: string;
|
|
7
|
+
source: CollectorType;
|
|
8
|
+
severity: Severity;
|
|
9
|
+
category: FindingCategory;
|
|
10
|
+
title: string;
|
|
11
|
+
detail: string;
|
|
12
|
+
package?: string;
|
|
13
|
+
currentVersion?: string;
|
|
14
|
+
latestVersion?: string;
|
|
15
|
+
eolDate?: string;
|
|
16
|
+
cveId?: string;
|
|
17
|
+
prUrl?: string;
|
|
18
|
+
fixable: boolean;
|
|
19
|
+
updatedAt: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ScanError {
|
|
22
|
+
collector: CollectorType;
|
|
23
|
+
appName?: string;
|
|
24
|
+
message: string;
|
|
25
|
+
timestamp: string;
|
|
26
|
+
}
|
|
27
|
+
export interface IgnoreRule {
|
|
28
|
+
appName?: string;
|
|
29
|
+
package?: string;
|
|
30
|
+
source?: CollectorType;
|
|
31
|
+
reason: string;
|
|
32
|
+
until?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface DepsConfig {
|
|
35
|
+
scanIntervalHours: number;
|
|
36
|
+
concurrency: number;
|
|
37
|
+
notifications: {
|
|
38
|
+
telegram: {
|
|
39
|
+
enabled: boolean;
|
|
40
|
+
chatId: string;
|
|
41
|
+
minSeverity: Severity;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
ignore: IgnoreRule[];
|
|
45
|
+
severityOverrides: {
|
|
46
|
+
eolDaysWarning: number;
|
|
47
|
+
majorVersionBehind: Severity;
|
|
48
|
+
minorVersionBehind: Severity;
|
|
49
|
+
patchVersionBehind: Severity;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export interface DepsCache {
|
|
53
|
+
version: 1;
|
|
54
|
+
lastScan: string;
|
|
55
|
+
scanDurationMs: number;
|
|
56
|
+
findings: Finding[];
|
|
57
|
+
errors: ScanError[];
|
|
58
|
+
config: DepsConfig;
|
|
59
|
+
}
|
|
60
|
+
export interface Collector {
|
|
61
|
+
type: CollectorType;
|
|
62
|
+
detect(appPath: string): boolean;
|
|
63
|
+
collect(app: AppEntry): Promise<Finding[]>;
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { load, findApp } from '../core/registry.js';
|
|
3
|
+
import { loadConfig, saveConfig } from '../core/deps/config.js';
|
|
4
|
+
import { loadCache, saveCache } from '../core/deps/cache.js';
|
|
5
|
+
import { runScan } from '../core/deps/scanner.js';
|
|
6
|
+
import { createDepsPr } from '../core/deps/actors/pr-creator.js';
|
|
7
|
+
import { AppNotFoundError } from '../core/errors.js';
|
|
8
|
+
function text(msg) {
|
|
9
|
+
return { content: [{ type: 'text', text: msg }] };
|
|
10
|
+
}
|
|
11
|
+
export function registerDepsTools(server) {
|
|
12
|
+
server.tool('fleet_deps_status', 'Dependency health summary from cache — outdated packages, CVEs, EOL warnings, Docker image updates', async () => {
|
|
13
|
+
const cache = loadCache();
|
|
14
|
+
if (!cache)
|
|
15
|
+
return text('No scan data. Run fleet deps scan first.');
|
|
16
|
+
return text(JSON.stringify(cache, null, 2));
|
|
17
|
+
});
|
|
18
|
+
server.tool('fleet_deps_scan', 'Run a fresh dependency scan across all registered apps', async () => {
|
|
19
|
+
const reg = load();
|
|
20
|
+
const config = loadConfig();
|
|
21
|
+
const cache = await runScan(reg.apps, config);
|
|
22
|
+
saveCache(cache);
|
|
23
|
+
return text(JSON.stringify({
|
|
24
|
+
findings: cache.findings.length,
|
|
25
|
+
errors: cache.errors.length,
|
|
26
|
+
duration: cache.scanDurationMs,
|
|
27
|
+
apps: reg.apps.length,
|
|
28
|
+
}, null, 2));
|
|
29
|
+
});
|
|
30
|
+
server.tool('fleet_deps_app', 'Dependency findings for a specific app', { app: z.string().describe('App name') }, async ({ app }) => {
|
|
31
|
+
const cache = loadCache();
|
|
32
|
+
if (!cache)
|
|
33
|
+
return text('No scan data. Run fleet deps scan first.');
|
|
34
|
+
const reg = load();
|
|
35
|
+
const entry = findApp(reg, app);
|
|
36
|
+
if (!entry)
|
|
37
|
+
throw new AppNotFoundError(app);
|
|
38
|
+
const findings = cache.findings.filter(f => f.appName === entry.name);
|
|
39
|
+
return text(JSON.stringify(findings, null, 2));
|
|
40
|
+
});
|
|
41
|
+
server.tool('fleet_deps_fix', 'Create a PR with dependency updates for an app (dry-run by default)', {
|
|
42
|
+
app: z.string().describe('App name'),
|
|
43
|
+
dryRun: z.boolean().default(true).describe('Preview changes without creating PR'),
|
|
44
|
+
}, async ({ app, dryRun }) => {
|
|
45
|
+
const reg = load();
|
|
46
|
+
const entry = findApp(reg, app);
|
|
47
|
+
if (!entry)
|
|
48
|
+
throw new AppNotFoundError(app);
|
|
49
|
+
const cache = loadCache();
|
|
50
|
+
if (!cache)
|
|
51
|
+
return text('No scan data. Run fleet deps scan first.');
|
|
52
|
+
const findings = cache.findings.filter(f => f.appName === entry.name && f.fixable);
|
|
53
|
+
const result = createDepsPr(entry, findings, dryRun);
|
|
54
|
+
return text(JSON.stringify(result, null, 2));
|
|
55
|
+
});
|
|
56
|
+
server.tool('fleet_deps_ignore', 'Add an ignore rule for a dependency finding', {
|
|
57
|
+
package: z.string().describe('Package name to ignore'),
|
|
58
|
+
reason: z.string().describe('Why this is being ignored'),
|
|
59
|
+
app: z.string().optional().describe('Limit to specific app'),
|
|
60
|
+
until: z.string().optional().describe('Auto-expire date (YYYY-MM-DD)'),
|
|
61
|
+
}, async (params) => {
|
|
62
|
+
const config = loadConfig();
|
|
63
|
+
config.ignore.push({
|
|
64
|
+
package: params.package, reason: params.reason,
|
|
65
|
+
...(params.app && { appName: params.app }),
|
|
66
|
+
...(params.until && { until: params.until }),
|
|
67
|
+
});
|
|
68
|
+
saveConfig(config);
|
|
69
|
+
return text(`Ignoring ${params.package}: ${params.reason}`);
|
|
70
|
+
});
|
|
71
|
+
server.tool('fleet_deps_config', 'Get or set dependency monitoring configuration', { key: z.string().optional(), value: z.string().optional() }, async ({ key, value }) => {
|
|
72
|
+
const config = loadConfig();
|
|
73
|
+
if (!key)
|
|
74
|
+
return text(JSON.stringify(config, null, 2));
|
|
75
|
+
if (!value)
|
|
76
|
+
return text(JSON.stringify(config[key], null, 2));
|
|
77
|
+
config[key] = value === 'true' ? true : value === 'false' ? false : isNaN(Number(value)) ? value : Number(value);
|
|
78
|
+
saveConfig(config);
|
|
79
|
+
return text(`Set ${key} = ${value}`);
|
|
80
|
+
});
|
|
81
|
+
}
|
package/dist/mcp/server.js
CHANGED
|
@@ -16,6 +16,7 @@ import { unsealAll, getStatus as getSecretsStatus } from '../core/secrets-ops.js
|
|
|
16
16
|
import { validateApp, validateAll } from '../core/secrets-validate.js';
|
|
17
17
|
import { registerGitTools } from './git-tools.js';
|
|
18
18
|
import { registerSecretsTools } from './secrets-tools.js';
|
|
19
|
+
import { registerDepsTools } from './deps-tools.js';
|
|
19
20
|
function requireApp(name) {
|
|
20
21
|
const reg = load();
|
|
21
22
|
const app = findApp(reg, name);
|
|
@@ -174,6 +175,7 @@ export async function startMcpServer() {
|
|
|
174
175
|
});
|
|
175
176
|
registerGitTools(server);
|
|
176
177
|
registerSecretsTools(server);
|
|
178
|
+
registerDepsTools(server);
|
|
177
179
|
const transport = new StdioServerTransport();
|
|
178
180
|
await server.connect(transport);
|
|
179
181
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateMotdScript(): string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function generateMotdScript() {
|
|
2
|
+
return `#!/bin/bash
|
|
3
|
+
# Fleet service health check — installed by "fleet motd install"
|
|
4
|
+
# Shows service status on SSH login
|
|
5
|
+
/usr/bin/node /home/matt/fleet/dist/index.js watchdog --motd 2>/dev/null || echo " Fleet: health check failed to run"
|
|
6
|
+
`;
|
|
7
|
+
}
|