auth-refresh-wiring.test.mjs
71 lines 3.3 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 2 days ago
1 /**
2 * Structural wiring tests — proves the self-hosted Hub actually mounts the persistent-session
3 * machinery (refresh-token rotation + HttpOnly cookie + real logout). These guard the
4 * integration points; the behavioral guarantees are covered by refresh-token-core,
5 * refresh-tokens-store, and auth-session test suites.
6 */
7
8 import { test, describe } from 'node:test';
9 import assert from 'node:assert/strict';
10 import fs from 'node:fs';
11 import path from 'node:path';
12 import { fileURLToPath } from 'node:url';
13
14 const __dirname = path.dirname(fileURLToPath(import.meta.url));
15 const ROOT = path.resolve(__dirname, '..');
16
17 describe('self-hosted Hub wires persistent sessions', () => {
18 let src;
19 const load = () => {
20 if (!src) src = fs.readFileSync(path.join(ROOT, 'hub/server.mjs'), 'utf8');
21 return src;
22 };
23
24 test('imports cookie-parser and registers it as middleware', () => {
25 const s = load();
26 assert.ok(s.includes("import cookieParser from 'cookie-parser'"), 'must import cookie-parser');
27 assert.ok(s.includes('app.use(cookieParser())'), 'must register cookieParser middleware');
28 });
29
30 test('imports the refresh-token store and auth-session helpers', () => {
31 const s = load();
32 assert.ok(s.includes("from './refresh-tokens.mjs'"), 'must import the refresh-token store');
33 assert.ok(s.includes("from './auth-session.mjs'"), 'must import auth-session helpers');
34 });
35
36 test('mounts POST /api/v1/auth/refresh and /api/v1/auth/logout', () => {
37 const s = load();
38 assert.ok(/app\.post\(\s*'\/api\/v1\/auth\/refresh'/.test(s), 'must mount POST /auth/refresh');
39 assert.ok(/app\.post\(\s*'\/api\/v1\/auth\/logout'/.test(s), 'must mount POST /auth/logout');
40 });
41
42 test('refresh route uses createRefreshHandler with the refresh store', () => {
43 const s = load();
44 const block = s.slice(s.indexOf("'/api/v1/auth/refresh'"), s.indexOf("'/api/v1/auth/refresh'") + 400);
45 assert.ok(block.includes('createRefreshHandler'), 'refresh route must use createRefreshHandler');
46 assert.ok(block.includes('issueAccessToken'), 'refresh route must supply an access-token signer');
47 });
48
49 test('OAuth callback issues a refresh cookie', () => {
50 const s = load();
51 const block = s.slice(s.indexOf('function handleAuthCallback'));
52 const end = block.indexOf('\n}\n');
53 const body = block.slice(0, end > 0 ? end : 1200);
54 assert.ok(body.includes('issueRefreshCookie'), 'login callback must issue a refresh cookie');
55 });
56
57 test('refresh cookie policy is HttpOnly and path-scoped to the auth endpoints', () => {
58 const s = load();
59 assert.ok(s.includes('refreshCookieOptions'), 'must use refreshCookieOptions for the policy');
60 // The policy helper centralizes HttpOnly; assert the auth-session module enforces it.
61 const sess = fs.readFileSync(path.join(ROOT, 'hub/auth-session.mjs'), 'utf8');
62 assert.ok(sess.includes('httpOnly: true'), 'refresh cookie must be HttpOnly');
63 assert.ok(sess.includes("REFRESH_COOKIE_PATH = '/api/v1/auth'"), 'cookie must be scoped to /api/v1/auth');
64 });
65
66 test('logout uses createLogoutHandler (server-side revocation)', () => {
67 const s = load();
68 const block = s.slice(s.indexOf("'/api/v1/auth/logout'"), s.indexOf("'/api/v1/auth/logout'") + 300);
69 assert.ok(block.includes('createLogoutHandler'), 'logout must use createLogoutHandler');
70 });
71 });
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 2 days ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 2 days ago