hololake-system-architecture/product-source/hololake-native-desktop/scripts/release-broadcast-server.test.mjs

184 lines
8.6 KiB
JavaScript
Raw Normal View History

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/hololake/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)
assert.equal((await fetch(`${base}/hololake/releases/latest.json`)).status, 204)
const publicHealth = await fetch(`${base}/hololake/releases/health`)
assert.equal(publicHealth.status, 200)
assert.equal((await publicHealth.json()).releaseEndpointPath, '/hololake/releases/latest.json')
})
})
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 publicLatest = await fetch(`${base}/hololake/releases/latest.json`)
assert.equal(publicLatest.status, 200)
assert.equal((await publicLatest.json()).releaseId, 'GH-HOLOLAKE-RELEASE-0.2.0')
const updater = await fetch(`${base}/hololake/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)
})
test('a package outside the registered public prefix locks the release', () => {
const fixture = buildReleaseRoot()
const latestPath = path.join(fixture.root, 'releases', '0.2.0', 'latest.json')
const latest = JSON.parse(fs.readFileSync(latestPath, 'utf8'))
latest.platforms['darwin-aarch64'].url = 'https://release.guanghu.test/releases/0.2.0/HoloLake.app.tar.gz'
writeJson(latestPath, latest)
const broadcastSha256 = sha256(fs.readFileSync(latestPath))
const pipelinePath = path.join(fixture.root, 'releases', '0.2.0', 'pipeline-receipt.json')
const pipeline = JSON.parse(fs.readFileSync(pipelinePath, 'utf8'))
pipeline.broadcastSha256 = broadcastSha256
writeJson(pipelinePath, pipeline)
const approvalPath = path.join(fixture.root, 'releases', '0.2.0', 'human-approval.json')
const approval = JSON.parse(fs.readFileSync(approvalPath, 'utf8'))
approval.broadcastSha256 = broadcastSha256
writeJson(approvalPath, approval)
const activationPath = path.join(fixture.root, 'ACTIVE.json')
const activation = JSON.parse(fs.readFileSync(activationPath, 'utf8'))
activation.broadcastSha256 = broadcastSha256
writeJson(activationPath, activation)
const state = loadRuntimeState(fixture.root)
assert.equal(state.state, 'LOCKED_INVALID_RELEASE_EVIDENCE')
assert.equal(state.reasonCode, 'HOLOLAKE_RELEASE_PACKAGE_PUBLIC_PREFIX_MISMATCH')
})