phase8-p1b-airgapped-walkthrough.test.mjs
96 lines 3.4 KB
Raw
sha256:b5f647cb9c409f563d4671fe3fc05ddea01fabfed9b41fc11cb923588e1c1baf mirror: GitHub Phase A durable MCP OAuth (#270) Human minor ⚠ breaking 10 days ago
1 /**
2 * Phase 8 P1b — e2e tier: air-gapped walkthrough, zero OAuth egress (§9).
3 */
4
5 import { describe, test, before, after } from 'node:test';
6 import assert from 'node:assert/strict';
7 import {
8 makeTempDataDir,
9 enableOfflineLockedTestEnv,
10 createLocalAuthTestApp,
11 TEST_PASSPHRASE,
12 TEST_SECRET,
13 } from '../helpers/phase8-p1b-local-auth-harness.mjs';
14 import { generateSetupToken } from '../../hub/lib/local-auth-bootstrap.mjs';
15 import { issueCliLocalToken } from '../../hub/lib/local-auth.mjs';
16
17 describe('phase8-p1b airgapped walkthrough (e2e)', () => {
18 /** @type {{ dataDir: string, cleanup: () => void }} */
19 let tmp;
20 /** @type {{ baseUrl: string, close: () => Promise<void> } | null} */
21 let hub = null;
22 /** @type {typeof globalThis.fetch} */
23 let originalFetch;
24
25 before(async () => {
26 tmp = await makeTempDataDir();
27 enableOfflineLockedTestEnv(tmp.dataDir);
28 originalFetch = globalThis.fetch;
29 globalThis.fetch = async (input, init) => {
30 const url = typeof input === 'string' ? input : input.url;
31 const host = new URL(url, 'http://localhost').hostname;
32 if (host !== '127.0.0.1' && host !== 'localhost') {
33 throw new Error(`Egress blocked in air-gapped test: ${url}`);
34 }
35 if (url.includes('accounts.google.com') || url.includes('github.com')) {
36 throw new Error(`OAuth provider egress blocked: ${url}`);
37 }
38 return originalFetch(input, init);
39 };
40 hub = await createLocalAuthTestApp(tmp.dataDir);
41 });
42
43 after(async () => {
44 if (hub) await hub.close();
45 globalThis.fetch = originalFetch;
46 tmp.cleanup();
47 delete process.env.KNOWTATION_OFFLINE_LOCKED_AUTH;
48 delete process.env.KNOWTATION_OFFLINE_LOCKED_AUTH_TEST_SHIPPED;
49 });
50
51 test('gate on, not bootstrapped → 503', async () => {
52 const res = await fetch(`${hub.baseUrl}/api/v1/auth/local/login`, {
53 method: 'POST',
54 headers: { 'Content-Type': 'application/json' },
55 body: JSON.stringify({ username: 'admin', passphrase: TEST_PASSPHRASE }),
56 });
57 assert.equal(res.status, 503);
58 assert.equal((await res.json()).code, 'OFFLINE_LOCKED_NOT_BOOTSTRAPPED');
59 });
60
61 test('setup token → bootstrap → login → CLI token → bearer session', async () => {
62 const { token: setupToken } = generateSetupToken(tmp.dataDir, 'admin', '15m');
63 const bootRes = await fetch(`${hub.baseUrl}/api/v1/auth/local/bootstrap`, {
64 method: 'POST',
65 headers: { 'Content-Type': 'application/json' },
66 body: JSON.stringify({
67 setupToken,
68 username: 'admin',
69 passphrase: TEST_PASSPHRASE,
70 }),
71 });
72 assert.equal(bootRes.status, 200);
73 const bootBody = await bootRes.json();
74 assert.equal(bootBody.userId, 'admin_001');
75
76 const loginRes = await fetch(`${hub.baseUrl}/api/v1/auth/local/login`, {
77 method: 'POST',
78 headers: { 'Content-Type': 'application/json' },
79 body: JSON.stringify({ username: 'admin', passphrase: TEST_PASSPHRASE }),
80 });
81 assert.equal(loginRes.status, 200);
82 const { token } = await loginRes.json();
83
84 const cliResult = await issueCliLocalToken(tmp.dataDir, 'admin', TEST_PASSPHRASE, {
85 sessionSecret: TEST_SECRET,
86 offlineLockedActive: true,
87 });
88 assert.equal(cliResult.ok, true);
89
90 const sessionRes = await fetch(`${hub.baseUrl}/api/v1/auth/session`, {
91 headers: { Authorization: `Bearer ${token}` },
92 });
93 assert.equal(sessionRes.status, 200);
94 assert.equal((await sessionRes.json()).provider, 'local');
95 });
96 });
File History 1 commit
sha256:b5f647cb9c409f563d4671fe3fc05ddea01fabfed9b41fc11cb923588e1c1baf mirror: GitHub Phase A durable MCP OAuth (#270) Human minor 10 days ago