import test from 'node:test'; import assert from 'node:assert/strict'; import { createHash } from 'node:crypto'; import { REQUEST_ROUTE, requestHTTP } from '../src/request-http.mjs'; test('owner downloads the exact authorized bytes as a private inert attachment', async () => { const path = '/api/requests/r1/artifact/d1'; assert.match(path, REQUEST_ROUTE); const bytes = Buffer.from('Timer'); const hash = createHash('sha256').update(bytes).digest('hex'); const session = { name: 'owner', provider: 'test', iss: 'test', sub: 'owner' }; const req = { method: 'GET', headersDistinct: { 'sec-fetch-site': ['same-origin'] } }; const res = { writeHead(status, headers) { this.status = status; this.headers = headers; }, end(data) { this.data = data; } }; const calls = []; await requestHTTP(req, res, { path, session, live: () => session, origin: 'https://console.test', log() {}, requestWrite: null, requestRead: async (verb, args) => { calls.push({ verb, args }); return verb === 'request.get.console' ? { version: 1, request: 'r1', revision: 1, phase: 'complete', delivery: 'd1' } : { mime: 'text/html', filename: 'timer.html', base64: bytes.toString('base64'), sha256: hash }; } }); assert.equal(res.status, 200); assert.deepEqual(res.data, bytes); assert.match(res.headers['content-disposition'], /^attachment/); assert.equal(res.headers['x-content-type-options'], 'nosniff'); assert.match(res.headers['cache-control'], /private/); assert.match(res.headers['cache-control'], /no-store/); assert.deepEqual(calls.map(c => c.verb), ['request.get.console', 'request.artifact.console']); }); test('artifact access refuses foreign ownership, tampered bytes and expired sessions', async () => { const path = '/api/requests/r1/artifact/d1', session = { name: 'owner', provider: 'test', iss: 'test', sub: 'owner' }; const req = { method: 'GET', headersDistinct: { 'sec-fetch-site': ['same-origin'] } }; const attempt = async (read, live = () => session) => { const res = { writeHead(status, headers) { this.status = status; this.headers = headers; }, end(data) { this.data = data; } }; await requestHTTP(req, res, { path, session, live, origin: 'https://console.test', log() {}, requestWrite: null, requestRead: read }); return res; }; const state = { version: 1, request: 'r1', revision: 1, phase: 'complete', delivery: 'd1' }; assert.equal((await attempt(async () => ({ ...state, delivery: 'someone-else' }))).status, 404); assert.equal((await attempt(async verb => verb === 'request.get.console' ? state : { mime: 'text/html', filename: 'timer.html', base64: 'eA==', sha256: '0'.repeat(64) })).status, 503); assert.equal((await attempt(async () => state, () => null)).status, 401); }); test('text view is inert and uses the same current delivery and digest checks', async () => { const path = '/api/requests/r1/artifact/d1/text'; assert.match(path, REQUEST_ROUTE); const bytes = Buffer.from(''); const session = { name: 'owner', provider: 'test', iss: 'test', sub: 'owner' }; const req = { method: 'GET', headersDistinct: { 'sec-fetch-site': ['same-origin'] } }; const state = { version: 1, request: 'r1', revision: 1, phase: 'complete', delivery: 'd1' }; const artifact = { mime: 'text/html', filename: 'timer.html', base64: bytes.toString('base64'), sha256: createHash('sha256').update(bytes).digest('hex') }; const attempt = async (read, live = () => session) => { const res = { writeHead(status, headers) { this.status = status; this.headers = headers; }, end(data) { this.data = data; } }; await requestHTTP(req, res, { path, session, live, origin: 'https://console.test', log() {}, requestRead: read }); return res; }; const good = await attempt(async verb => verb === 'request.get.console' ? state : artifact); assert.equal(good.status, 200); assert.deepEqual(good.data, bytes); assert.equal(good.headers['content-type'], 'text/plain; charset=utf-8'); assert.equal(good.headers['x-content-type-options'], 'nosniff'); assert.equal(good.headers['content-security-policy'], "sandbox; default-src 'none'"); assert.equal(good.headers['cache-control'], 'private, no-store'); assert.equal((await attempt(async verb => verb === 'request.get.console' ? { ...state, delivery: 'd2' } : artifact)).status, 404); assert.equal((await attempt(async verb => verb === 'request.get.console' ? state : { ...artifact, sha256: '0'.repeat(64) })).status, 503); let reads = 0; assert.equal((await attempt(async verb => { reads++; return verb === 'request.get.console' ? state : artifact; }, () => reads < 2 ? session : null)).status, 401); assert.doesNotMatch('/api/requests/r1/artifact/d1/text/extra', REQUEST_ROUTE); assert.doesNotMatch('/api/requests/r1/artifact/d1/html', REQUEST_ROUTE); });