'use strict'; const assert = require('node:assert/strict'); const crypto = require('node:crypto'); const test = require('node:test'); const { createCompanionWorkerService } = require('../../src/services/companion-worker-service'); function fixture() { const values = new Map(); const secretValues = new Map(); const settings = { get: (key, fallback) => values.has(key) ? values.get(key) : fallback, set: (key, value) => values.set(key, value) }; const secrets = { has: key => secretValues.has(key), get: key => secretValues.get(key) || '', set: (key, value) => value ? secretValues.set(key, value) : secretValues.delete(key) }; return { settings, secrets, secretValues }; } test('companion workers require HTTPS and never accept shell or arbitrary path jobs', () => { const f = fixture(); const service = createCompanionWorkerService(f); assert.throws(() => service.save({ id: 'win-one', endpoint: 'http://worker.local:9443' }), /HTTPS/); service.save({ id: 'win-one', endpoint: 'https://worker.local:9443' }); const pairing = service.pair('win-one'); assert.equal(pairing.shownOnce, true); assert.equal(pairing.pairingKey.length, 64); const key = Buffer.from(pairing.pairingKey, 'hex'); assert.throws(() => service.signedJob(key, 'win-one', { type: 'shell', artifactId: 'game:1', outputSlot: 'exports' }), /workertype/); assert.throws(() => service.signedJob(key, 'win-one', { type: 'exfat', artifactId: '../../etc', outputSlot: 'exports' }), /uitsluitend/); const job = service.signedJob(key, 'win-one', { type: 'exfat', artifactId: 'game:1', outputSlot: 'exports' }); assert.equal(job.job.type, 'exfat'); assert.equal(Object.prototype.hasOwnProperty.call(job.job, 'path'), false); assert.equal(Object.prototype.hasOwnProperty.call(job.job, 'command'), false); }); test('capability response must be nonce-bound, HMAC-authenticated and allowlisted', async () => { const f = fixture(); let key; const fetchImpl = async (_url, options) => { const nonce = options.headers['X-Chimera-Nonce']; const payload = Buffer.from(JSON.stringify({ version: '1.0.0', capabilities: ['exfat', 'shell'], slots: ['exports', '../../bad'], limits: { maxInputBytes: 123 } })).toString('base64'); const transcript = `capabilities|win-one|${nonce}|${payload}`; return { ok: true, json: async () => ({ schema: 1, workerId: 'win-one', nonce, payload, hmac: crypto.createHmac('sha256', key).update(transcript).digest('hex') }) }; }; const service = createCompanionWorkerService({ ...f, fetchImpl }); service.save({ id: 'win-one', endpoint: 'https://worker.local:9443' }); key = Buffer.from(service.pair('win-one').pairingKey, 'hex'); const result = await service.capabilities('win-one'); assert.deepEqual(result.capabilities, ['exfat']); assert.deepEqual(result.slots, ['exports']); assert.equal(result.shell, false); assert.equal(result.arbitraryPaths, false); });