@memnexus-ai/mx-agent-cli 0.1.174 → 0.1.175
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__/coordination-provision.test.d.ts +12 -0
- package/dist/__tests__/coordination-provision.test.d.ts.map +1 -0
- package/dist/__tests__/coordination-provision.test.js +76 -0
- package/dist/__tests__/coordination-provision.test.js.map +1 -0
- package/dist/__tests__/coordination-token.test.d.ts +11 -0
- package/dist/__tests__/coordination-token.test.d.ts.map +1 -0
- package/dist/__tests__/coordination-token.test.js +166 -0
- package/dist/__tests__/coordination-token.test.js.map +1 -0
- package/dist/commands/coordination.d.ts +21 -0
- package/dist/commands/coordination.d.ts.map +1 -1
- package/dist/commands/coordination.js +74 -15
- package/dist/commands/coordination.js.map +1 -1
- package/dist/lib/coordination-token.d.ts +75 -0
- package/dist/lib/coordination-token.d.ts.map +1 -0
- package/dist/lib/coordination-token.js +168 -0
- package/dist/lib/coordination-token.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prepareClient -- token self-provisioning glue (SF-A never-crash, SF-B SF-1 arm).
|
|
3
|
+
*
|
|
4
|
+
* SF-A: a throw from resolveCoordinationToken (e.g. mkdirSync EACCES on an
|
|
5
|
+
* unwritable HOME during the config read) must degrade to the null fall-back
|
|
6
|
+
* path, never propagate out and crash `mx-agent coordination brief`.
|
|
7
|
+
* SF-B: on a successful bare self-provision, MX_COORD_EXPECT_TEAM is armed to the
|
|
8
|
+
* resolved slug so runBrief's verify-before-confirm interlock runs — matching the
|
|
9
|
+
* hook — without overwriting an explicit (hook-set) value.
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=coordination-provision.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordination-provision.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/coordination-provision.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prepareClient -- token self-provisioning glue (SF-A never-crash, SF-B SF-1 arm).
|
|
3
|
+
*
|
|
4
|
+
* SF-A: a throw from resolveCoordinationToken (e.g. mkdirSync EACCES on an
|
|
5
|
+
* unwritable HOME during the config read) must degrade to the null fall-back
|
|
6
|
+
* path, never propagate out and crash `mx-agent coordination brief`.
|
|
7
|
+
* SF-B: on a successful bare self-provision, MX_COORD_EXPECT_TEAM is armed to the
|
|
8
|
+
* resolved slug so runBrief's verify-before-confirm interlock runs — matching the
|
|
9
|
+
* hook — without overwriting an explicit (hook-set) value.
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
12
|
+
// Mock the token module so we can drive prepareClient's inputs deterministically
|
|
13
|
+
// (throw for SF-A, resolved-with-slug for SF-B) without touching az / the fs.
|
|
14
|
+
vi.mock('../lib/coordination-token.js', () => ({
|
|
15
|
+
resolveCoordinationToken: vi.fn(),
|
|
16
|
+
}));
|
|
17
|
+
import { prepareClient } from '../commands/coordination.js';
|
|
18
|
+
import { resolveCoordinationToken } from '../lib/coordination-token.js';
|
|
19
|
+
const mockResolve = resolveCoordinationToken;
|
|
20
|
+
const savedEnv = { ...process.env };
|
|
21
|
+
let stderr;
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
mockResolve.mockReset();
|
|
24
|
+
stderr = [];
|
|
25
|
+
vi.spyOn(process.stderr, 'write').mockImplementation(((c) => { stderr.push(String(c)); return true; }));
|
|
26
|
+
delete process.env.MX_COORD_SERVICE_TOKEN;
|
|
27
|
+
delete process.env.MX_COORD_SERVICE_URL;
|
|
28
|
+
delete process.env.MX_COORD_EXPECT_TEAM;
|
|
29
|
+
});
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
vi.restoreAllMocks();
|
|
32
|
+
process.env = { ...savedEnv };
|
|
33
|
+
});
|
|
34
|
+
describe('prepareClient — SF-A never-crash', () => {
|
|
35
|
+
it('returns null (fall back) and does NOT throw when token resolution throws', () => {
|
|
36
|
+
// Simulate mkdirSync EACCES surfacing out of the config read.
|
|
37
|
+
mockResolve.mockImplementation(() => { throw new Error("EACCES: permission denied, mkdir '/home/nobody/.mx-agent'"); });
|
|
38
|
+
let result;
|
|
39
|
+
expect(() => { result = prepareClient(); }).not.toThrow();
|
|
40
|
+
expect(result).toBeNull();
|
|
41
|
+
expect(stderr.join('')).toContain('could not provision a service token');
|
|
42
|
+
});
|
|
43
|
+
it('returns null (fall back) when a token cannot be provisioned (unprovisioned)', () => {
|
|
44
|
+
mockResolve.mockReturnValue({ status: 'unprovisioned', detail: 'no coordination marker in this worktree' });
|
|
45
|
+
expect(prepareClient()).toBeNull();
|
|
46
|
+
expect(stderr.join('')).toContain('could not provision a service token');
|
|
47
|
+
});
|
|
48
|
+
it('returns null and names the roster-mismatch on a not-on-roster result (fail-closed)', () => {
|
|
49
|
+
mockResolve.mockReturnValue({ status: 'not-on-roster', slug: 'not-a-team' });
|
|
50
|
+
expect(prepareClient()).toBeNull();
|
|
51
|
+
expect(stderr.join('')).toContain('"not-a-team" is not on the coordination roster');
|
|
52
|
+
});
|
|
53
|
+
it('skips provisioning entirely when a client is injected (tests / manual override)', () => {
|
|
54
|
+
const injected = { async enqueue() { return { messageId: 'x', duplicate: false }; } };
|
|
55
|
+
expect(prepareClient({ client: injected })).toBe(injected);
|
|
56
|
+
expect(mockResolve).not.toHaveBeenCalled();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe('prepareClient — SF-B arms the SF-1 interlock', () => {
|
|
60
|
+
it('sets MX_COORD_EXPECT_TEAM to the resolved slug on a bare self-provision', () => {
|
|
61
|
+
process.env.MX_COORD_SERVICE_URL = 'https://coord.example';
|
|
62
|
+
mockResolve.mockReturnValue({ status: 'resolved', token: 'kv-tok', slug: 'eval', source: 'keyvault' });
|
|
63
|
+
const client = prepareClient();
|
|
64
|
+
expect(client).not.toBeNull();
|
|
65
|
+
expect(process.env.MX_COORD_SERVICE_TOKEN).toBe('kv-tok');
|
|
66
|
+
expect(process.env.MX_COORD_EXPECT_TEAM).toBe('eval');
|
|
67
|
+
});
|
|
68
|
+
it('never overwrites an explicit (hook-set) MX_COORD_EXPECT_TEAM', () => {
|
|
69
|
+
process.env.MX_COORD_SERVICE_URL = 'https://coord.example';
|
|
70
|
+
process.env.MX_COORD_EXPECT_TEAM = 'marketing'; // hook already armed it
|
|
71
|
+
mockResolve.mockReturnValue({ status: 'resolved', token: 'kv-tok', slug: 'eval', source: 'keyvault' });
|
|
72
|
+
prepareClient();
|
|
73
|
+
expect(process.env.MX_COORD_EXPECT_TEAM).toBe('marketing');
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=coordination-provision.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordination-provision.test.js","sourceRoot":"","sources":["../../src/__tests__/coordination-provision.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* coordination-token -- self-provisioning the coordination service token.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the CLI reproduces the coordination-brief hook's isolation properties:
|
|
5
|
+
* marker-authoritative slug (MF-2), roster-gate before any az call (SF-2),
|
|
6
|
+
* slug-bound per-worktree cache (MF-1), born-0600 cache write (SF-3),
|
|
7
|
+
* fail-OPEN on infra errors, fail-CLOSED on a roster mismatch, and no token
|
|
8
|
+
* logging.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=coordination-token.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordination-token.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/coordination-token.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* coordination-token -- self-provisioning the coordination service token.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the CLI reproduces the coordination-brief hook's isolation properties:
|
|
5
|
+
* marker-authoritative slug (MF-2), roster-gate before any az call (SF-2),
|
|
6
|
+
* slug-bound per-worktree cache (MF-1), born-0600 cache write (SF-3),
|
|
7
|
+
* fail-OPEN on infra errors, fail-CLOSED on a roster mismatch, and no token
|
|
8
|
+
* logging.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
11
|
+
import { mkdtempSync, rmSync, writeFileSync, readFileSync, statSync, existsSync } from 'fs';
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
import { tmpdir } from 'os';
|
|
14
|
+
// Mock the config store so we can simulate getConfigValue throwing (mkdirSync
|
|
15
|
+
// EACCES on an unwritable HOME) for the SF-A belt-and-suspenders test. Default
|
|
16
|
+
// returns undefined (no configured token) so the other tests reach the marker path.
|
|
17
|
+
vi.mock('../lib/config.js', () => ({ getConfigValue: vi.fn(() => undefined) }));
|
|
18
|
+
import { resolveCoordinationToken, KEYVAULT_NAME } from '../lib/coordination-token.js';
|
|
19
|
+
import { getConfigValue } from '../lib/config.js';
|
|
20
|
+
const mockGetConfigValue = getConfigValue;
|
|
21
|
+
let dir;
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
dir = mkdtempSync(join(tmpdir(), 'coord-token-'));
|
|
24
|
+
mockGetConfigValue.mockReset();
|
|
25
|
+
mockGetConfigValue.mockReturnValue(undefined);
|
|
26
|
+
});
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
rmSync(dir, { recursive: true, force: true });
|
|
29
|
+
vi.restoreAllMocks();
|
|
30
|
+
});
|
|
31
|
+
/** In-memory readFileText backed by a path→contents map. */
|
|
32
|
+
function reader(files) {
|
|
33
|
+
return (p) => (p in files ? files[p] : undefined);
|
|
34
|
+
}
|
|
35
|
+
describe('resolveCoordinationToken', () => {
|
|
36
|
+
it('uses an already-set env token and never calls Key Vault', () => {
|
|
37
|
+
const fetchSecret = vi.fn();
|
|
38
|
+
const res = resolveCoordinationToken({
|
|
39
|
+
env: { MX_COORD_SERVICE_TOKEN: 'env-tok', CLAUDE_WORKTREE_PATH: dir },
|
|
40
|
+
fetchSecret,
|
|
41
|
+
});
|
|
42
|
+
expect(res.status).toBe('already-configured');
|
|
43
|
+
expect(res.token).toBe('env-tok');
|
|
44
|
+
expect(fetchSecret).not.toHaveBeenCalled();
|
|
45
|
+
});
|
|
46
|
+
it('uses the per-worktree cache when present and never calls Key Vault', () => {
|
|
47
|
+
const fetchSecret = vi.fn();
|
|
48
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
49
|
+
const cache = join(dir, '.mx-coordination-token-eval');
|
|
50
|
+
const res = resolveCoordinationToken({
|
|
51
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
52
|
+
readFileText: reader({ [marker]: 'eval\n', [cache]: 'cached-eval-tok\n' }),
|
|
53
|
+
fetchSecret,
|
|
54
|
+
});
|
|
55
|
+
expect(res.status).toBe('resolved');
|
|
56
|
+
expect(res.source).toBe('cache');
|
|
57
|
+
expect(res.token).toBe('cached-eval-tok');
|
|
58
|
+
expect(fetchSecret).not.toHaveBeenCalled();
|
|
59
|
+
});
|
|
60
|
+
it('fetches from Key Vault on a cache miss, caches born-0600, and returns it', () => {
|
|
61
|
+
// Real fs so we can assert the on-disk cache mode.
|
|
62
|
+
writeFileSync(join(dir, '.mx-coordination-team'), 'eval\n');
|
|
63
|
+
const fetchSecret = vi.fn((_vault, name) => {
|
|
64
|
+
expect(name).toBe('coordination-token-eval');
|
|
65
|
+
return 'kv-fetched-tok';
|
|
66
|
+
});
|
|
67
|
+
const res = resolveCoordinationToken({ env: { CLAUDE_WORKTREE_PATH: dir }, fetchSecret });
|
|
68
|
+
expect(res.status).toBe('resolved');
|
|
69
|
+
expect(res.source).toBe('keyvault');
|
|
70
|
+
expect(res.token).toBe('kv-fetched-tok');
|
|
71
|
+
expect(fetchSecret).toHaveBeenCalledWith(KEYVAULT_NAME, 'coordination-token-eval');
|
|
72
|
+
const cachePath = join(dir, '.mx-coordination-token-eval');
|
|
73
|
+
expect(existsSync(cachePath)).toBe(true);
|
|
74
|
+
expect(readFileSync(cachePath, 'utf-8')).toBe('kv-fetched-tok');
|
|
75
|
+
// SF-3: born 0600 — no group/other bits.
|
|
76
|
+
expect(statSync(cachePath).mode & 0o777).toBe(0o600);
|
|
77
|
+
});
|
|
78
|
+
it('fails CLOSED on an unknown-slug marker — no Key Vault fetch', () => {
|
|
79
|
+
const fetchSecret = vi.fn();
|
|
80
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
81
|
+
const res = resolveCoordinationToken({
|
|
82
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
83
|
+
readFileText: reader({ [marker]: 'not-a-real-team\n' }),
|
|
84
|
+
fetchSecret,
|
|
85
|
+
});
|
|
86
|
+
expect(res.status).toBe('not-on-roster');
|
|
87
|
+
expect(res.slug).toBe('not-a-real-team');
|
|
88
|
+
expect(res.token).toBeUndefined();
|
|
89
|
+
expect(fetchSecret).not.toHaveBeenCalled();
|
|
90
|
+
});
|
|
91
|
+
it('MF-1: a stale cross-team cache is never read — marker=marketing ignores eval cache', () => {
|
|
92
|
+
// The worktree was recycled from eval to marketing: eval's cache lingers, but
|
|
93
|
+
// the marketing marker must fetch marketing's token, never reuse eval's.
|
|
94
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
95
|
+
const evalCache = join(dir, '.mx-coordination-token-eval');
|
|
96
|
+
const fetchSecret = vi.fn(() => 'marketing-tok');
|
|
97
|
+
const res = resolveCoordinationToken({
|
|
98
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
99
|
+
readFileText: reader({ [marker]: 'marketing\n', [evalCache]: 'STALE-EVAL-TOKEN' }),
|
|
100
|
+
fetchSecret,
|
|
101
|
+
});
|
|
102
|
+
expect(res.slug).toBe('marketing');
|
|
103
|
+
expect(res.token).toBe('marketing-tok');
|
|
104
|
+
expect(res.token).not.toBe('STALE-EVAL-TOKEN');
|
|
105
|
+
// It fetched marketing's secret, never touched eval's.
|
|
106
|
+
expect(fetchSecret).toHaveBeenCalledWith(KEYVAULT_NAME, 'coordination-token-marketing');
|
|
107
|
+
});
|
|
108
|
+
it('fails OPEN when Key Vault / az errors — reports unprovisioned, never throws', () => {
|
|
109
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
110
|
+
// Mock az failure: fetchSecret returns undefined (az not logged in / KV down).
|
|
111
|
+
const fetchSecret = vi.fn(() => undefined);
|
|
112
|
+
const res = resolveCoordinationToken({
|
|
113
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
114
|
+
readFileText: reader({ [marker]: 'eval\n' }),
|
|
115
|
+
fetchSecret,
|
|
116
|
+
});
|
|
117
|
+
expect(res.status).toBe('unprovisioned');
|
|
118
|
+
expect(res.slug).toBe('eval');
|
|
119
|
+
expect(res.token).toBeUndefined();
|
|
120
|
+
expect(res.detail).toMatch(/Key Vault/);
|
|
121
|
+
});
|
|
122
|
+
it('fails OPEN when the marker is missing', () => {
|
|
123
|
+
const res = resolveCoordinationToken({
|
|
124
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
125
|
+
readFileText: reader({}),
|
|
126
|
+
fetchSecret: vi.fn(),
|
|
127
|
+
});
|
|
128
|
+
expect(res.status).toBe('unprovisioned');
|
|
129
|
+
expect(res.detail).toMatch(/no coordination marker/);
|
|
130
|
+
});
|
|
131
|
+
it('fails OPEN when CLAUDE_WORKTREE_PATH is unset (no marker to read)', () => {
|
|
132
|
+
const res = resolveCoordinationToken({ env: {}, fetchSecret: vi.fn() });
|
|
133
|
+
expect(res.status).toBe('unprovisioned');
|
|
134
|
+
expect(res.detail).toMatch(/CLAUDE_WORKTREE_PATH/);
|
|
135
|
+
});
|
|
136
|
+
it('SF-A: never throws when the config read throws (unwritable HOME) — continues to the marker path', () => {
|
|
137
|
+
mockGetConfigValue.mockImplementation(() => { throw new Error("EACCES: permission denied, mkdir '/home/nobody/.mx-agent'"); });
|
|
138
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
139
|
+
const cache = join(dir, '.mx-coordination-token-eval');
|
|
140
|
+
let res;
|
|
141
|
+
expect(() => {
|
|
142
|
+
res = resolveCoordinationToken({
|
|
143
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
144
|
+
readFileText: reader({ [marker]: 'eval\n', [cache]: 'cached-eval-tok' }),
|
|
145
|
+
fetchSecret: vi.fn(),
|
|
146
|
+
});
|
|
147
|
+
}).not.toThrow();
|
|
148
|
+
// The config throw was swallowed → resolution proceeded to the cache.
|
|
149
|
+
expect(res?.status).toBe('resolved');
|
|
150
|
+
expect(res?.token).toBe('cached-eval-tok');
|
|
151
|
+
});
|
|
152
|
+
it('never logs the token to the console', () => {
|
|
153
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
154
|
+
const errSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
155
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
156
|
+
const cache = join(dir, '.mx-coordination-token-eval');
|
|
157
|
+
resolveCoordinationToken({
|
|
158
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
159
|
+
readFileText: reader({ [marker]: 'eval\n', [cache]: 'secret-token-value' }),
|
|
160
|
+
fetchSecret: vi.fn(() => 'secret-token-value'),
|
|
161
|
+
});
|
|
162
|
+
const all = [...logSpy.mock.calls, ...errSpy.mock.calls].flat().join(' ');
|
|
163
|
+
expect(all).not.toContain('secret-token-value');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
//# sourceMappingURL=coordination-token.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordination-token.test.js","sourceRoot":"","sources":["../../src/__tests__/coordination-token.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,27 @@
|
|
|
10
10
|
* only a local durable fallback file and flushes it on the next success.
|
|
11
11
|
*/
|
|
12
12
|
import { type CoordinationClient } from '../lib/coordination-client.js';
|
|
13
|
+
/**
|
|
14
|
+
* Build the HTTP client, self-provisioning the coordination token from Key Vault
|
|
15
|
+
* when none is configured. This ports the coordination-brief hook's KV-fetch into
|
|
16
|
+
* the CLI so a bare `mx-agent coordination brief` (and drain/escalate/history)
|
|
17
|
+
* works standalone with the SAME isolation the security review required (marker
|
|
18
|
+
* authoritative, roster-gated, slug-bound per-worktree 0600 cache, no global-
|
|
19
|
+
* config clobber, no token logging).
|
|
20
|
+
*
|
|
21
|
+
* Returns null — never throws — when a token cannot be provisioned, so the caller
|
|
22
|
+
* degrades cleanly (falls back to the manual channel) instead of crashing:
|
|
23
|
+
* - roster mismatch → fail-CLOSED (no KV fetch), one-line notice.
|
|
24
|
+
* - infra/no-marker → fail-OPEN, one-line notice.
|
|
25
|
+
* When a client IS injected (tests), provisioning is skipped entirely.
|
|
26
|
+
*
|
|
27
|
+
* The resolved token is set in-memory (process env for the request) and is NEVER
|
|
28
|
+
* written to the global ~/.mx-agent config (the MF-2 cross-worktree-clobber
|
|
29
|
+
* defect) and NEVER logged.
|
|
30
|
+
*/
|
|
31
|
+
export declare function prepareClient(deps?: {
|
|
32
|
+
client?: CoordinationClient;
|
|
33
|
+
}): CoordinationClient | null;
|
|
13
34
|
export interface EscalateOptions {
|
|
14
35
|
to: string;
|
|
15
36
|
priority: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordination.d.ts","sourceRoot":"","sources":["../../src/commands/coordination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAKL,KAAK,kBAAkB,EAExB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"coordination.d.ts","sourceRoot":"","sources":["../../src/commands/coordination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAKL,KAAK,kBAAkB,EAExB,MAAM,+BAA+B,CAAC;AAoCvC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,kBAAkB,GAAG,IAAI,CAqC/F;AAkCD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B9G;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4EAA4E;IAC5E,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBxG;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,IAAI,GAAE,YAAiB,EAAE,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4C7G;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,kFAAkF;AAClF,qBAAa,cAAe,SAAQ,KAAK;;CAKxC;AAQD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,GAAE,YAAiB,EACvB,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,GAC5E,OAAO,CAAC,IAAI,CAAC,CAqCf;AAED,gBAAgB;AAChB,wBAAsB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrG;AAED,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAKD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,IAAI,GAAE,cAAmB,EAAE,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBjH"}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* only a local durable fallback file and flushes it on the next success.
|
|
11
11
|
*/
|
|
12
12
|
import { HttpCoordinationClient, resolveClientConfig, ServiceUnreachableError, ServiceHttpError, } from '../lib/coordination-client.js';
|
|
13
|
+
import { resolveCoordinationToken } from '../lib/coordination-token.js';
|
|
13
14
|
import { appendFallbackEntry, flushFallback } from '../lib/coordination-fallback.js';
|
|
14
15
|
import { renderMessages } from '../lib/coordination-render.js';
|
|
15
16
|
const VALID_PRIORITIES = new Set(['p0', 'p1', 'p2', 'p3']);
|
|
@@ -38,9 +39,60 @@ function flushStdout() {
|
|
|
38
39
|
process.stdout.write('', () => resolve());
|
|
39
40
|
});
|
|
40
41
|
}
|
|
41
|
-
/**
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Build the HTTP client, self-provisioning the coordination token from Key Vault
|
|
44
|
+
* when none is configured. This ports the coordination-brief hook's KV-fetch into
|
|
45
|
+
* the CLI so a bare `mx-agent coordination brief` (and drain/escalate/history)
|
|
46
|
+
* works standalone with the SAME isolation the security review required (marker
|
|
47
|
+
* authoritative, roster-gated, slug-bound per-worktree 0600 cache, no global-
|
|
48
|
+
* config clobber, no token logging).
|
|
49
|
+
*
|
|
50
|
+
* Returns null — never throws — when a token cannot be provisioned, so the caller
|
|
51
|
+
* degrades cleanly (falls back to the manual channel) instead of crashing:
|
|
52
|
+
* - roster mismatch → fail-CLOSED (no KV fetch), one-line notice.
|
|
53
|
+
* - infra/no-marker → fail-OPEN, one-line notice.
|
|
54
|
+
* When a client IS injected (tests), provisioning is skipped entirely.
|
|
55
|
+
*
|
|
56
|
+
* The resolved token is set in-memory (process env for the request) and is NEVER
|
|
57
|
+
* written to the global ~/.mx-agent config (the MF-2 cross-worktree-clobber
|
|
58
|
+
* defect) and NEVER logged.
|
|
59
|
+
*/
|
|
60
|
+
export function prepareClient(deps) {
|
|
61
|
+
if (deps?.client)
|
|
62
|
+
return deps.client;
|
|
63
|
+
// SF-A never-crash contract: resolveCoordinationToken is documented never-throws,
|
|
64
|
+
// but its config read can still touch the filesystem (mkdirSync on an unwritable/
|
|
65
|
+
// read-only HOME → EACCES/EROFS). Keep the WHOLE resolve+build inside the
|
|
66
|
+
// try/catch so ANY throw degrades to the null fall-back path — a coordination
|
|
67
|
+
// hiccup must never crash `mx-agent coordination brief` (breaks session start).
|
|
68
|
+
let res = { status: 'unprovisioned', detail: 'token resolution failed' };
|
|
69
|
+
try {
|
|
70
|
+
res = resolveCoordinationToken();
|
|
71
|
+
if (res.status === 'resolved' && res.token) {
|
|
72
|
+
// In-memory only: resolveClientConfig reads MX_COORD_SERVICE_TOKEN in
|
|
73
|
+
// preference to the global config, so we never touch the shared config file.
|
|
74
|
+
process.env.MX_COORD_SERVICE_TOKEN = res.token;
|
|
75
|
+
// SF-B: arm the SF-1 verify-before-confirm interlock on the bare
|
|
76
|
+
// self-provisioned path, matching the hook (which set MX_COORD_EXPECT_TEAM).
|
|
77
|
+
// `??=` so an explicit hook-set value is never overwritten.
|
|
78
|
+
if (res.slug)
|
|
79
|
+
process.env.MX_COORD_EXPECT_TEAM ??= res.slug;
|
|
80
|
+
}
|
|
81
|
+
return new HttpCoordinationClient(resolveClientConfig());
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
// No usable token/URL (or a resolve-time throw). Report a non-secret, one-line
|
|
85
|
+
// fall-back notice and return null; the caller returns cleanly so the agent
|
|
86
|
+
// uses the old channel.
|
|
87
|
+
if (res.status === 'not-on-roster') {
|
|
88
|
+
process.stderr.write(`coordination: team "${res.slug}" is not on the coordination roster — falling back to the manual channel\n`);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const why = res.detail ?? (err instanceof Error ? err.message : String(err));
|
|
92
|
+
process.stderr.write(`coordination: could not provision a service token (${why}) — falling back to the manual channel\n`);
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
44
96
|
}
|
|
45
97
|
/**
|
|
46
98
|
* Opportunistically flush any queued-locally entries. Surfaces a flush FAILURE
|
|
@@ -87,14 +139,11 @@ export async function runEscalate(opts, deps) {
|
|
|
87
139
|
}
|
|
88
140
|
const team = resolveTeam(opts.team);
|
|
89
141
|
const entry = { team, to: opts.to, priority: opts.priority, body: opts.body, from: team };
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
catch (err) {
|
|
95
|
-
// No config at all — still degrade to the local fallback so nothing is lost.
|
|
142
|
+
const client = prepareClient(deps);
|
|
143
|
+
if (!client) {
|
|
144
|
+
// No token/URL could be provisioned (prepareClient already printed the reason).
|
|
145
|
+
// Degrade to the local fallback so the message is never lost.
|
|
96
146
|
writeFallbackOrFail(entry);
|
|
97
|
-
console.error(err instanceof Error ? err.message : String(err));
|
|
98
147
|
console.log('queued locally, will flush on reconnect');
|
|
99
148
|
return;
|
|
100
149
|
}
|
|
@@ -123,7 +172,9 @@ export async function runEscalate(opts, deps) {
|
|
|
123
172
|
* it pending for re-queue. `--no-confirm` leaves the batch unconfirmed.
|
|
124
173
|
*/
|
|
125
174
|
export async function runDrain(opts, deps) {
|
|
126
|
-
const client = deps
|
|
175
|
+
const client = prepareClient(deps);
|
|
176
|
+
if (!client)
|
|
177
|
+
return; // could not provision — fall back (prepareClient printed why)
|
|
127
178
|
// Flush any queued-locally entries now that the service is reachable.
|
|
128
179
|
await opportunisticFlush(client);
|
|
129
180
|
const limit = opts.all ? undefined : opts.limit ? parseInt(opts.limit, 10) : undefined;
|
|
@@ -152,7 +203,9 @@ export async function runDrain(opts, deps) {
|
|
|
152
203
|
* keep the block under the token ceiling for any backlog.
|
|
153
204
|
*/
|
|
154
205
|
export async function runBrief(opts = {}, deps) {
|
|
155
|
-
const client = deps
|
|
206
|
+
const client = prepareClient(deps);
|
|
207
|
+
if (!client)
|
|
208
|
+
return; // could not provision — fall back (prepareClient printed why)
|
|
156
209
|
await opportunisticFlush(client);
|
|
157
210
|
const limit = opts.limit ?? envInt('MX_COORD_BRIEF_LIMIT', 10);
|
|
158
211
|
const res = await client.drain({ limit });
|
|
@@ -226,7 +279,9 @@ export function redactSecrets(s) {
|
|
|
226
279
|
* scope (see README).
|
|
227
280
|
*/
|
|
228
281
|
export async function runWatch(opts = {}, deps) {
|
|
229
|
-
const client = deps
|
|
282
|
+
const client = prepareClient(deps);
|
|
283
|
+
if (!client)
|
|
284
|
+
return; // could not provision — fall back (prepareClient printed why)
|
|
230
285
|
const intervalMs = opts.intervalMs ?? envInt('MX_COORD_PRIORITY_POLL_MS', 15_000);
|
|
231
286
|
const limit = opts.limit ?? envInt('MX_COORD_BRIEF_LIMIT', 10);
|
|
232
287
|
const sleep = deps?.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
@@ -266,7 +321,9 @@ export async function runWatch(opts = {}, deps) {
|
|
|
266
321
|
}
|
|
267
322
|
/** FR-7 ack. */
|
|
268
323
|
export async function runAck(messageId, deps) {
|
|
269
|
-
const client = deps
|
|
324
|
+
const client = prepareClient(deps);
|
|
325
|
+
if (!client)
|
|
326
|
+
return; // could not provision — fall back (prepareClient printed why)
|
|
270
327
|
await client.ack(messageId);
|
|
271
328
|
console.log(`acked: ${messageId}`);
|
|
272
329
|
}
|
|
@@ -281,7 +338,9 @@ const HISTORY_MAX_PAGES = 500;
|
|
|
281
338
|
* follows the `nextBefore` cursor to page the full history (most-recent-first).
|
|
282
339
|
*/
|
|
283
340
|
export async function runHistory(opts = {}, deps) {
|
|
284
|
-
const client = deps
|
|
341
|
+
const client = prepareClient(deps);
|
|
342
|
+
if (!client)
|
|
343
|
+
return; // could not provision — fall back (prepareClient printed why)
|
|
285
344
|
const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;
|
|
286
345
|
const collected = [];
|
|
287
346
|
let before;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordination.js","sourceRoot":"","sources":["../../src/commands/coordination.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"coordination.js","sourceRoot":"","sources":["../../src/commands/coordination.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* coordination-token -- self-provision the coordination service bearer token.
|
|
3
|
+
*
|
|
4
|
+
* Ports the security-reviewed KV-fetch logic from the agent-config hook
|
|
5
|
+
* `coordination-brief.sh` into the CLI so that a bare `mx-agent coordination
|
|
6
|
+
* brief` (and drain/escalate/history) resolves its own token when none is
|
|
7
|
+
* configured, instead of failing with "token not set" and falling back to the
|
|
8
|
+
* old channel. The isolation properties the security review required are
|
|
9
|
+
* preserved 1:1:
|
|
10
|
+
*
|
|
11
|
+
* - MF-2 The team slug is read from the authoritative worktree marker
|
|
12
|
+
* (.mx-coordination-team). It is NEVER derived from CLAUDE_TEAM_NAME
|
|
13
|
+
* or the worktree name.
|
|
14
|
+
* - SF-2 The slug is validated against the exact roster BEFORE any `az` call.
|
|
15
|
+
* A non-member fails CLOSED (no fetch) so the caller falls back.
|
|
16
|
+
* - MF-1 The token cache filename embeds the slug
|
|
17
|
+
* (.mx-coordination-token-<slug>), per worktree. A worktree recycled
|
|
18
|
+
* to a different team can never read another team's cached token.
|
|
19
|
+
* - SF-3 The cache is created born 0600 (mode on create — no readable window).
|
|
20
|
+
* - No shell: the roster-validated slug is passed to `az` via execFile with an
|
|
21
|
+
* args array, never interpolated into a shell string.
|
|
22
|
+
* - The token is NEVER written to the global ~/.mx-agent config (that clobbers
|
|
23
|
+
* across worktrees — the MF-2 defect) and is NEVER logged.
|
|
24
|
+
* - Fail-OPEN on infra errors (no marker, az not logged in, KV unreachable):
|
|
25
|
+
* report "unprovisioned" so the caller degrades, never crash.
|
|
26
|
+
* - Fail-CLOSED only on a roster mismatch.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* SF-2 canonical roster — mirror of coordination-brief.sh's COORD_ROSTER. The
|
|
30
|
+
* marker slug MUST be an exact member of this list before it is ever passed to
|
|
31
|
+
* `az`. Aliases (mx-agent / mx-agent-system) are intentionally excluded.
|
|
32
|
+
*/
|
|
33
|
+
export declare const COORD_ROSTER: readonly ["platform", "retrieval", "mcp", "pipeline", "marketing", "customer-portal", "eval", "product"];
|
|
34
|
+
export declare const KEYVAULT_NAME = "mx-dev-eastus2-kv-001";
|
|
35
|
+
export type TokenResolveStatus =
|
|
36
|
+
/** A token was already in env/config; KV is skipped (hook path + manual override). */
|
|
37
|
+
'already-configured'
|
|
38
|
+
/** A token was provisioned (from the per-worktree cache or a fresh KV fetch). */
|
|
39
|
+
| 'resolved'
|
|
40
|
+
/** Fail-CLOSED: the marker slug is not on the roster — no fetch performed. */
|
|
41
|
+
| 'not-on-roster'
|
|
42
|
+
/** Fail-OPEN: no marker, az not logged in, KV unreachable, or empty secret. */
|
|
43
|
+
| 'unprovisioned';
|
|
44
|
+
export interface TokenResolveResult {
|
|
45
|
+
status: TokenResolveStatus;
|
|
46
|
+
/** The resolved token — set only for 'already-configured' and 'resolved'. */
|
|
47
|
+
token?: string;
|
|
48
|
+
/** The marker slug, when one was read (roster or not). */
|
|
49
|
+
slug?: string;
|
|
50
|
+
/** Where the token came from — for diagnostics; never includes the token. */
|
|
51
|
+
source?: 'env' | 'config' | 'cache' | 'keyvault';
|
|
52
|
+
/** Non-secret reason for a fail-open, safe to print to stderr. */
|
|
53
|
+
detail?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface TokenResolveDeps {
|
|
56
|
+
/** Environment to read (default process.env). */
|
|
57
|
+
env?: NodeJS.ProcessEnv;
|
|
58
|
+
/**
|
|
59
|
+
* Fetch a Key Vault secret's value by validated name. Overridable in tests to
|
|
60
|
+
* mock `az`. Returns undefined on any failure (fail-open).
|
|
61
|
+
*/
|
|
62
|
+
fetchSecret?: (vault: string, secretName: string) => string | undefined;
|
|
63
|
+
/** Read a file's text, or undefined if missing/unreadable. Overridable in tests. */
|
|
64
|
+
readFileText?: (path: string) => string | undefined;
|
|
65
|
+
/** Persist the fetched token to the per-worktree cache (born 0600). */
|
|
66
|
+
writeCache?: (path: string, value: string) => void;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the coordination token, self-provisioning from Key Vault when none is
|
|
70
|
+
* configured. Never throws — every failure is a typed result the caller acts on.
|
|
71
|
+
* The returned token (when present) must be handed to the client in-memory
|
|
72
|
+
* (process env for the request); it must NOT be written to the global config.
|
|
73
|
+
*/
|
|
74
|
+
export declare function resolveCoordinationToken(deps?: TokenResolveDeps): TokenResolveResult;
|
|
75
|
+
//# sourceMappingURL=coordination-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordination-token.d.ts","sourceRoot":"","sources":["../../src/lib/coordination-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAQH;;;;GAIG;AACH,eAAO,MAAM,YAAY,0GASf,CAAC;AAEX,eAAO,MAAM,aAAa,0BAA0B,CAAC;AAKrD,MAAM,MAAM,kBAAkB;AAC5B,sFAAsF;AACpF,oBAAoB;AACtB,iFAAiF;GAC/E,UAAU;AACZ,8EAA8E;GAC5E,eAAe;AACjB,+EAA+E;GAC7E,eAAe,CAAC;AAEpB,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;IACjD,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,iDAAiD;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,oFAAoF;IACpF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACpD,uEAAuE;IACvE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpD;AAmDD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,gBAAqB,GAAG,kBAAkB,CAmExF"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* coordination-token -- self-provision the coordination service bearer token.
|
|
3
|
+
*
|
|
4
|
+
* Ports the security-reviewed KV-fetch logic from the agent-config hook
|
|
5
|
+
* `coordination-brief.sh` into the CLI so that a bare `mx-agent coordination
|
|
6
|
+
* brief` (and drain/escalate/history) resolves its own token when none is
|
|
7
|
+
* configured, instead of failing with "token not set" and falling back to the
|
|
8
|
+
* old channel. The isolation properties the security review required are
|
|
9
|
+
* preserved 1:1:
|
|
10
|
+
*
|
|
11
|
+
* - MF-2 The team slug is read from the authoritative worktree marker
|
|
12
|
+
* (.mx-coordination-team). It is NEVER derived from CLAUDE_TEAM_NAME
|
|
13
|
+
* or the worktree name.
|
|
14
|
+
* - SF-2 The slug is validated against the exact roster BEFORE any `az` call.
|
|
15
|
+
* A non-member fails CLOSED (no fetch) so the caller falls back.
|
|
16
|
+
* - MF-1 The token cache filename embeds the slug
|
|
17
|
+
* (.mx-coordination-token-<slug>), per worktree. A worktree recycled
|
|
18
|
+
* to a different team can never read another team's cached token.
|
|
19
|
+
* - SF-3 The cache is created born 0600 (mode on create — no readable window).
|
|
20
|
+
* - No shell: the roster-validated slug is passed to `az` via execFile with an
|
|
21
|
+
* args array, never interpolated into a shell string.
|
|
22
|
+
* - The token is NEVER written to the global ~/.mx-agent config (that clobbers
|
|
23
|
+
* across worktrees — the MF-2 defect) and is NEVER logged.
|
|
24
|
+
* - Fail-OPEN on infra errors (no marker, az not logged in, KV unreachable):
|
|
25
|
+
* report "unprovisioned" so the caller degrades, never crash.
|
|
26
|
+
* - Fail-CLOSED only on a roster mismatch.
|
|
27
|
+
*/
|
|
28
|
+
import { execFileSync } from 'node:child_process';
|
|
29
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
30
|
+
import { join } from 'node:path';
|
|
31
|
+
import { getConfigValue } from './config.js';
|
|
32
|
+
import { CONFIG_KEY_TOKEN } from './coordination-client.js';
|
|
33
|
+
/**
|
|
34
|
+
* SF-2 canonical roster — mirror of coordination-brief.sh's COORD_ROSTER. The
|
|
35
|
+
* marker slug MUST be an exact member of this list before it is ever passed to
|
|
36
|
+
* `az`. Aliases (mx-agent / mx-agent-system) are intentionally excluded.
|
|
37
|
+
*/
|
|
38
|
+
export const COORD_ROSTER = [
|
|
39
|
+
'platform',
|
|
40
|
+
'retrieval',
|
|
41
|
+
'mcp',
|
|
42
|
+
'pipeline',
|
|
43
|
+
'marketing',
|
|
44
|
+
'customer-portal',
|
|
45
|
+
'eval',
|
|
46
|
+
'product',
|
|
47
|
+
];
|
|
48
|
+
export const KEYVAULT_NAME = 'mx-dev-eastus2-kv-001';
|
|
49
|
+
const MARKER_FILE = '.mx-coordination-team';
|
|
50
|
+
const CACHE_PREFIX = '.mx-coordination-token-';
|
|
51
|
+
/** Default marker/cache reader: undefined on missing or unreadable file. */
|
|
52
|
+
function defaultReadFileText(path) {
|
|
53
|
+
try {
|
|
54
|
+
if (!existsSync(path))
|
|
55
|
+
return undefined;
|
|
56
|
+
return readFileSync(path, 'utf-8');
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Default KV fetch. The slug embedded in `secretName` is roster-validated by the
|
|
64
|
+
* caller; it is passed to `az` as a single argv element via execFile (no shell),
|
|
65
|
+
* so a metacharacter in a slug could never inject a command even if the roster
|
|
66
|
+
* gate were bypassed. Any failure (az not logged in, KV unreachable, missing
|
|
67
|
+
* secret) returns undefined → fail-open.
|
|
68
|
+
*/
|
|
69
|
+
function defaultFetchSecret(vault, secretName) {
|
|
70
|
+
try {
|
|
71
|
+
const out = execFileSync('az', ['keyvault', 'secret', 'show', '--vault-name', vault, '--name', secretName, '--query', 'value', '-o', 'tsv'], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
72
|
+
const trimmed = out.trim();
|
|
73
|
+
return trimmed || undefined;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** SF-3 born-0600 cache write. A write failure is tolerated (fail-open). */
|
|
80
|
+
function defaultWriteCache(path, value) {
|
|
81
|
+
try {
|
|
82
|
+
// mode 0600 on create — 0600 has no group/other bits, so no umask can widen
|
|
83
|
+
// it. The cache is only written when absent (see resolveCoordinationToken),
|
|
84
|
+
// so this is always a create.
|
|
85
|
+
writeFileSync(path, value, { mode: 0o600 });
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
/* A cache-write failure must not break provisioning — the token is still returned. */
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** Extract the first line and strip all whitespace (marker/cache are single-value). */
|
|
92
|
+
function firstLineNoSpace(raw) {
|
|
93
|
+
const firstLine = raw.split(/\r?\n/, 1)[0] ?? '';
|
|
94
|
+
return firstLine.replace(/\s+/g, '');
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Resolve the coordination token, self-provisioning from Key Vault when none is
|
|
98
|
+
* configured. Never throws — every failure is a typed result the caller acts on.
|
|
99
|
+
* The returned token (when present) must be handed to the client in-memory
|
|
100
|
+
* (process env for the request); it must NOT be written to the global config.
|
|
101
|
+
*/
|
|
102
|
+
export function resolveCoordinationToken(deps = {}) {
|
|
103
|
+
const env = deps.env ?? process.env;
|
|
104
|
+
const readFileText = deps.readFileText ?? defaultReadFileText;
|
|
105
|
+
// 1. Already configured → use it, skip KV. Env preferred, then global config.
|
|
106
|
+
// This keeps the hook path (which injects MX_COORD_SERVICE_TOKEN) and any
|
|
107
|
+
// manual `mx-agent config set coordination-service-token` working unchanged.
|
|
108
|
+
const envToken = env.MX_COORD_SERVICE_TOKEN;
|
|
109
|
+
if (envToken)
|
|
110
|
+
return { status: 'already-configured', token: envToken, source: 'env' };
|
|
111
|
+
// Belt-and-suspenders for the SF-A never-crash contract: getConfigValue →
|
|
112
|
+
// loadConfig → getConfigDir calls mkdirSync, which throws on an unwritable/
|
|
113
|
+
// read-only HOME (EACCES/EROFS/ENOSPC). Swallow it and treat the config token
|
|
114
|
+
// as absent so resolution continues to the marker/KV path instead of throwing.
|
|
115
|
+
let configToken;
|
|
116
|
+
try {
|
|
117
|
+
configToken = getConfigValue(CONFIG_KEY_TOKEN);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
configToken = undefined;
|
|
121
|
+
}
|
|
122
|
+
if (configToken)
|
|
123
|
+
return { status: 'already-configured', token: configToken, source: 'config' };
|
|
124
|
+
// 2. MF-2: read the authoritative marker. No worktree path or no marker →
|
|
125
|
+
// fail-OPEN. We do NOT derive the slug from any other signal.
|
|
126
|
+
const worktree = env.CLAUDE_WORKTREE_PATH;
|
|
127
|
+
if (!worktree) {
|
|
128
|
+
return { status: 'unprovisioned', detail: 'CLAUDE_WORKTREE_PATH is unset — cannot locate the coordination marker' };
|
|
129
|
+
}
|
|
130
|
+
const markerRaw = readFileText(join(worktree, MARKER_FILE));
|
|
131
|
+
if (markerRaw === undefined) {
|
|
132
|
+
return { status: 'unprovisioned', detail: 'no coordination marker (.mx-coordination-team) in this worktree' };
|
|
133
|
+
}
|
|
134
|
+
const slug = firstLineNoSpace(markerRaw);
|
|
135
|
+
if (!slug) {
|
|
136
|
+
return { status: 'unprovisioned', detail: 'coordination marker is empty' };
|
|
137
|
+
}
|
|
138
|
+
// 3. SF-2: roster-membership gate BEFORE any az call. Not a member → fail-CLOSED.
|
|
139
|
+
if (!COORD_ROSTER.includes(slug)) {
|
|
140
|
+
return { status: 'not-on-roster', slug };
|
|
141
|
+
}
|
|
142
|
+
// 4. MF-1: slug-bound per-worktree cache. The slug is in the filename, so a
|
|
143
|
+
// worktree recycled to another team (marker rewritten) can never read the
|
|
144
|
+
// prior team's token — its cache path simply does not exist yet.
|
|
145
|
+
const cachePath = join(worktree, `${CACHE_PREFIX}${slug}`);
|
|
146
|
+
const cachedRaw = readFileText(cachePath);
|
|
147
|
+
if (cachedRaw) {
|
|
148
|
+
const cached = firstLineNoSpace(cachedRaw);
|
|
149
|
+
if (cached)
|
|
150
|
+
return { status: 'resolved', token: cached, slug, source: 'cache' };
|
|
151
|
+
}
|
|
152
|
+
// 5. Fetch from Key Vault once. The roster-validated slug is the only variable
|
|
153
|
+
// part of the secret name, passed via execFile args (no shell).
|
|
154
|
+
const fetchSecret = deps.fetchSecret ?? defaultFetchSecret;
|
|
155
|
+
const fetched = fetchSecret(KEYVAULT_NAME, `coordination-token-${slug}`);
|
|
156
|
+
if (!fetched) {
|
|
157
|
+
return {
|
|
158
|
+
status: 'unprovisioned',
|
|
159
|
+
slug,
|
|
160
|
+
detail: 'Key Vault returned no token (az not logged in, KV unreachable, or secret missing)',
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
// SF-3: cache born 0600. NEVER persisted to the global config.
|
|
164
|
+
const writeCache = deps.writeCache ?? defaultWriteCache;
|
|
165
|
+
writeCache(cachePath, fetched);
|
|
166
|
+
return { status: 'resolved', token: fetched, slug, source: 'keyvault' };
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=coordination-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordination-token.js","sourceRoot":"","sources":["../../src/lib/coordination-token.ts"],"names":[],"mappings":"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"}
|