feat(hololake): add explicit JD release activation operator

This commit is contained in:
冰朔 2026-08-13 18:54:04 +08:00
commit 4357d25ea8
5 changed files with 608 additions and 0 deletions

View file

@ -47,6 +47,10 @@ test('release activation remains explicitly human controlled', () => {
assert.equal(foundation.release_signed_notarized_pipeline_implemented, true)
assert.equal(foundation.release_broadcast_candidate_service_implemented, true)
assert.equal(foundation.release_broadcast_candidate_service_default_state, 'EMPTY_FAIL_CLOSED_LOOPBACK_ONLY')
assert.equal(foundation.release_broadcast_explicit_operator_activation_implemented, true)
assert.equal(foundation.release_broadcast_activation_requires_exact_human_approval, true)
assert.equal(foundation.release_broadcast_activation_requires_repeated_expected_facts, true)
assert.equal(foundation.release_broadcast_operator_automatic_restart_allowed, false)
assert.equal(foundation.release_pipeline_automatic_upload_allowed, false)
assert.equal(
foundation.release_production_activation_state,

View file

@ -0,0 +1,167 @@
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 { activateRelease, verifyReleaseBundle } from '../server/release-broadcast/operator.mjs'
import { 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 })
function buildOperatorFixture() {
const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'hololake-release-operator-fixture-'))
const source = path.join(fixtureRoot, 'source')
const approvals = path.join(fixtureRoot, 'approvals')
const stateRoot = path.join(fixtureRoot, 'state')
for (const directory of [source, approvals, stateRoot]) fs.mkdirSync(directory, { mode: 0o700 })
const packageName = 'HoloLake.app.tar.gz'
const packageBytes = Buffer.from('signed-notarized-updater-package')
const sourceCommit = '2'.repeat(40)
fs.writeFileSync(path.join(source, packageName), packageBytes, { mode: 0o600 })
writeJson(path.join(source, 'HOLOLAKE-CODESIGN.json'), {
schema: 'hololake.platform-code-signature-receipt/v1',
state: 'DEVELOPER_ID_SIGNATURE_STRICT_AND_GATEKEEPER_ACCEPTED',
sourceCommit,
})
writeJson(path.join(source, 'HOLOLAKE-NOTARIZATION.json'), {
schema: 'hololake.apple-notarization-receipt/v1',
state: 'APPLE_NOTARIZATION_ACCEPTED_AND_STAPLED',
sourceCommit,
})
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://guanghulab.com/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(source, 'latest.json')
writeJson(broadcastPath, broadcast)
const broadcastSha256 = sha256(fs.readFileSync(broadcastPath))
writeJson(path.join(source, 'pipeline-receipt.json'), {
schema: 'hololake.signed-release-pipeline-receipt/v1',
state: 'SIGNED_NOTARIZED_RELEASE_BROADCAST_READY_FOR_JD_CONTROLLER_UPLOAD',
sourceCommit,
broadcastSha256,
automaticUpload: false,
automaticActivation: false,
})
const approval = path.join(approvals, 'approval.json')
writeJson(approval, {
schema: 'hololake.release-broadcast-human-approval/v1',
state: 'HUMAN_APPROVED_EXACT_SIGNED_NOTARIZED_RELEASE',
approvalId: 'GH-HUMAN-RELEASE-APPROVAL-002',
releaseId: broadcast.releaseId,
version: broadcast.version,
broadcastSha256,
})
return {
fixtureRoot,
source,
approval,
stateRoot,
expected: { releaseId: broadcast.releaseId, version: broadcast.version, sourceCommit, broadcastSha256 },
}
}
test('verify reconstructs and validates an exact private candidate without mutating state', () => {
const fixture = buildOperatorFixture()
try {
const result = verifyReleaseBundle(fixture.source, fixture.approval)
assert.equal(result.state, 'EXACT_SIGNED_NOTARIZED_HUMAN_APPROVED_BUNDLE_VERIFIED')
assert.equal(result.broadcastSha256, fixture.expected.broadcastSha256)
assert.equal(result.artifacts.some((artifact) => artifact.name === 'HoloLake.app.tar.gz'), true)
assert.deepEqual(fs.readdirSync(fixture.stateRoot), [])
} finally {
fs.rmSync(fixture.fixtureRoot, { recursive: true, force: true })
}
})
test('activation repeats expected facts, commits atomically, and still requires explicit restart', () => {
const fixture = buildOperatorFixture()
try {
const receipt = activateRelease({
sourceDirectory: fixture.source,
humanApprovalPath: fixture.approval,
stateRoot: fixture.stateRoot,
expected: fixture.expected,
enforceRootOwner: false,
})
assert.equal(receipt.state, 'ACTIVATED_EXPLICIT_SERVICE_RESTART_REQUIRED')
assert.equal(receipt.automaticUpload, false)
assert.equal(receipt.automaticActivation, false)
assert.equal(receipt.automaticRestart, false)
assert.equal(loadRuntimeState(fixture.stateRoot).state, 'READY_SIGNED_NOTARIZED_BROADCAST')
assert.equal(fs.existsSync(path.join(fixture.stateRoot, '.operator-lock')), false)
} finally {
fs.rmSync(fixture.fixtureRoot, { recursive: true, force: true })
}
})
test('expected-fact mismatch performs no activation or release staging', () => {
const fixture = buildOperatorFixture()
try {
assert.throws(() => activateRelease({
sourceDirectory: fixture.source,
humanApprovalPath: fixture.approval,
stateRoot: fixture.stateRoot,
expected: { ...fixture.expected, broadcastSha256: '3'.repeat(64) },
enforceRootOwner: false,
}), /HOLOLAKE_RELEASE_OPERATOR_EXPECTED_BROADCAST_SHA256_MISMATCH/)
assert.deepEqual(fs.readdirSync(fixture.stateRoot), [])
} finally {
fs.rmSync(fixture.fixtureRoot, { recursive: true, force: true })
}
})
test('human approval cannot be reused after broadcast bytes change', () => {
const fixture = buildOperatorFixture()
try {
const latestPath = path.join(fixture.source, 'latest.json')
const latest = JSON.parse(fs.readFileSync(latestPath, 'utf8'))
latest.notes = 'Changed after approval'
writeJson(latestPath, latest)
assert.throws(
() => verifyReleaseBundle(fixture.source, fixture.approval),
/HOLOLAKE_RELEASE_OPERATOR_PIPELINE_RECEIPT_INVALID/,
)
} finally {
fs.rmSync(fixture.fixtureRoot, { recursive: true, force: true })
}
})
test('symlinked package inputs are rejected instead of followed', () => {
const fixture = buildOperatorFixture()
try {
const packagePath = path.join(fixture.source, 'HoloLake.app.tar.gz')
const moved = path.join(fixture.fixtureRoot, 'moved-package')
fs.renameSync(packagePath, moved)
fs.symlinkSync(moved, packagePath)
assert.throws(
() => verifyReleaseBundle(fixture.source, fixture.approval),
/HOLOLAKE_RELEASE_OPERATOR_FILE_INVALID/,
)
} finally {
fs.rmSync(fixture.fixtureRoot, { recursive: true, force: true })
}
})