/** * Audit P0-1 (2026-10-27): with TOTP enabled, totpAuthMiddleware answered 401 * BEFORE jwtApiKeyAuthMiddleware ever ran, so machine credentials (dk_ API * keys, JWTs) were dead on every TOTP-protected install — live-verified with * a freshly minted key getting 401 on /api/v1/mcp/info. The route-level tests * missed it because they inject req.auth directly instead of exercising the * real chain. * * This suite boots the REAL configureMiddleware chain (both auth gates in * registration order) and drives synthetic requests through it — the test the * codebase was missing. No req.auth injection anywhere. */ 'use strict'; const express = require('express'); const request = require('supertest'); const crypto = require('crypto'); const configureMiddleware = require('../../src/utilities/middleware'); const KEY = Buffer.alloc(32, 7); function makeDeps() { return { siteConfig: { dashboardHost: 'status.sami', tld: '.sami' }, totpConfig: { enabled: true, sessionDuration: '24h' }, tailscaleConfig: { enabled: false, requireAuth: false }, metrics: { recordRequest: jest.fn() }, auditLogger: { middleware: () => (_req, _res, next) => next() }, authManager: { verifyJWT: jest.fn(async (token) => token === 'good.jwt' ? { userId: 'u1', scope: ['read'] } : null), verifyAPIKey: jest.fn(async (key) => key === 'dk_goodkey' ? { keyId: 'k1', name: 'test-key', scopes: ['read', 'write'] } : null), }, log: { debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() }, cryptoUtils: { loadOrCreateKey: () => KEY }, isValidContainerId: () => true, isTailscaleIP: () => false, getTailscaleStatus: async () => null, }; } // Mint a session cookie exactly the way setSessionCookie does, so the // session path of the chain is exercised with real HMAC math too. function mintSessionCookie() { const payload = { v: true, exp: Date.now() + 86400000 }; const payloadB64 = Buffer.from(JSON.stringify(payload)).toString('base64url'); const sig = crypto.createHmac('sha256', KEY).update(payloadB64).digest('base64url'); return `dashcaddy_session=${payloadB64}.${sig}`; } function buildApp() { const app = express(); configureMiddleware(app, makeDeps()); // Probe route registered AFTER the middleware chain, like a real mount. // NOT in PUBLIC_ROUTES — it must go through the full chain. app.get('/api/v1/mcp/info', (req, res) => res.json({ ok: true, auth: req.auth })); return app; } describe('middleware chain: machine credentials pass the TOTP gate (audit P0-1)', () => { test('valid x-api-key reaches the route when TOTP is enabled', async () => { const res = await request(buildApp()) .get('/api/v1/mcp/info') .set('x-api-key', 'dk_goodkey'); expect(res.status).toBe(200); expect(res.body.ok).toBe(true); expect(res.body.auth).toMatchObject({ type: 'apikey', keyId: 'k1', name: 'test-key' }); }); test('valid Bearer JWT reaches the route when TOTP is enabled', async () => { const res = await request(buildApp()) .get('/api/v1/mcp/info') .set('Authorization', 'Bearer good.jwt'); expect(res.status).toBe(200); expect(res.body.auth).toMatchObject({ type: 'jwt', userId: 'u1' }); }); test('INVALID api key is still rejected with requiresTotp', async () => { const res = await request(buildApp()) .get('/api/v1/mcp/info') .set('x-api-key', 'dk_wrong'); expect(res.status).toBe(401); expect(res.body.error).toContain('DC-110'); expect(res.body.requiresTotp).toBe(true); }); test('no credentials at all is still rejected with requiresTotp', async () => { const res = await request(buildApp()).get('/api/v1/mcp/info'); expect(res.status).toBe(401); expect(res.body.requiresTotp).toBe(true); }); test('valid session cookie still authenticates (session path unchanged)', async () => { const res = await request(buildApp()) .get('/api/v1/mcp/info') .set('Cookie', mintSessionCookie()); expect(res.status).toBe(200); expect(res.body.auth).toMatchObject({ type: 'session', scope: ['admin'] }); }); });