import assert from 'node:assert/strict' import crypto from 'node:crypto' import fs from 'node:fs' import os from 'node:os' import path from 'node:path' import test from 'node:test' import { createReleaseServer, isMainModule, loadRuntimeState } from '../server/release-broadcast/server.mjs' const sha256 = (bytes) => crypto.createHash('sha256').update(bytes).digest('hex') const writeJson = (file, value) => fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 }) async function withServer(state, callback) { const server = createReleaseServer(state) await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)) const address = server.address() try { return await callback(`http://127.0.0.1:${address.port}`) } finally { await new Promise((resolve, reject) => server.close((error) => error ? reject(error) : resolve())) } } function buildReleaseRoot() { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'hololake-release-broadcast-')) const releaseDirectory = path.join(root, 'releases', '0.2.0') fs.mkdirSync(releaseDirectory, { recursive: true }) const packageBytes = Buffer.from('signed-notarized-updater-placeholder') const packageName = 'HoloLake.app.tar.gz' fs.writeFileSync(path.join(releaseDirectory, packageName), packageBytes, { mode: 0o600 }) writeJson(path.join(releaseDirectory, 'HOLOLAKE-CODESIGN.json'), { schema: 'hololake.platform-code-signature-receipt/v1', state: 'DEVELOPER_ID_SIGNATURE_STRICT_AND_GATEKEEPER_ACCEPTED', sourceCommit: '1'.repeat(40), }) writeJson(path.join(releaseDirectory, 'HOLOLAKE-NOTARIZATION.json'), { schema: 'hololake.apple-notarization-receipt/v1', state: 'APPLE_NOTARIZATION_ACCEPTED_AND_STAPLED', sourceCommit: '1'.repeat(40), }) const broadcast = { schema: 'hololake.release-broadcast/v1', releaseId: 'GH-HOLOLAKE-RELEASE-0.2.0', version: '0.2.0', pub_date: '2026-08-13T10:00:00.000Z', notes: 'Signed release', platforms: { 'darwin-aarch64': { url: `https://release.guanghu.test/releases/0.2.0/${packageName}`, signature: 'trusted-updater-signature', size: packageBytes.length, sha256: sha256(packageBytes), platformCodeSignatureReceipt: 'HOLOLAKE-CODESIGN', notarizationReceipt: 'HOLOLAKE-NOTARIZATION', }, }, hololake: { features: ['Stage one'], fixes: [], compatibility: { minimumVersion: '0.1.0', dataMigrationRequired: false }, restart: { required: true, automaticAllowed: false }, rollback: { supported: true, healthReceiptRequired: true, previousVersion: '0.1.0' }, }, } const broadcastPath = path.join(releaseDirectory, 'latest.json') writeJson(broadcastPath, broadcast) const broadcastSha256 = sha256(fs.readFileSync(broadcastPath)) writeJson(path.join(releaseDirectory, 'pipeline-receipt.json'), { schema: 'hololake.signed-release-pipeline-receipt/v1', state: 'SIGNED_NOTARIZED_RELEASE_BROADCAST_READY_FOR_JD_CONTROLLER_UPLOAD', sourceCommit: '1'.repeat(40), broadcastSha256, automaticUpload: false, automaticActivation: false, }) writeJson(path.join(root, 'ACTIVE.json'), { schema: 'hololake.release-broadcast-activation/v1', state: 'HUMAN_APPROVED_SIGNED_NOTARIZED_RELEASE_ACTIVE', releaseId: broadcast.releaseId, version: broadcast.version, broadcastRelativePath: 'releases/0.2.0/latest.json', broadcastSha256, pipelineReceiptRelativePath: 'releases/0.2.0/pipeline-receipt.json', humanApprovalReceipt: 'GH-HUMAN-RELEASE-APPROVAL-001', humanApprovalReceiptRelativePath: 'releases/0.2.0/human-approval.json', }) writeJson(path.join(releaseDirectory, 'human-approval.json'), { schema: 'hololake.release-broadcast-human-approval/v1', state: 'HUMAN_APPROVED_EXACT_SIGNED_NOTARIZED_RELEASE', approvalId: 'GH-HUMAN-RELEASE-APPROVAL-001', releaseId: broadcast.releaseId, version: broadcast.version, broadcastSha256, }) return { root, packageBytes } } test('empty release root stays healthy but returns Tauri-compatible 204 no update', async () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'hololake-release-empty-')) const state = loadRuntimeState(root) assert.equal(state.state, 'EMPTY_FAIL_CLOSED') await withServer(state, async (base) => { const health = await fetch(`${base}/health`) assert.equal(health.status, 200) assert.deepEqual((await health.json()).upstreamUpdateSources, []) assert.equal((await fetch(`${base}/latest.json`)).status, 204) }) }) test('invalid activation locks the endpoint instead of falling back to an update', async () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'hololake-release-invalid-')) writeJson(path.join(root, 'ACTIVE.json'), { schema: 'wrong', state: 'ACTIVE' }) const state = loadRuntimeState(root) assert.equal(state.state, 'LOCKED_INVALID_RELEASE_EVIDENCE') await withServer(state, async (base) => { assert.equal((await fetch(`${base}/health`)).status, 503) assert.equal((await fetch(`${base}/latest.json`)).status, 503) }) }) test('only an exact human-approved signed notarized evidence chain becomes readable', async () => { const fixture = buildReleaseRoot() const state = loadRuntimeState(fixture.root) assert.equal(state.state, 'READY_SIGNED_NOTARIZED_BROADCAST') await withServer(state, async (base) => { const latest = await fetch(`${base}/latest.json`) assert.equal(latest.status, 200) assert.equal((await latest.json()).releaseId, 'GH-HOLOLAKE-RELEASE-0.2.0') const updater = await fetch(`${base}/releases/0.2.0/HoloLake.app.tar.gz`) assert.equal(updater.status, 200) assert.deepEqual(Buffer.from(await updater.arrayBuffer()), fixture.packageBytes) assert.equal((await fetch(`${base}/unknown`)).status, 404) }) }) test('package tampering after pipeline output locks the whole release at startup', () => { const fixture = buildReleaseRoot() fs.appendFileSync(path.join(fixture.root, 'releases', '0.2.0', 'HoloLake.app.tar.gz'), 'tampered') assert.equal(loadRuntimeState(fixture.root).state, 'LOCKED_INVALID_RELEASE_EVIDENCE') }) test('a symlinked immutable current directory is recognized as the intended executable', () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'hololake-release-symlink-')) const versionDirectory = path.join(root, 'immutable') fs.mkdirSync(versionDirectory) const source = fs.readFileSync(new URL('../server/release-broadcast/server.mjs', import.meta.url), 'utf8') const copy = path.join(versionDirectory, 'server.mjs') fs.writeFileSync(copy, source, { mode: 0o500 }) const current = path.join(root, 'current') fs.symlinkSync(versionDirectory, current) assert.equal(isMainModule(path.join(current, 'server.mjs'), new URL(`file://${copy}`)), true) })