@proappstore/cli 2.6.40 → 2.6.41
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/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-auth.d.ts +3 -0
- package/dist/mcp-auth.d.ts.map +1 -0
- package/dist/mcp-auth.js +131 -0
- package/dist/mcp-auth.js.map +1 -0
- package/dist/mcp-remote-auth-relay.test.d.ts +2 -0
- package/dist/mcp-remote-auth-relay.test.d.ts.map +1 -0
- package/dist/mcp-remote-auth-relay.test.js +95 -0
- package/dist/mcp-remote-auth-relay.test.js.map +1 -0
- package/dist/mcp-remote-auth.d.ts +140 -0
- package/dist/mcp-remote-auth.d.ts.map +1 -0
- package/dist/mcp-remote-auth.js +472 -0
- package/dist/mcp-remote-auth.js.map +1 -0
- package/dist/mcp-remote-auth.test.d.ts +2 -0
- package/dist/mcp-remote-auth.test.d.ts.map +1 -0
- package/dist/mcp-remote-auth.test.js +367 -0
- package/dist/mcp-remote-auth.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { mkdtemp, readFile, rm, stat, writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { webcrypto } from 'node:crypto';
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
6
|
+
// The broker's own sealing function, so these tests open exactly what production seals. Loaded by a
|
|
7
|
+
// computed path so the CLI's type program stays inside the CLI (the backend is a Workers package).
|
|
8
|
+
const BROKER = '../../backend/src/routes/mcp-broker.js';
|
|
9
|
+
const { seal } = await import(/* @vite-ignore */ BROKER);
|
|
10
|
+
import { connect, generateMachineSecrets, openEnvelope, RemoteAuthError, } from './mcp-remote-auth.js';
|
|
11
|
+
// #356, synthetic: a fake broker that keeps the real broker's rules (proof hash, PKCE, generic 409,
|
|
12
|
+
// single redemption, receipt-gated `connected`) and seals with the broker's own `seal`; a fake phone;
|
|
13
|
+
// a fake MCP endpoint that records the authenticated read; a fake `pags`. No network, no real account,
|
|
14
|
+
// no real device. Real-device acceptance is ProAgentStore #1006.
|
|
15
|
+
const API = 'https://api.test';
|
|
16
|
+
const RESOURCE = 'https://mcp.test/mcp';
|
|
17
|
+
const OWNER_SESSION = 'owner-session-synthetic';
|
|
18
|
+
const OTHER_SESSION = 'other-session-synthetic';
|
|
19
|
+
const OWNERS = { [OWNER_SESSION]: 'gh:1', [OTHER_SESSION]: 'gh:2' };
|
|
20
|
+
const b64 = (u) => Buffer.from(u).toString('base64url');
|
|
21
|
+
const sha = async (s) => new Uint8Array(await webcrypto.subtle.digest('SHA-256', new TextEncoder().encode(s)));
|
|
22
|
+
let dir;
|
|
23
|
+
let clock;
|
|
24
|
+
let lines;
|
|
25
|
+
let requests;
|
|
26
|
+
let creates;
|
|
27
|
+
let relays;
|
|
28
|
+
let states;
|
|
29
|
+
let pagsVersion;
|
|
30
|
+
let relayExit;
|
|
31
|
+
let failNetwork;
|
|
32
|
+
let onPoll;
|
|
33
|
+
let polls;
|
|
34
|
+
let mcpUp;
|
|
35
|
+
/** The phone: approve as `session`'s user. A user who is not the owner cannot approve (the broker refuses). */
|
|
36
|
+
async function approve(r, session = OWNER_SESSION) {
|
|
37
|
+
if (OWNERS[session] !== r.owner || r.status !== 'pending')
|
|
38
|
+
return false;
|
|
39
|
+
r.token = `mcp-token-${b64(webcrypto.getRandomValues(new Uint8Array(16)))}`;
|
|
40
|
+
const sealed = await seal(r.publicKey, { access_token: r.token, token_type: 'Bearer', resource: r.resource, expires_in: 86_400 }, r.id);
|
|
41
|
+
r.envelope = { iv: sealed.iv, ...JSON.parse(sealed.ciphertext) };
|
|
42
|
+
r.status = 'approved_awaiting_machine';
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
function json(status, body) {
|
|
46
|
+
return new Response(JSON.stringify(body), { status, headers: { 'Content-Type': 'application/json' } });
|
|
47
|
+
}
|
|
48
|
+
const fakeFetch = async (input, init) => {
|
|
49
|
+
const url = String(input);
|
|
50
|
+
const body = init?.body ? JSON.parse(String(init.body)) : {};
|
|
51
|
+
if (failNetwork && url.endsWith(failNetwork.path) && failNetwork.times > 0) {
|
|
52
|
+
failNetwork.times -= 1;
|
|
53
|
+
throw new TypeError('fetch failed');
|
|
54
|
+
}
|
|
55
|
+
if (url === RESOURCE) {
|
|
56
|
+
const bearer = new Headers(init?.headers).get('Authorization')?.slice(7);
|
|
57
|
+
const r = [...requests.values()].find((x) => x.token && x.token === bearer);
|
|
58
|
+
if (!mcpUp || !r)
|
|
59
|
+
return new Response('unauthorized', { status: 401 });
|
|
60
|
+
r.seen = true;
|
|
61
|
+
return json(200, { jsonrpc: '2.0', id: 1, result: {} });
|
|
62
|
+
}
|
|
63
|
+
const path = url.slice(`${API}/v1/mcp/broker/v2`.length);
|
|
64
|
+
const unavailable = () => json(409, { error: 'remote_auth_unavailable' });
|
|
65
|
+
if (path === '/requests') {
|
|
66
|
+
const owner = OWNERS[new Headers(init?.headers).get('Authorization')?.slice(7) ?? ''];
|
|
67
|
+
if (!owner)
|
|
68
|
+
return json(401, { error: 'unauthorized' });
|
|
69
|
+
creates += 1;
|
|
70
|
+
const id = `req_${b64(webcrypto.getRandomValues(new Uint8Array(32)))}`;
|
|
71
|
+
requests.set(id, {
|
|
72
|
+
id, owner, proofHash: String(body.machine_proof_hash), challenge: String(body.code_challenge), publicKey: String(body.machine_public_key),
|
|
73
|
+
resource: String(body.resource), status: 'pending', expires: clock + 10 * 60_000, envelope: null, attemptId: null, token: null, seen: false,
|
|
74
|
+
});
|
|
75
|
+
return json(201, { request_id: id, status: 'pending', expires_at: clock + 10 * 60_000, approval_url: `${API}/v1/mcp/broker/v2/requests/${id}/approve`, status_url: `${API}/v1/mcp/broker/v2/requests/${id}/status` });
|
|
76
|
+
}
|
|
77
|
+
const r = requests.get(String(body.request_id));
|
|
78
|
+
if (!r || Buffer.from(await sha(String(body.machine_proof))).toString('hex') !== r.proofHash)
|
|
79
|
+
return unavailable();
|
|
80
|
+
if (r.expires <= clock && ['pending', 'approving', 'approved_awaiting_machine'].includes(r.status))
|
|
81
|
+
r.status = 'expired';
|
|
82
|
+
const pkceOk = async () => b64(await sha(String(body.code_verifier))) === r.challenge;
|
|
83
|
+
if (path === '/requests/poll') {
|
|
84
|
+
polls += 1;
|
|
85
|
+
await onPoll(r, polls);
|
|
86
|
+
return json(200, { status: r.status, retry_after_ms: 2000, expires_at: r.expires });
|
|
87
|
+
}
|
|
88
|
+
if (path === '/requests/redeem') {
|
|
89
|
+
if (!(await pkceOk()))
|
|
90
|
+
return unavailable();
|
|
91
|
+
if (r.status === 'approved_awaiting_machine') {
|
|
92
|
+
r.status = 'consumed';
|
|
93
|
+
r.attemptId = String(body.redeem_attempt_id);
|
|
94
|
+
return json(200, { status: 'consumed', credential: r.envelope });
|
|
95
|
+
}
|
|
96
|
+
if (r.status === 'consumed' && r.attemptId === body.redeem_attempt_id)
|
|
97
|
+
return json(200, { status: 'consumed', credential: r.envelope });
|
|
98
|
+
return unavailable();
|
|
99
|
+
}
|
|
100
|
+
if (path === '/requests/connected' || path === '/requests/failed') {
|
|
101
|
+
if (!(await pkceOk()) || r.status !== 'consumed' || (path === '/requests/connected' && !r.seen))
|
|
102
|
+
return unavailable();
|
|
103
|
+
r.status = path.endsWith('connected') ? 'connected' : 'failed';
|
|
104
|
+
return json(200, { status: r.status });
|
|
105
|
+
}
|
|
106
|
+
return unavailable();
|
|
107
|
+
};
|
|
108
|
+
function deps(over = {}) {
|
|
109
|
+
return {
|
|
110
|
+
fetch: fakeFetch,
|
|
111
|
+
runPags: async (args, stdin) => {
|
|
112
|
+
if (args[0] === '--version') {
|
|
113
|
+
if (pagsVersion === null)
|
|
114
|
+
throw Object.assign(new Error('spawn pags ENOENT'), { code: 'ENOENT' });
|
|
115
|
+
return { code: 0, stdout: `${pagsVersion}\n`, stderr: '' };
|
|
116
|
+
}
|
|
117
|
+
if (args[0] === 'remote-auth' && args[1] === 'relay') {
|
|
118
|
+
const exit = relayExit.shift() ?? 0;
|
|
119
|
+
if (exit !== 0)
|
|
120
|
+
return { code: exit, stdout: '', stderr: 'refused' };
|
|
121
|
+
const parsed = JSON.parse(stdin ?? '');
|
|
122
|
+
const duplicate = relays.some((x) => x.parsed.request_id === parsed.request_id);
|
|
123
|
+
relays.push({ input: stdin ?? '', parsed });
|
|
124
|
+
return { code: 0, stdout: `${JSON.stringify({ id: `rar_${String(parsed.request_id).slice(4, 12)}`, url: 'https://pags.test/console/remote-auth/rar_x', state: 'pending', duplicate })}\n`, stderr: '' };
|
|
125
|
+
}
|
|
126
|
+
if (args[0] === 'remote-auth' && args[1] === 'state') {
|
|
127
|
+
states.push([args[2], args[3]]);
|
|
128
|
+
return { code: 0, stdout: '', stderr: '' };
|
|
129
|
+
}
|
|
130
|
+
return { code: 2, stdout: '', stderr: 'unknown' };
|
|
131
|
+
},
|
|
132
|
+
sleep: async (ms) => { clock += ms; },
|
|
133
|
+
now: () => clock,
|
|
134
|
+
out: (line) => { lines.push(line); },
|
|
135
|
+
dir,
|
|
136
|
+
pid: 4242,
|
|
137
|
+
isAlive: () => false,
|
|
138
|
+
...over,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function opts(over = {}) {
|
|
142
|
+
return {
|
|
143
|
+
apiBase: API, bearer: OWNER_SESSION, resource: RESOURCE, name: 'proappstore-remote',
|
|
144
|
+
agent: { id: 'codex', label: 'Codex' }, machine: { id: 'mac-42', label: 'Remote Mac' }, relay: true, clientVersion: '0.0.0-test',
|
|
145
|
+
...over,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const stored = async () => JSON.parse(await readFile(join(dir, 'proappstore-remote.json'), 'utf8'));
|
|
149
|
+
const attemptFile = () => readFile(join(dir, 'proappstore-remote.attempt.json'), 'utf8').then((s) => JSON.parse(s), () => null);
|
|
150
|
+
async function expectCode(p, code) {
|
|
151
|
+
const e = await p.then(() => null, (err) => err);
|
|
152
|
+
expect(e).toBeInstanceOf(RemoteAuthError);
|
|
153
|
+
expect(e.code).toBe(code);
|
|
154
|
+
return e;
|
|
155
|
+
}
|
|
156
|
+
beforeEach(async () => {
|
|
157
|
+
dir = await mkdtemp(join(tmpdir(), 'pas-mcp-auth-'));
|
|
158
|
+
clock = 1_800_000_000_000;
|
|
159
|
+
lines = [];
|
|
160
|
+
requests = new Map();
|
|
161
|
+
creates = 0;
|
|
162
|
+
relays = [];
|
|
163
|
+
states = [];
|
|
164
|
+
pagsVersion = '0.4.121';
|
|
165
|
+
relayExit = [];
|
|
166
|
+
failNetwork = null;
|
|
167
|
+
polls = 0;
|
|
168
|
+
mcpUp = true;
|
|
169
|
+
// The phone approves on each request's second poll.
|
|
170
|
+
const perRequest = new Map();
|
|
171
|
+
onPoll = async (r) => {
|
|
172
|
+
const n = (perRequest.get(r.id) ?? 0) + 1;
|
|
173
|
+
perRequest.set(r.id, n);
|
|
174
|
+
if (n === 2)
|
|
175
|
+
await approve(r);
|
|
176
|
+
};
|
|
177
|
+
});
|
|
178
|
+
afterEach(async () => { await rm(dir, { recursive: true, force: true }); });
|
|
179
|
+
describe('the phone-approved happy path (#356)', () => {
|
|
180
|
+
it('relays, waits, redeems, proves the credential with an MCP read, installs it 0600, then reports connected', async () => {
|
|
181
|
+
const result = await connect(deps(), opts());
|
|
182
|
+
const r = requests.get(result.requestId);
|
|
183
|
+
expect(r.status).toBe('connected');
|
|
184
|
+
expect(r.seen).toBe(true);
|
|
185
|
+
const cred = await stored();
|
|
186
|
+
expect(cred).toMatchObject({ resource: RESOURCE, token_type: 'Bearer', access_token: r.token });
|
|
187
|
+
expect((await stat(join(dir, 'proappstore-remote.json'))).mode & 0o777).toBe(0o600);
|
|
188
|
+
expect((await stat(dir)).mode & 0o777).toBe(0o700);
|
|
189
|
+
expect(await attemptFile()).toBeNull();
|
|
190
|
+
// The relay carried only the documented public fields; the page saw every state, connected last.
|
|
191
|
+
expect(Object.keys(relays[0].parsed).sort()).toEqual(['agent', 'approval_url', 'expires_at', 'machine', 'request_id', 'resource', 'scopes']);
|
|
192
|
+
expect(states.map(([, s]) => s)).toEqual(['approved_awaiting_machine', 'consumed', 'connected']);
|
|
193
|
+
expect(lines.join('\n')).toContain(`${API}/v1/mcp/broker/v2/requests/${result.requestId}/approve`);
|
|
194
|
+
});
|
|
195
|
+
it('never puts a secret on stdout, in the relay, in a URL or in an error', async () => {
|
|
196
|
+
const leaks = [];
|
|
197
|
+
let secrets = [];
|
|
198
|
+
const watched = deps({
|
|
199
|
+
fetch: async (input, init) => {
|
|
200
|
+
const body = init?.body ? JSON.parse(String(init.body)) : {};
|
|
201
|
+
if (body.machine_proof)
|
|
202
|
+
secrets.push(String(body.machine_proof), String(body.code_verifier ?? ''));
|
|
203
|
+
leaks.push(String(input));
|
|
204
|
+
return fakeFetch(input, init);
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
const result = await connect(watched, opts());
|
|
208
|
+
secrets = [...secrets.filter(Boolean), requests.get(result.requestId).token];
|
|
209
|
+
const attempt = await connect(deps(), opts({ bearer: null })).catch((e) => e.message);
|
|
210
|
+
const observable = [lines.join('\n'), relays.map((x) => x.input).join('\n'), states.flat().join(' '), leaks.join('\n'), String(attempt)].join('\n');
|
|
211
|
+
for (const s of secrets)
|
|
212
|
+
expect(observable).not.toContain(s);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
describe('the owner says no, or nobody answers', () => {
|
|
216
|
+
it.each([['denied'], ['cancelled']])('%s at ProAppStore: a readable error, the page told, nothing installed', async (status) => {
|
|
217
|
+
onPoll = (r) => { r.status = status; };
|
|
218
|
+
const e = await expectCode(connect(deps(), opts()), status);
|
|
219
|
+
expect(e.message).toMatch(/Nothing changed on this machine/);
|
|
220
|
+
expect(states.at(-1)[1]).toBe(status);
|
|
221
|
+
await expect(stored()).rejects.toThrow();
|
|
222
|
+
expect(await attemptFile()).toBeNull();
|
|
223
|
+
});
|
|
224
|
+
it('expires when nobody approves before the deadline', async () => {
|
|
225
|
+
onPoll = () => undefined;
|
|
226
|
+
await expectCode(connect(deps(), opts()), 'expired');
|
|
227
|
+
expect(states.at(-1)[1]).toBe('expired');
|
|
228
|
+
expect(await attemptFile()).toBeNull();
|
|
229
|
+
});
|
|
230
|
+
it('wrong owner: a different account cannot approve this machine, so it never connects', async () => {
|
|
231
|
+
onPoll = async (r) => { expect(await approve(r, OTHER_SESSION)).toBe(false); };
|
|
232
|
+
await expectCode(connect(deps(), opts()), 'expired');
|
|
233
|
+
await expect(stored()).rejects.toThrow();
|
|
234
|
+
});
|
|
235
|
+
it('no PAS session on this machine: a clear error before any request is made', async () => {
|
|
236
|
+
const e = await expectCode(connect(deps(), opts({ bearer: null })), 'not_signed_in');
|
|
237
|
+
expect(e.message).toMatch(/pas login/);
|
|
238
|
+
expect(creates).toBe(0);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
describe('wrong machine, wrong request, double redemption', () => {
|
|
242
|
+
async function plantAttempt(over) {
|
|
243
|
+
const secrets = await generateMachineSecrets();
|
|
244
|
+
await mkdir(dir, { recursive: true });
|
|
245
|
+
await writeFile(join(dir, 'proappstore-remote.attempt.json'), JSON.stringify({
|
|
246
|
+
request_id: `req_${'A'.repeat(43)}`, resource: RESOURCE, approval_url: `${API}/x`, expires_at: clock + 60_000,
|
|
247
|
+
agent: { id: 'codex', label: 'Codex' }, machine: { id: 'mac-42', label: 'Remote Mac' }, rar_id: 'rar_x', reported: 'pending',
|
|
248
|
+
secrets, redeem_attempt_id: null, ...over,
|
|
249
|
+
}), { mode: 0o600 });
|
|
250
|
+
}
|
|
251
|
+
it('wrong machine: another machine\'s proof is refused with the generic answer, and the attempt is dropped', async () => {
|
|
252
|
+
const theirs = await connect(deps(), opts({ name: 'other-machine' }));
|
|
253
|
+
expect(requests.get(theirs.requestId).status).toBe('connected');
|
|
254
|
+
await plantAttempt({ request_id: theirs.requestId });
|
|
255
|
+
const e = await expectCode(connect(deps(), opts()), 'unavailable');
|
|
256
|
+
expect(e.message).toMatch(/belongs to another machine/);
|
|
257
|
+
expect(await attemptFile()).toBeNull();
|
|
258
|
+
});
|
|
259
|
+
it('wrong request: an unknown request id is refused the same way', async () => {
|
|
260
|
+
await plantAttempt({});
|
|
261
|
+
await expectCode(connect(deps(), opts()), 'unavailable');
|
|
262
|
+
});
|
|
263
|
+
it('a lost redeem answer is recovered with the same attempt id: one redemption, one credential', async () => {
|
|
264
|
+
// The first redeem reaches the broker and is consumed, but its answer is lost on the way back.
|
|
265
|
+
const realFetch = fakeFetch;
|
|
266
|
+
let lostOnce = false;
|
|
267
|
+
const result = await connect(deps({
|
|
268
|
+
fetch: async (input, init) => {
|
|
269
|
+
if (String(input).endsWith('/requests/redeem') && !lostOnce) {
|
|
270
|
+
lostOnce = true;
|
|
271
|
+
await realFetch(input, init);
|
|
272
|
+
throw new TypeError('fetch failed');
|
|
273
|
+
}
|
|
274
|
+
return realFetch(input, init);
|
|
275
|
+
},
|
|
276
|
+
}), opts());
|
|
277
|
+
const r = requests.get(result.requestId);
|
|
278
|
+
expect(lostOnce).toBe(true);
|
|
279
|
+
expect(r.status).toBe('connected');
|
|
280
|
+
expect((await stored()).access_token).toBe(r.token);
|
|
281
|
+
});
|
|
282
|
+
it('a second machine redeeming with a different attempt id is refused (double redemption)', async () => {
|
|
283
|
+
const result = await connect(deps(), opts());
|
|
284
|
+
const r = requests.get(result.requestId);
|
|
285
|
+
r.status = 'consumed'; // as if a replay arrived right after redemption
|
|
286
|
+
const res = await fakeFetch(`${API}/v1/mcp/broker/v2/requests/redeem`, { method: 'POST', body: JSON.stringify({ request_id: r.id, machine_proof: 'x'.repeat(43), code_verifier: 'y'.repeat(43), redeem_attempt_id: 'z'.repeat(43) }) });
|
|
287
|
+
expect(res.status).toBe(409);
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
describe('one attempt at a time; restarts resume', () => {
|
|
291
|
+
it('a live lock refuses a concurrent start; a dead process\'s lock is taken over', async () => {
|
|
292
|
+
await mkdir(dir, { recursive: true });
|
|
293
|
+
await writeFile(join(dir, 'proappstore-remote.lock'), JSON.stringify({ pid: 99, started: clock }));
|
|
294
|
+
const e = await expectCode(connect(deps({ isAlive: () => true }), opts()), 'busy');
|
|
295
|
+
expect(e.message).toMatch(/already running \(process 99\)/);
|
|
296
|
+
expect(creates).toBe(0);
|
|
297
|
+
await connect(deps({ isAlive: () => false }), opts());
|
|
298
|
+
expect(creates).toBe(1);
|
|
299
|
+
});
|
|
300
|
+
it('a machine that goes offline and comes back resumes the same request: no second request, no second push', async () => {
|
|
301
|
+
onPoll = () => undefined;
|
|
302
|
+
failNetwork = { path: '/requests/poll', times: 1_000 };
|
|
303
|
+
await expectCode(connect(deps(), opts()), 'network');
|
|
304
|
+
expect(await attemptFile()).not.toBeNull();
|
|
305
|
+
// Back online, the owner approves.
|
|
306
|
+
failNetwork = null;
|
|
307
|
+
onPoll = async (r, n) => { if (n === 1)
|
|
308
|
+
await approve(r); };
|
|
309
|
+
const result = await connect(deps(), opts());
|
|
310
|
+
expect(result.resumed).toBe(true);
|
|
311
|
+
expect(creates).toBe(1);
|
|
312
|
+
expect(relays).toHaveLength(1);
|
|
313
|
+
expect(requests.get(result.requestId).status).toBe('connected');
|
|
314
|
+
});
|
|
315
|
+
it('a brief network loss while waiting is retried with backoff, not fatal', async () => {
|
|
316
|
+
failNetwork = { path: '/requests/poll', times: 3 };
|
|
317
|
+
onPoll = async (r) => { await approve(r); };
|
|
318
|
+
const sleeps = [];
|
|
319
|
+
await connect(deps({ sleep: async (ms) => { sleeps.push(ms); clock += ms; } }), opts());
|
|
320
|
+
expect(sleeps.slice(0, 4)).toEqual([2000, 4000, 8000, 16000]);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
describe('the previous connection survives until the new one works', () => {
|
|
324
|
+
it('a credential that fails its MCP read is not installed, the old one is kept, and the broker is told "failed"', async () => {
|
|
325
|
+
await connect(deps(), opts());
|
|
326
|
+
const before = await stored();
|
|
327
|
+
mcpUp = false;
|
|
328
|
+
const e = await expectCode(connect(deps(), opts()), 'health_check_failed');
|
|
329
|
+
expect(e.message).toMatch(/previous connection is unchanged/);
|
|
330
|
+
expect(await stored()).toEqual(before);
|
|
331
|
+
expect([...requests.values()].at(-1).status).toBe('failed');
|
|
332
|
+
expect(states.at(-1)[1]).toBe('failed');
|
|
333
|
+
});
|
|
334
|
+
it('a successful reconnect replaces the credential', async () => {
|
|
335
|
+
await connect(deps(), opts());
|
|
336
|
+
const before = await stored();
|
|
337
|
+
await connect(deps(), opts());
|
|
338
|
+
expect((await stored()).access_token).not.toBe(before.access_token);
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
describe('the ProAgentStore CLI', () => {
|
|
342
|
+
it('older than 0.4.121 is refused with an update message; a missing one says how to proceed', async () => {
|
|
343
|
+
pagsVersion = '0.4.120';
|
|
344
|
+
expect((await expectCode(connect(deps(), opts()), 'old_cli')).message).toMatch(/0\.4\.121/);
|
|
345
|
+
pagsVersion = null;
|
|
346
|
+
expect((await expectCode(connect(deps(), opts()), 'pags_missing')).message).toMatch(/--no-relay/);
|
|
347
|
+
expect(creates).toBe(0);
|
|
348
|
+
});
|
|
349
|
+
it('--no-relay works without pags: the approval link is printed, nothing is relayed', async () => {
|
|
350
|
+
pagsVersion = null;
|
|
351
|
+
await connect(deps(), opts({ relay: false }));
|
|
352
|
+
expect(relays).toHaveLength(0);
|
|
353
|
+
expect(lines.some((l) => l.includes('/approve'))).toBe(true);
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
describe('the broker\'s envelope (contract)', () => {
|
|
357
|
+
it('opens exactly what the broker\'s own seal produces, and nothing sealed for another request', async () => {
|
|
358
|
+
const secrets = await generateMachineSecrets();
|
|
359
|
+
const sealed = await seal(secrets.publicKeySpki, { access_token: 't', token_type: 'Bearer', resource: RESOURCE, expires_in: 60 }, 'req_one');
|
|
360
|
+
const envelope = { iv: sealed.iv, ...JSON.parse(sealed.ciphertext) };
|
|
361
|
+
expect(await openEnvelope(envelope, secrets.privateKeyPkcs8, 'req_one')).toEqual({ access_token: 't', token_type: 'Bearer', resource: RESOURCE, expires_in: 60 });
|
|
362
|
+
await expect(openEnvelope(envelope, secrets.privateKeyPkcs8, 'req_two')).rejects.toThrow();
|
|
363
|
+
const other = await generateMachineSecrets();
|
|
364
|
+
await expect(openEnvelope(envelope, other.privateKeyPkcs8, 'req_one')).rejects.toThrow();
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
//# sourceMappingURL=mcp-remote-auth.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-remote-auth.test.js","sourceRoot":"","sources":["../src/mcp-remote-auth.test.ts"],"names":[],"mappings":"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"}
|