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);
});