@memnexus-ai/mx-agent-cli 0.1.208 → 0.1.210
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/dist/__tests__/claude-sync.test.js +77 -5
- package/dist/__tests__/claude-sync.test.js.map +1 -1
- package/dist/__tests__/config-generation-gate.test.js +18 -9
- package/dist/__tests__/config-generation-gate.test.js.map +1 -1
- package/dist/__tests__/generate-claude.test.js +90 -6
- package/dist/__tests__/generate-claude.test.js.map +1 -1
- package/dist/__tests__/security-posture.test.d.ts +8 -0
- package/dist/__tests__/security-posture.test.d.ts.map +1 -0
- package/dist/__tests__/security-posture.test.js +82 -0
- package/dist/__tests__/security-posture.test.js.map +1 -0
- package/dist/__tests__/start-report-generation-capture.test.d.ts +17 -0
- package/dist/__tests__/start-report-generation-capture.test.d.ts.map +1 -0
- package/dist/__tests__/start-report-generation-capture.test.js +127 -0
- package/dist/__tests__/start-report-generation-capture.test.js.map +1 -0
- package/dist/__tests__/startup-health-render.test.d.ts +11 -0
- package/dist/__tests__/startup-health-render.test.d.ts.map +1 -0
- package/dist/__tests__/startup-health-render.test.js +60 -0
- package/dist/__tests__/startup-health-render.test.js.map +1 -0
- package/dist/__tests__/startup-report.test.js +34 -1
- package/dist/__tests__/startup-report.test.js.map +1 -1
- package/dist/__tests__/startup-shipper.test.d.ts +13 -0
- package/dist/__tests__/startup-shipper.test.d.ts.map +1 -0
- package/dist/__tests__/startup-shipper.test.js +149 -0
- package/dist/__tests__/startup-shipper.test.js.map +1 -0
- package/dist/agent-config/settings.json +3 -3
- package/dist/commands/dashboard.d.ts +21 -0
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +72 -1
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +16 -0
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +17 -0
- package/dist/commands/sync.js.map +1 -1
- package/dist/lib/claude.d.ts.map +1 -1
- package/dist/lib/claude.js +31 -6
- package/dist/lib/claude.js.map +1 -1
- package/dist/lib/security-posture.d.ts +69 -0
- package/dist/lib/security-posture.d.ts.map +1 -0
- package/dist/lib/security-posture.js +102 -0
- package/dist/lib/security-posture.js.map +1 -0
- package/dist/lib/startup-report.d.ts +19 -3
- package/dist/lib/startup-report.d.ts.map +1 -1
- package/dist/lib/startup-report.js +66 -8
- package/dist/lib/startup-report.js.map +1 -1
- package/dist/lib/startup-shipper.d.ts +55 -0
- package/dist/lib/startup-shipper.d.ts.map +1 -0
- package/dist/lib/startup-shipper.js +177 -0
- package/dist/lib/startup-shipper.js.map +1 -0
- package/package.json +1 -1
- package/scripts/generate-claude.mjs +45 -1
- package/dist/__tests__/config-mirror-integrity.test.d.ts +0 -32
- package/dist/__tests__/config-mirror-integrity.test.d.ts.map +0 -1
- package/dist/__tests__/config-mirror-integrity.test.js +0 -248
- package/dist/__tests__/config-mirror-integrity.test.js.map +0 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the shared self-protection posture contract (security-posture.ts,
|
|
3
|
+
* #4304 Phase 4). This is the single source of truth reused by the CI generation
|
|
4
|
+
* gate and by syncClaudeConfig's no-config hard-stop, so it is worth direct
|
|
5
|
+
* coverage independent of either consumer.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=security-posture.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-posture.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/security-posture.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the shared self-protection posture contract (security-posture.ts,
|
|
3
|
+
* #4304 Phase 4). This is the single source of truth reused by the CI generation
|
|
4
|
+
* gate and by syncClaudeConfig's no-config hard-stop, so it is worth direct
|
|
5
|
+
* coverage independent of either consumer.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect } from 'vitest';
|
|
8
|
+
import { REQUIRED_SOURCE_DENIES, SELF_PROTECTED_PATHS, unmatchedFilePathDenies, pathIsWriteProtected, assessSettingsPosture, } from '../lib/security-posture.js';
|
|
9
|
+
describe('REQUIRED_SOURCE_DENIES', () => {
|
|
10
|
+
it('is the Edit-form of every SELF_PROTECTED_PATHS entry (settings, hooks, staging, prev)', () => {
|
|
11
|
+
expect(REQUIRED_SOURCE_DENIES).toEqual([
|
|
12
|
+
'Edit(.claude/settings.json)',
|
|
13
|
+
'Edit(.claude/hooks/**)',
|
|
14
|
+
'Edit(.claude.staging-*/**)',
|
|
15
|
+
'Edit(.claude.prev-*/**)',
|
|
16
|
+
]);
|
|
17
|
+
expect(REQUIRED_SOURCE_DENIES).toHaveLength(SELF_PROTECTED_PATHS.length);
|
|
18
|
+
});
|
|
19
|
+
it('contains no unmatched file-path form (Edit-only, canary syntax fix)', () => {
|
|
20
|
+
expect(unmatchedFilePathDenies(REQUIRED_SOURCE_DENIES)).toEqual([]);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe('unmatchedFilePathDenies', () => {
|
|
24
|
+
it('flags Write(path)/NotebookEdit(path)/Glob(path) but not Edit/Read/Bash or bare tool names', () => {
|
|
25
|
+
const deny = [
|
|
26
|
+
'Write(.claude/settings.json)', // flagged
|
|
27
|
+
'NotebookEdit(nb/**)', // flagged
|
|
28
|
+
'Glob(src/**)', // flagged
|
|
29
|
+
'Edit(.claude/hooks/**)', // ok
|
|
30
|
+
'Read(/secrets/**)', // ok
|
|
31
|
+
'Bash(rm -rf /)', // ok (not a file-path tool form)
|
|
32
|
+
'Write', // ok — bare tool name, matches everywhere, no warning
|
|
33
|
+
];
|
|
34
|
+
expect(unmatchedFilePathDenies(deny)).toEqual([
|
|
35
|
+
'Write(.claude/settings.json)',
|
|
36
|
+
'NotebookEdit(nb/**)',
|
|
37
|
+
'Glob(src/**)',
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('pathIsWriteProtected', () => {
|
|
42
|
+
it('accepts either the Edit form or the legacy Write form', () => {
|
|
43
|
+
expect(pathIsWriteProtected(['Edit(.claude/settings.json)'], '.claude/settings.json')).toBe(true);
|
|
44
|
+
expect(pathIsWriteProtected(['Write(.claude/settings.json)'], '.claude/settings.json')).toBe(true);
|
|
45
|
+
expect(pathIsWriteProtected(['Edit(other)'], '.claude/settings.json')).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe('assessSettingsPosture', () => {
|
|
49
|
+
const ok = JSON.stringify({
|
|
50
|
+
permissions: { deny: ['Edit(.claude/settings.json)', 'Edit(.claude/hooks/**)'] },
|
|
51
|
+
});
|
|
52
|
+
it('returns null for a valid posture', () => {
|
|
53
|
+
expect(assessSettingsPosture(ok)).toBeNull();
|
|
54
|
+
});
|
|
55
|
+
it('accepts the legacy Write(...) form (lenient on form)', () => {
|
|
56
|
+
const legacy = JSON.stringify({
|
|
57
|
+
permissions: { deny: ['Write(.claude/settings.json)', 'Write(.claude/hooks/**)'] },
|
|
58
|
+
});
|
|
59
|
+
expect(assessSettingsPosture(legacy)).toBeNull();
|
|
60
|
+
});
|
|
61
|
+
it('rejects a zero-byte / non-JSON file', () => {
|
|
62
|
+
expect(assessSettingsPosture('')).toMatch(/not valid JSON/);
|
|
63
|
+
expect(assessSettingsPosture('{ not json')).toMatch(/not valid JSON/);
|
|
64
|
+
});
|
|
65
|
+
it('rejects an empty or missing permissions.deny', () => {
|
|
66
|
+
expect(assessSettingsPosture('{"permissions":{"deny":[]}}')).toMatch(/deny is missing or empty/);
|
|
67
|
+
expect(assessSettingsPosture('{"permissions":{"allow":["Bash"]}}')).toMatch(/deny is missing or empty/);
|
|
68
|
+
expect(assessSettingsPosture('{}')).toMatch(/deny is missing or empty/);
|
|
69
|
+
});
|
|
70
|
+
it('rejects a deny list missing a required self-protection path', () => {
|
|
71
|
+
const halfProtected = JSON.stringify({
|
|
72
|
+
permissions: { deny: ['Edit(.claude/settings.json)'] }, // hooks/** missing
|
|
73
|
+
});
|
|
74
|
+
expect(assessSettingsPosture(halfProtected)).toMatch(/\.claude\/hooks/);
|
|
75
|
+
});
|
|
76
|
+
it('never throws on garbage shapes', () => {
|
|
77
|
+
expect(() => assessSettingsPosture('null')).not.toThrow();
|
|
78
|
+
expect(() => assessSettingsPosture('[]')).not.toThrow();
|
|
79
|
+
expect(() => assessSettingsPosture('42')).not.toThrow();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=security-posture.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-posture.test.js","sourceRoot":"","sources":["../../src/__tests__/security-posture.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test (#4304 Phase 4, KI item 3d): the startup-report (v2.58, #4350)
|
|
3
|
+
* captures the config-generation lines of the REAL start path.
|
|
4
|
+
*
|
|
5
|
+
* The v2.58 startup report tees/records everything the start path prints. This
|
|
6
|
+
* test drives the actual `syncClaudeConfig` — the same function `mx-agent start`
|
|
7
|
+
* calls at §5 — against a REAL git origin so the REAL generator subprocess
|
|
8
|
+
* (`node scripts/generate-claude.mjs --from-git origin/main`) materializes
|
|
9
|
+
* `.claude/` from source, then asserts the durable JSONL records the generation
|
|
10
|
+
* lines. No production code changed for this deliverable: the confirmation is that
|
|
11
|
+
* the existing capture already records these lines end-to-end.
|
|
12
|
+
*
|
|
13
|
+
* This is the committed equivalent of the built-binary smoke: temp HOME, temp
|
|
14
|
+
* worktree clone, real generator, real durable log.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=start-report-generation-capture.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start-report-generation-capture.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/start-report-generation-capture.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test (#4304 Phase 4, KI item 3d): the startup-report (v2.58, #4350)
|
|
3
|
+
* captures the config-generation lines of the REAL start path.
|
|
4
|
+
*
|
|
5
|
+
* The v2.58 startup report tees/records everything the start path prints. This
|
|
6
|
+
* test drives the actual `syncClaudeConfig` — the same function `mx-agent start`
|
|
7
|
+
* calls at §5 — against a REAL git origin so the REAL generator subprocess
|
|
8
|
+
* (`node scripts/generate-claude.mjs --from-git origin/main`) materializes
|
|
9
|
+
* `.claude/` from source, then asserts the durable JSONL records the generation
|
|
10
|
+
* lines. No production code changed for this deliverable: the confirmation is that
|
|
11
|
+
* the existing capture already records these lines end-to-end.
|
|
12
|
+
*
|
|
13
|
+
* This is the committed equivalent of the built-binary smoke: temp HOME, temp
|
|
14
|
+
* worktree clone, real generator, real durable log.
|
|
15
|
+
*/
|
|
16
|
+
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
|
17
|
+
import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync, existsSync } from 'fs';
|
|
18
|
+
import { execFileSync } from 'child_process';
|
|
19
|
+
import { tmpdir } from 'os';
|
|
20
|
+
import { dirname, join } from 'path';
|
|
21
|
+
import { fileURLToPath } from 'url';
|
|
22
|
+
import { syncClaudeConfig } from '../lib/claude.js';
|
|
23
|
+
import { startupReport } from '../lib/startup-report.js';
|
|
24
|
+
const CONFIG_SOURCE = 'mx-agent-system/agent-config';
|
|
25
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
/** Locate the repo root that holds the real agent-config source. */
|
|
27
|
+
function findRepoRoot() {
|
|
28
|
+
let dir = HERE;
|
|
29
|
+
for (let i = 0; i < 20; i++) {
|
|
30
|
+
if (existsSync(join(dir, CONFIG_SOURCE, 'settings.json')))
|
|
31
|
+
return dir;
|
|
32
|
+
const parent = dirname(dir);
|
|
33
|
+
if (parent === dir)
|
|
34
|
+
break;
|
|
35
|
+
dir = parent;
|
|
36
|
+
}
|
|
37
|
+
throw new Error('could not locate repo root from ' + HERE);
|
|
38
|
+
}
|
|
39
|
+
const REPO_ROOT = findRepoRoot();
|
|
40
|
+
let tmp;
|
|
41
|
+
let originDir;
|
|
42
|
+
let wt;
|
|
43
|
+
let home;
|
|
44
|
+
const OLD_HOME = process.env.HOME;
|
|
45
|
+
function git(cwd, ...args) {
|
|
46
|
+
execFileSync('git', args, { cwd, stdio: 'pipe' });
|
|
47
|
+
}
|
|
48
|
+
beforeAll(() => {
|
|
49
|
+
tmp = mkdtempSync(join(tmpdir(), 'mx-gencap-'));
|
|
50
|
+
originDir = join(tmp, 'origin.git');
|
|
51
|
+
wt = join(tmp, 'wt');
|
|
52
|
+
// Bare origin.
|
|
53
|
+
mkdirSync(originDir, { recursive: true });
|
|
54
|
+
git(originDir, 'init', '--bare', '-q');
|
|
55
|
+
// Working clone with the REAL agent-config source committed at CONFIG_SOURCE, so
|
|
56
|
+
// the generator has a faithful, generatable tree to archive from origin/main.
|
|
57
|
+
mkdirSync(wt, { recursive: true });
|
|
58
|
+
git(wt, 'init', '-q');
|
|
59
|
+
git(wt, 'config', 'user.email', 'test@example.com');
|
|
60
|
+
git(wt, 'config', 'user.name', 'Test');
|
|
61
|
+
git(wt, 'config', 'commit.gpgsign', 'false');
|
|
62
|
+
const dstSrc = join(wt, CONFIG_SOURCE);
|
|
63
|
+
mkdirSync(dirname(dstSrc), { recursive: true });
|
|
64
|
+
cpSync(join(REPO_ROOT, CONFIG_SOURCE), dstSrc, { recursive: true });
|
|
65
|
+
git(wt, 'add', '-A');
|
|
66
|
+
git(wt, 'commit', '-q', '-m', 'seed agent-config');
|
|
67
|
+
git(wt, 'branch', '-M', 'main');
|
|
68
|
+
git(wt, 'remote', 'add', 'origin', originDir);
|
|
69
|
+
git(wt, 'push', '-q', '-u', 'origin', 'main');
|
|
70
|
+
});
|
|
71
|
+
afterAll(() => {
|
|
72
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
73
|
+
if (OLD_HOME === undefined)
|
|
74
|
+
delete process.env.HOME;
|
|
75
|
+
else
|
|
76
|
+
process.env.HOME = OLD_HOME;
|
|
77
|
+
});
|
|
78
|
+
beforeEach(() => {
|
|
79
|
+
home = mkdtempSync(join(tmpdir(), 'mx-gencap-home-'));
|
|
80
|
+
process.env.HOME = home;
|
|
81
|
+
startupReport._reset();
|
|
82
|
+
});
|
|
83
|
+
describe('startup report captures config-generation lines (real generator, real origin)', () => {
|
|
84
|
+
it('generates .claude/ from source and records the generation lines in the durable JSONL', () => {
|
|
85
|
+
startupReport.setContext({ project: 'proj', team: 'genteam', worktree: 'genwt' });
|
|
86
|
+
startupReport.installConsoleCapture();
|
|
87
|
+
// The real start-path config step: fetch origin, then run the generator
|
|
88
|
+
// subprocess against origin/main. No mocks — this spawns node on the actual
|
|
89
|
+
// scripts/generate-claude.mjs.
|
|
90
|
+
syncClaudeConfig(wt, { baseBranch: 'main', configSource: CONFIG_SOURCE });
|
|
91
|
+
startupReport.finalize('ok');
|
|
92
|
+
// The generator actually materialized .claude/ from source.
|
|
93
|
+
expect(existsSync(join(wt, '.claude', 'settings.json')), '.claude/ was not generated').toBe(true);
|
|
94
|
+
// The durable JSONL captured the generation lines.
|
|
95
|
+
const file = join(home, '.mx-agent', 'logs', 'startup', 'genwt.jsonl');
|
|
96
|
+
const lines = readFileSync(file, 'utf-8').trim().split('\n');
|
|
97
|
+
expect(lines).toHaveLength(1);
|
|
98
|
+
const report = JSON.parse(lines[0]);
|
|
99
|
+
expect(report.outcome).toBe('ok');
|
|
100
|
+
const messages = report.entries.map((e) => e.message).join('\n');
|
|
101
|
+
// syncClaudeConfig's generation lines (the start path's config step).
|
|
102
|
+
expect(messages).toContain('Syncing agent config');
|
|
103
|
+
expect(messages).toContain('Agent config generated from');
|
|
104
|
+
});
|
|
105
|
+
it('records a generator FAILURE warning (incl. generator stderr) when a valid backstop exists', () => {
|
|
106
|
+
// Prove generator WARNINGS also reach the JSONL: force generation to fail by
|
|
107
|
+
// pointing at a missing branch, with a valid existing .claude/ backstop so the
|
|
108
|
+
// path warn-and-continues (no hard stop) and the warning — which carries the
|
|
109
|
+
// generator's stderr — is recorded.
|
|
110
|
+
const claudeDir = join(wt, '.claude');
|
|
111
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
112
|
+
writeFileSync(join(claudeDir, 'settings.json'), JSON.stringify({
|
|
113
|
+
permissions: { deny: ['Edit(.claude/settings.json)', 'Edit(.claude/hooks/**)'] },
|
|
114
|
+
}) + '\n');
|
|
115
|
+
startupReport.setContext({ project: 'proj', team: 'genteam', worktree: 'genwt2' });
|
|
116
|
+
startupReport.installConsoleCapture();
|
|
117
|
+
// baseBranch that does not exist in origin → git fetch fails → warn-and-continue
|
|
118
|
+
// on the valid backstop (hard stop only fires without a usable backstop).
|
|
119
|
+
syncClaudeConfig(wt, { baseBranch: 'no-such-branch', configSource: CONFIG_SOURCE });
|
|
120
|
+
startupReport.finalize('ok');
|
|
121
|
+
const file = join(home, '.mx-agent', 'logs', 'startup', 'genwt2.jsonl');
|
|
122
|
+
const report = JSON.parse(readFileSync(file, 'utf-8').trim());
|
|
123
|
+
const warnings = report.entries.filter((e) => e.level === 'warning');
|
|
124
|
+
expect(warnings.length).toBeGreaterThan(0);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
//# sourceMappingURL=start-report-generation-capture.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start-report-generation-capture.test.js","sourceRoot":"","sources":["../../src/__tests__/start-report-generation-capture.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CWE-150 render-layer test (#4350 security review).
|
|
3
|
+
*
|
|
4
|
+
* renderStartupHealth() prints fleet-supplied fields (team, latest_outcome,
|
|
5
|
+
* warning messages) to the operator's terminal. Any worktree can POST crafted
|
|
6
|
+
* control sequences straight to the API with the shared token, so the render
|
|
7
|
+
* layer must strip them before printing. This asserts the rendered output
|
|
8
|
+
* contains none of the injected sequences.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=startup-health-render.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startup-health-render.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/startup-health-render.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CWE-150 render-layer test (#4350 security review).
|
|
3
|
+
*
|
|
4
|
+
* renderStartupHealth() prints fleet-supplied fields (team, latest_outcome,
|
|
5
|
+
* warning messages) to the operator's terminal. Any worktree can POST crafted
|
|
6
|
+
* control sequences straight to the API with the shared token, so the render
|
|
7
|
+
* layer must strip them before printing. This asserts the rendered output
|
|
8
|
+
* contains none of the injected sequences.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
11
|
+
import chalk from 'chalk';
|
|
12
|
+
import { renderStartupHealth } from '../commands/dashboard.js';
|
|
13
|
+
const ESC = String.fromCharCode(27); // \x1b
|
|
14
|
+
const BEL = String.fromCharCode(7); // \x07
|
|
15
|
+
const SCREEN_CLEAR = ESC + '[2J';
|
|
16
|
+
const OSC_TITLE = ESC + ']0;OWNED' + BEL;
|
|
17
|
+
let logged;
|
|
18
|
+
const origLevel = chalk.level;
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
// Disable chalk styling so the only escape sequences that could appear in the
|
|
21
|
+
// output are ones that leaked through from the (hostile) input fields.
|
|
22
|
+
chalk.level = 0;
|
|
23
|
+
logged = '';
|
|
24
|
+
vi.spyOn(console, 'log').mockImplementation((...args) => {
|
|
25
|
+
logged += args.map((a) => String(a)).join(' ') + '\n';
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
vi.restoreAllMocks();
|
|
30
|
+
chalk.level = origLevel;
|
|
31
|
+
});
|
|
32
|
+
describe('renderStartupHealth — control-sequence stripping', () => {
|
|
33
|
+
it('renders team, outcome, and warning message with the injected sequences absent', () => {
|
|
34
|
+
renderStartupHealth({
|
|
35
|
+
window_days: 7,
|
|
36
|
+
generated_at: new Date().toISOString(),
|
|
37
|
+
teams: [
|
|
38
|
+
{
|
|
39
|
+
team: `evil${SCREEN_CLEAR}team`,
|
|
40
|
+
latest_outcome: `ok${OSC_TITLE}`,
|
|
41
|
+
latest_started_at: new Date().toISOString(),
|
|
42
|
+
latest_warning_count: 1,
|
|
43
|
+
latest_error_count: 0,
|
|
44
|
+
report_count: 1,
|
|
45
|
+
total_warning_count: 1,
|
|
46
|
+
total_error_count: 0,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
top_warnings: [{ message: `boom${SCREEN_CLEAR}${OSC_TITLE}bar`, count: 3 }],
|
|
50
|
+
});
|
|
51
|
+
// No ESC byte, no screen-clear, no OSC payload anywhere in the printed output.
|
|
52
|
+
expect(logged.includes(ESC)).toBe(false);
|
|
53
|
+
expect(logged.includes('[2J')).toBe(false);
|
|
54
|
+
expect(logged.includes('OWNED')).toBe(false);
|
|
55
|
+
// The benign parts of each field still render.
|
|
56
|
+
expect(logged).toContain('evilteam');
|
|
57
|
+
expect(logged).toContain('boombar');
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=startup-health-render.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startup-health-render.test.js","sourceRoot":"","sources":["../../src/__tests__/startup-health-render.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO;AAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO;AAC3C,MAAM,YAAY,GAAG,GAAG,GAAG,KAAK,CAAC;AACjC,MAAM,SAAS,GAAG,GAAG,GAAG,UAAU,GAAG,GAAG,CAAC;AAEzC,IAAI,MAAc,CAAC;AACnB,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;AAE9B,UAAU,CAAC,GAAG,EAAE;IACd,8EAA8E;IAC9E,uEAAuE;IACvE,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IAChB,MAAM,GAAG,EAAE,CAAC;IACZ,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,CAAC,GAAG,IAAe,EAAE,EAAE;QACjE,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,EAAE,CAAC,eAAe,EAAE,CAAC;IACrB,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kDAAkD,EAAE,GAAG,EAAE;IAChE,EAAE,CAAC,+EAA+E,EAAE,GAAG,EAAE;QACvF,mBAAmB,CAAC;YAClB,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACtC,KAAK,EAAE;gBACL;oBACE,IAAI,EAAE,OAAO,YAAY,MAAM;oBAC/B,cAAc,EAAE,KAAK,SAAS,EAAE;oBAChC,iBAAiB,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBAC3C,oBAAoB,EAAE,CAAC;oBACvB,kBAAkB,EAAE,CAAC;oBACrB,YAAY,EAAE,CAAC;oBACf,mBAAmB,EAAE,CAAC;oBACtB,iBAAiB,EAAE,CAAC;iBACrB;aACF;YACD,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,YAAY,GAAG,SAAS,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;SAC5E,CAAC,CAAC;QAEH,+EAA+E;QAC/E,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE7C,+CAA+C;QAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - the console-capture tee records every print without altering output
|
|
11
11
|
*/
|
|
12
12
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
13
|
-
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, existsSync, rmSync, chmodSync } from 'fs';
|
|
13
|
+
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, readdirSync, existsSync, rmSync, chmodSync } from 'fs';
|
|
14
14
|
import { tmpdir } from 'os';
|
|
15
15
|
import { join } from 'path';
|
|
16
16
|
import { startupReport, inferLevel, stripAnsi, redactUrlCredentials } from '../lib/startup-report.js';
|
|
@@ -126,6 +126,39 @@ describe('record + finalize', () => {
|
|
|
126
126
|
expect(raw).toHaveLength(1);
|
|
127
127
|
expect(JSON.parse(raw[0]).outcome).toBe('ok');
|
|
128
128
|
});
|
|
129
|
+
it('persists messages with terminal control sequences stripped (CWE-150)', () => {
|
|
130
|
+
const ESC = String.fromCharCode(27);
|
|
131
|
+
const BEL = String.fromCharCode(7);
|
|
132
|
+
startupReport.setContext({ worktree: 'ctrl-wt' });
|
|
133
|
+
startupReport.record('warning', `boom${ESC}[2J${ESC}]0;OWNED${BEL}bar`);
|
|
134
|
+
startupReport.finalize('ok');
|
|
135
|
+
const raw = readFileSync(logPath('ctrl-wt'), 'utf-8').trim();
|
|
136
|
+
// The whole persisted line must be free of ESC, screen-clear, and OSC payload.
|
|
137
|
+
expect(raw.includes(ESC)).toBe(false);
|
|
138
|
+
expect(raw.includes('[2J')).toBe(false);
|
|
139
|
+
expect(raw.includes('OWNED')).toBe(false);
|
|
140
|
+
const report = JSON.parse(raw);
|
|
141
|
+
expect(report.entries[0].message).toBe('boombar');
|
|
142
|
+
});
|
|
143
|
+
it('spools a copy of the report for central shipping (#4350 Phase 2)', () => {
|
|
144
|
+
startupReport.setContext({ worktree: 'ship-wt', team: 'shipteam' });
|
|
145
|
+
startupReport.record('warning', 'w');
|
|
146
|
+
startupReport.finalize('ok');
|
|
147
|
+
const spool = join(home, '.mx-agent', 'logs', 'startup', 'spool');
|
|
148
|
+
const files = readdirSync(spool).filter((f) => f.endsWith('.json'));
|
|
149
|
+
expect(files).toHaveLength(1);
|
|
150
|
+
const spooled = JSON.parse(readFileSync(join(spool, files[0]), 'utf-8'));
|
|
151
|
+
expect(spooled.worktree).toBe('ship-wt');
|
|
152
|
+
expect(spooled.outcome).toBe('ok');
|
|
153
|
+
});
|
|
154
|
+
it('fires the ship hook once on finalize (fire-and-forget)', () => {
|
|
155
|
+
const hook = vi.fn();
|
|
156
|
+
startupReport.setShipHook(hook);
|
|
157
|
+
startupReport.setContext({ worktree: 'hook-wt' });
|
|
158
|
+
startupReport.finalize('ok');
|
|
159
|
+
startupReport.finalize('error'); // idempotent — hook must not fire twice
|
|
160
|
+
expect(hook).toHaveBeenCalledTimes(1);
|
|
161
|
+
});
|
|
129
162
|
it('falls back to team, then "unknown", for the file name', () => {
|
|
130
163
|
startupReport.setContext({ team: 'teamx' }); // no worktree
|
|
131
164
|
startupReport.record('info', 'x');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"startup-report.test.js","sourceRoot":"","sources":["../../src/__tests__/startup-report.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"startup-report.test.js","sourceRoot":"","sources":["../../src/__tests__/startup-report.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the central StartupReport shipper (platform v2.58 Phase 2, #4350).
|
|
3
|
+
*
|
|
4
|
+
* Covers the spool lifecycle and never-throw discipline:
|
|
5
|
+
* - spoolReport writes one file; flush POSTs and deletes on 2xx
|
|
6
|
+
* - POST failure (non-2xx / network) leaves the file spooled
|
|
7
|
+
* - no token → flush skips the POST and leaves everything spooled
|
|
8
|
+
* - 50-file cap drops the oldest beyond 50
|
|
9
|
+
* - 14-day age drop happens at spool-write time
|
|
10
|
+
* - spoolReport never throws under a read-only spool dir
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=startup-shipper.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startup-shipper.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/startup-shipper.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the central StartupReport shipper (platform v2.58 Phase 2, #4350).
|
|
3
|
+
*
|
|
4
|
+
* Covers the spool lifecycle and never-throw discipline:
|
|
5
|
+
* - spoolReport writes one file; flush POSTs and deletes on 2xx
|
|
6
|
+
* - POST failure (non-2xx / network) leaves the file spooled
|
|
7
|
+
* - no token → flush skips the POST and leaves everything spooled
|
|
8
|
+
* - 50-file cap drops the oldest beyond 50
|
|
9
|
+
* - 14-day age drop happens at spool-write time
|
|
10
|
+
* - spoolReport never throws under a read-only spool dir
|
|
11
|
+
*/
|
|
12
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
13
|
+
import { mkdtempSync, mkdirSync, writeFileSync, readdirSync, rmSync, chmodSync, utimesSync } from 'fs';
|
|
14
|
+
import { tmpdir } from 'os';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
import { spoolReport, flushSpool, spoolDir } from '../lib/startup-shipper.js';
|
|
17
|
+
let home;
|
|
18
|
+
const OLD_HOME = process.env.HOME;
|
|
19
|
+
function report(over = {}) {
|
|
20
|
+
return JSON.stringify({
|
|
21
|
+
schema_version: 1,
|
|
22
|
+
project: 'memnexus',
|
|
23
|
+
team: 'platform',
|
|
24
|
+
worktree: 'platform-wt',
|
|
25
|
+
machine: 'host-a',
|
|
26
|
+
cli_version: '2.58.0',
|
|
27
|
+
outcome: 'ok',
|
|
28
|
+
started_at: new Date().toISOString(),
|
|
29
|
+
entries: [{ ts: '', level: 'warning', message: 'w' }],
|
|
30
|
+
...over,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function spoolFiles() {
|
|
34
|
+
try {
|
|
35
|
+
return readdirSync(spoolDir()).filter((f) => f.endsWith('.json'));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
home = mkdtempSync(join(tmpdir(), 'mx-shipper-home-'));
|
|
43
|
+
process.env.HOME = home;
|
|
44
|
+
vi.unstubAllGlobals();
|
|
45
|
+
});
|
|
46
|
+
afterEach(() => {
|
|
47
|
+
vi.unstubAllGlobals();
|
|
48
|
+
// Restore perms so cleanup can remove read-only dirs created by a test.
|
|
49
|
+
try {
|
|
50
|
+
chmodSync(spoolDir(), 0o755);
|
|
51
|
+
}
|
|
52
|
+
catch { /* ignore */ }
|
|
53
|
+
rmSync(home, { recursive: true, force: true });
|
|
54
|
+
if (OLD_HOME === undefined)
|
|
55
|
+
delete process.env.HOME;
|
|
56
|
+
else
|
|
57
|
+
process.env.HOME = OLD_HOME;
|
|
58
|
+
});
|
|
59
|
+
describe('spoolReport', () => {
|
|
60
|
+
it('writes one JSON file to the spool dir', () => {
|
|
61
|
+
const p = spoolReport(report());
|
|
62
|
+
expect(p).toBeTruthy();
|
|
63
|
+
expect(spoolFiles().length).toBe(1);
|
|
64
|
+
});
|
|
65
|
+
it('never throws under a read-only spool dir (returns null)', () => {
|
|
66
|
+
mkdirSync(spoolDir(), { recursive: true });
|
|
67
|
+
chmodSync(spoolDir(), 0o500); // read+execute, no write
|
|
68
|
+
let result = 'sentinel';
|
|
69
|
+
expect(() => { result = spoolReport(report()); }).not.toThrow();
|
|
70
|
+
// On most CI the write fails and returns null; if the platform ignores the
|
|
71
|
+
// mode (e.g. running as root), it may still succeed — either is acceptable
|
|
72
|
+
// as long as it did not throw.
|
|
73
|
+
expect(result === null || typeof result === 'string').toBe(true);
|
|
74
|
+
});
|
|
75
|
+
it('drops files older than 14 days at write time', () => {
|
|
76
|
+
mkdirSync(spoolDir(), { recursive: true });
|
|
77
|
+
const stale = join(spoolDir(), 'stale.json');
|
|
78
|
+
writeFileSync(stale, report());
|
|
79
|
+
const old = Date.now() / 1000 - 15 * 24 * 60 * 60; // 15 days ago
|
|
80
|
+
utimesSync(stale, old, old);
|
|
81
|
+
spoolReport(report()); // triggers the age sweep
|
|
82
|
+
const files = spoolFiles();
|
|
83
|
+
expect(files).not.toContain('stale.json');
|
|
84
|
+
expect(files.length).toBe(1); // only the freshly-written report remains
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe('flushSpool — POST lifecycle', () => {
|
|
88
|
+
it('POSTs each spooled report and deletes it on 2xx', async () => {
|
|
89
|
+
spoolReport(report());
|
|
90
|
+
spoolReport(report({ worktree: 'wt2' }));
|
|
91
|
+
expect(spoolFiles().length).toBe(2);
|
|
92
|
+
const fetchMock = vi.fn(() => Promise.resolve(new Response(JSON.stringify({ stored: 1 }), { status: 201 })));
|
|
93
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
94
|
+
const res = await flushSpool({ apiUrl: 'http://obs.test', apiToken: 'tok' });
|
|
95
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
96
|
+
expect(res.shipped).toBe(2);
|
|
97
|
+
expect(res.remaining).toBe(0);
|
|
98
|
+
expect(spoolFiles().length).toBe(0);
|
|
99
|
+
});
|
|
100
|
+
it('leaves the file spooled when the POST is not 2xx', async () => {
|
|
101
|
+
spoolReport(report());
|
|
102
|
+
vi.stubGlobal('fetch', vi.fn(() => Promise.resolve(new Response('nope', { status: 500 }))));
|
|
103
|
+
const res = await flushSpool({ apiUrl: 'http://obs.test', apiToken: 'tok' });
|
|
104
|
+
expect(res.shipped).toBe(0);
|
|
105
|
+
expect(spoolFiles().length).toBe(1);
|
|
106
|
+
});
|
|
107
|
+
it('leaves the file spooled when the POST rejects (network error)', async () => {
|
|
108
|
+
spoolReport(report());
|
|
109
|
+
vi.stubGlobal('fetch', vi.fn(() => Promise.reject(new Error('ECONNREFUSED'))));
|
|
110
|
+
const res = await flushSpool({ apiUrl: 'http://obs.test', apiToken: 'tok' });
|
|
111
|
+
expect(res.shipped).toBe(0);
|
|
112
|
+
expect(spoolFiles().length).toBe(1);
|
|
113
|
+
});
|
|
114
|
+
it('skips the POST entirely when no token is configured', async () => {
|
|
115
|
+
spoolReport(report());
|
|
116
|
+
const fetchMock = vi.fn(() => Promise.resolve(new Response('', { status: 201 })));
|
|
117
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
118
|
+
const res = await flushSpool({ apiUrl: 'http://obs.test', apiToken: undefined });
|
|
119
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
120
|
+
expect(res.shipped).toBe(0);
|
|
121
|
+
expect(res.remaining).toBe(1);
|
|
122
|
+
expect(spoolFiles().length).toBe(1);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
describe('flushSpool — 50-file cap', () => {
|
|
126
|
+
it('drops the oldest files beyond 50 before shipping', async () => {
|
|
127
|
+
mkdirSync(spoolDir(), { recursive: true });
|
|
128
|
+
// Write 55 files with strictly increasing mtimes so "oldest" is deterministic.
|
|
129
|
+
for (let i = 0; i < 55; i++) {
|
|
130
|
+
const p = join(spoolDir(), `f${String(i).padStart(3, '0')}.json`);
|
|
131
|
+
writeFileSync(p, report({ worktree: `wt${i}` }));
|
|
132
|
+
const t = Date.now() / 1000 - (55 - i) * 60; // older files first
|
|
133
|
+
utimesSync(p, t, t);
|
|
134
|
+
}
|
|
135
|
+
expect(spoolFiles().length).toBe(55);
|
|
136
|
+
const logs = [];
|
|
137
|
+
vi.stubGlobal('fetch', vi.fn(() => Promise.resolve(new Response('', { status: 201 }))));
|
|
138
|
+
const res = await flushSpool({
|
|
139
|
+
apiUrl: 'http://obs.test',
|
|
140
|
+
apiToken: 'tok',
|
|
141
|
+
log: (m) => logs.push(m),
|
|
142
|
+
});
|
|
143
|
+
// 5 oldest dropped, 50 shipped (and deleted on 2xx) → none remain.
|
|
144
|
+
expect(res.shipped).toBe(50);
|
|
145
|
+
expect(spoolFiles().length).toBe(0);
|
|
146
|
+
expect(logs.some((m) => m.includes('exceeded 50'))).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
//# sourceMappingURL=startup-shipper.test.js.map
|