20260826 两宿主全线正本/回执/状态 + 协议正本地图v1.2 + 模板/镜面/坑清单(元审计收敛commit;前人未提交改动未碰)

This commit is contained in:
冰朔 2026-08-26 16:23:44 +08:00
commit 59fc9bfd7b
670 changed files with 133422 additions and 129 deletions

View file

@ -0,0 +1,59 @@
# HoloLake release broadcast candidate
This is the HoloLake-owned, loopback-only origin for signed update broadcasts.
It has no upstream software feed and never uploads or activates a release.
Without `ACTIVE.json`, `/health` reports `EMPTY_FAIL_CLOSED` and `/latest.json`
returns HTTP 204, the updater protocol's explicit no-update result. An active
release is accepted only when the human activation record, immutable broadcast,
pipeline receipt, package bytes, Developer ID receipt, and Apple notarization
receipt form one exact evidence chain. Invalid evidence locks the whole release
endpoint until an operator fixes the evidence and explicitly restarts the
service.
The service listens only on `127.0.0.1`. The public HTTPS path is carried by a
dedicated, port-forwarding-only identity from JD-FD-PRIMARY to BS-GZ-006 and
currently returns the origin's empty fail-closed `204` response. Artifact
upload, activation, and desktop rollout remain independent deployment gates.
The registered public namespace is `/hololake/releases`. The loopback origin
accepts the manifest at both its operator health-check path `/latest.json` and
the public updater path `/hololake/releases/latest.json`; release package URLs
must remain under that same public prefix. The front-door proxy must therefore
preserve the full request URI. The registered BS-GZ-006 loopback tunnel port is
`19440`; it is not a public listener.
`render-front-door.mjs --loopback-port PORT` renders the bounded Nginx
location. It refuses an omitted
port, preserves the full public request path by leaving `proxy_pass` without a
URI suffix, accepts only GET and HEAD, forwards no request body, and strips
authorization, cookies, and client forwarding headers. Rendering is not
deployment; Nginx validation, transactional install, public certificate/readback,
and a separate server receipt remain required.
`operator.mjs` supplies the separate, root-operated verification and activation
boundary. `verify` reconstructs a private candidate tree and accepts it only when
the broadcast, pipeline receipt, package bytes, Developer ID receipt, Apple
notarization receipt, and exact human approval all agree. `activate` additionally
requires the operator to repeat the expected release id, version, source commit,
and broadcast SHA-256. It copies only referenced immutable artifacts, commits
`ACTIVE.json` atomically, and reports that an explicit service restart is still
required. It never uploads, activates, or restarts on its own.
```text
node operator.mjs verify \
--source /secure/release/out/0.2.0 \
--human-approval /secure/approvals/0.2.0.json
sudo node operator.mjs activate \
--source /secure/release/out/0.2.0 \
--human-approval /secure/approvals/0.2.0.json \
--state-root /var/lib/guanghu/hololake-release-broadcast \
--expect-release-id GH-HOLOLAKE-RELEASE-0.2.0 \
--expect-version 0.2.0 \
--expect-source-commit 0000000000000000000000000000000000000000 \
--expect-broadcast-sha256 0000000000000000000000000000000000000000000000000000000000000000
```
The zeros above are placeholders, not deployable values. A real activation must
use the exact facts printed by `verify` and a separately issued human approval.

View file

@ -0,0 +1,36 @@
[Unit]
Description=HoloLake signed release broadcast candidate
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=hololake-release
Group=hololake-release
WorkingDirectory=/opt/guanghu/hololake-release-broadcast-candidate/current
Environment=HOLOLAKE_RELEASE_HOST=127.0.0.1
Environment=HOLOLAKE_RELEASE_PORT=3940
Environment=HOLOLAKE_RELEASE_STATE_ROOT=/var/lib/guanghu/hololake-release-broadcast
Environment=HOLOLAKE_RELEASE_ENFORCE_ROOT_OWNER=1
Environment=HOLOLAKE_RELEASE_PUBLIC_PREFIX=/hololake/releases
ExecStart=/usr/bin/node /opt/guanghu/hololake-release-broadcast-candidate/current/server.mjs
Restart=on-failure
RestartSec=5
UMask=0027
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictSUIDSGID=true
RestrictRealtime=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
IPAddressDeny=any
IPAddressAllow=localhost
ReadOnlyPaths=/opt/guanghu/hololake-release-broadcast-candidate
ReadOnlyPaths=/var/lib/guanghu/hololake-release-broadcast
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,431 @@
#!/usr/bin/env node
import crypto from 'node:crypto'
import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import { DEFAULT_PUBLIC_PREFIX, isMainModule, loadRuntimeState, normalizePublicPrefix } from './server.mjs'
const MAX_CONTROL_BYTES = 1024 * 1024
const SHA256_PATTERN = /^[a-f0-9]{64}$/
const SOURCE_COMMIT_PATTERN = /^[a-f0-9]{40}$/
const VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/
const fail = (code) => {
throw new Error(code)
}
const sha256 = (bytes) => crypto.createHash('sha256').update(bytes).digest('hex')
const requireText = (value, code) => {
if (typeof value !== 'string' || value.trim() === '') fail(code)
return value.trim()
}
function requireTrustedDirectory(directory, { enforceRootOwner = false } = {}) {
const info = fs.lstatSync(directory)
if (!info.isDirectory() || info.isSymbolicLink()) fail('HOLOLAKE_RELEASE_OPERATOR_DIRECTORY_INVALID')
if ((info.mode & 0o022) !== 0) fail('HOLOLAKE_RELEASE_OPERATOR_DIRECTORY_WRITABLE_BY_NON_OWNER')
if (enforceRootOwner && info.uid !== 0) fail('HOLOLAKE_RELEASE_OPERATOR_DIRECTORY_NOT_ROOT_OWNED')
return info
}
function requireTrustedFile(file, { enforceRootOwner = false, maxBytes = null } = {}) {
const info = fs.lstatSync(file)
if (!info.isFile() || info.isSymbolicLink()) fail('HOLOLAKE_RELEASE_OPERATOR_FILE_INVALID')
if ((info.mode & 0o022) !== 0) fail('HOLOLAKE_RELEASE_OPERATOR_FILE_WRITABLE_BY_NON_OWNER')
if (enforceRootOwner && info.uid !== 0) fail('HOLOLAKE_RELEASE_OPERATOR_FILE_NOT_ROOT_OWNED')
if (maxBytes !== null && info.size > maxBytes) fail('HOLOLAKE_RELEASE_OPERATOR_CONTROL_FILE_TOO_LARGE')
return info
}
function readJson(file, { enforceRootOwner = false } = {}) {
requireTrustedFile(file, { enforceRootOwner, maxBytes: MAX_CONTROL_BYTES })
const bytes = fs.readFileSync(file)
return { bytes, value: JSON.parse(bytes.toString('utf8')) }
}
function directFile(directory, name, code) {
const value = requireText(name, code)
if (value !== path.basename(value) || value === '.' || value === '..' || value.includes('\0')) fail(code)
const resolved = path.resolve(directory, value)
if (path.dirname(resolved) !== directory) fail(code)
return resolved
}
function packageNameFromUrl(value, publicPrefix) {
const url = new URL(requireText(value, 'HOLOLAKE_RELEASE_OPERATOR_PACKAGE_URL_REQUIRED'))
if (url.protocol !== 'https:' || url.username || url.password || url.search || url.hash) {
fail('HOLOLAKE_RELEASE_OPERATOR_PACKAGE_URL_INVALID')
}
let packageName
try {
packageName = decodeURIComponent(path.posix.basename(url.pathname))
} catch {
fail('HOLOLAKE_RELEASE_OPERATOR_PACKAGE_URL_INVALID')
}
if (!packageName || packageName === '.' || packageName === '..') fail('HOLOLAKE_RELEASE_OPERATOR_PACKAGE_NAME_INVALID')
if (!url.pathname.startsWith(`${publicPrefix}/`) || url.pathname === `${publicPrefix}/latest.json` || url.pathname === `${publicPrefix}/health`) {
fail('HOLOLAKE_RELEASE_OPERATOR_PACKAGE_PUBLIC_PREFIX_MISMATCH')
}
return packageName
}
function addArtifact(artifacts, source, name, type) {
const previous = artifacts.get(name)
if (previous && previous.source !== source) fail('HOLOLAKE_RELEASE_OPERATOR_ARTIFACT_NAME_COLLISION')
artifacts.set(name, { source, name, type })
}
export function inspectReleaseBundle(
sourceDirectory,
humanApprovalPath,
{ enforceRootOwner = false, publicPrefix = DEFAULT_PUBLIC_PREFIX } = {},
) {
const source = path.resolve(sourceDirectory)
const normalizedPublicPrefix = normalizePublicPrefix(publicPrefix)
requireTrustedDirectory(source, { enforceRootOwner })
const latestPath = directFile(source, 'latest.json', 'HOLOLAKE_RELEASE_OPERATOR_BROADCAST_PATH_INVALID')
const pipelinePath = directFile(source, 'pipeline-receipt.json', 'HOLOLAKE_RELEASE_OPERATOR_PIPELINE_PATH_INVALID')
const approvalPath = path.resolve(humanApprovalPath)
const latestDocument = readJson(latestPath, { enforceRootOwner })
const pipelineReceipt = readJson(pipelinePath, { enforceRootOwner }).value
const approvalReceipt = readJson(approvalPath, { enforceRootOwner }).value
const broadcast = latestDocument.value
const broadcastSha256 = sha256(latestDocument.bytes)
if (broadcast?.schema !== 'hololake.release-broadcast/v1') fail('HOLOLAKE_RELEASE_OPERATOR_BROADCAST_INVALID')
const releaseId = requireText(broadcast.releaseId, 'HOLOLAKE_RELEASE_OPERATOR_RELEASE_ID_REQUIRED')
const version = requireText(broadcast.version, 'HOLOLAKE_RELEASE_OPERATOR_VERSION_REQUIRED')
if (!VERSION_PATTERN.test(version)) fail('HOLOLAKE_RELEASE_OPERATOR_VERSION_INVALID')
if (
broadcast?.hololake?.restart?.required !== true ||
broadcast?.hololake?.restart?.automaticAllowed !== false ||
broadcast?.hololake?.rollback?.supported !== true ||
broadcast?.hololake?.rollback?.healthReceiptRequired !== true ||
!broadcast.platforms ||
typeof broadcast.platforms !== 'object' ||
Array.isArray(broadcast.platforms) ||
Object.keys(broadcast.platforms).length === 0
) fail('HOLOLAKE_RELEASE_OPERATOR_BROADCAST_POLICY_INVALID')
if (
pipelineReceipt?.schema !== 'hololake.signed-release-pipeline-receipt/v1' ||
pipelineReceipt?.state !== 'SIGNED_NOTARIZED_RELEASE_BROADCAST_READY_FOR_JD_CONTROLLER_UPLOAD' ||
pipelineReceipt?.broadcastSha256 !== broadcastSha256 ||
!SOURCE_COMMIT_PATTERN.test(pipelineReceipt?.sourceCommit || '') ||
pipelineReceipt?.automaticUpload !== false ||
pipelineReceipt?.automaticActivation !== false
) fail('HOLOLAKE_RELEASE_OPERATOR_PIPELINE_RECEIPT_INVALID')
const approvalId = requireText(approvalReceipt?.approvalId, 'HOLOLAKE_RELEASE_OPERATOR_APPROVAL_ID_REQUIRED')
if (
approvalReceipt?.schema !== 'hololake.release-broadcast-human-approval/v1' ||
approvalReceipt?.state !== 'HUMAN_APPROVED_EXACT_SIGNED_NOTARIZED_RELEASE' ||
approvalReceipt?.releaseId !== releaseId ||
approvalReceipt?.version !== version ||
approvalReceipt?.broadcastSha256 !== broadcastSha256
) fail('HOLOLAKE_RELEASE_OPERATOR_HUMAN_APPROVAL_INVALID')
const artifacts = new Map()
addArtifact(artifacts, latestPath, 'latest.json', 'control')
addArtifact(artifacts, pipelinePath, 'pipeline-receipt.json', 'control')
addArtifact(artifacts, approvalPath, 'human-approval.json', 'control')
for (const platform of Object.values(broadcast.platforms)) {
const packageName = packageNameFromUrl(platform?.url, normalizedPublicPrefix)
const packagePath = directFile(source, packageName, 'HOLOLAKE_RELEASE_OPERATOR_PACKAGE_PATH_INVALID')
const packageInfo = requireTrustedFile(packagePath, { enforceRootOwner })
if (!Number.isSafeInteger(platform.size) || platform.size <= 0 || platform.size !== packageInfo.size) {
fail('HOLOLAKE_RELEASE_OPERATOR_PACKAGE_SIZE_MISMATCH')
}
if (!SHA256_PATTERN.test(platform.sha256 || '') || sha256(fs.readFileSync(packagePath)) !== platform.sha256) {
fail('HOLOLAKE_RELEASE_OPERATOR_PACKAGE_SHA256_MISMATCH')
}
requireText(platform.signature, 'HOLOLAKE_RELEASE_OPERATOR_PACKAGE_SIGNATURE_REQUIRED')
const codeReceiptId = requireText(platform.platformCodeSignatureReceipt, 'HOLOLAKE_RELEASE_OPERATOR_CODESIGN_RECEIPT_REQUIRED')
const notarizationReceiptId = requireText(platform.notarizationReceipt, 'HOLOLAKE_RELEASE_OPERATOR_NOTARIZATION_RECEIPT_REQUIRED')
const codeReceiptName = `${codeReceiptId}.json`
const notarizationReceiptName = `${notarizationReceiptId}.json`
const codeReceiptPath = directFile(source, codeReceiptName, 'HOLOLAKE_RELEASE_OPERATOR_CODESIGN_RECEIPT_PATH_INVALID')
const notarizationReceiptPath = directFile(source, notarizationReceiptName, 'HOLOLAKE_RELEASE_OPERATOR_NOTARIZATION_RECEIPT_PATH_INVALID')
const codeReceipt = readJson(codeReceiptPath, { enforceRootOwner }).value
const notarizationReceipt = readJson(notarizationReceiptPath, { enforceRootOwner }).value
if (
codeReceipt?.schema !== 'hololake.platform-code-signature-receipt/v1' ||
codeReceipt?.state !== 'DEVELOPER_ID_SIGNATURE_STRICT_AND_GATEKEEPER_ACCEPTED' ||
codeReceipt?.sourceCommit !== pipelineReceipt.sourceCommit
) fail('HOLOLAKE_RELEASE_OPERATOR_CODESIGN_RECEIPT_INVALID')
if (
notarizationReceipt?.schema !== 'hololake.apple-notarization-receipt/v1' ||
notarizationReceipt?.state !== 'APPLE_NOTARIZATION_ACCEPTED_AND_STAPLED' ||
notarizationReceipt?.sourceCommit !== pipelineReceipt.sourceCommit
) fail('HOLOLAKE_RELEASE_OPERATOR_NOTARIZATION_RECEIPT_INVALID')
addArtifact(artifacts, packagePath, packageName, 'package')
addArtifact(artifacts, codeReceiptPath, codeReceiptName, 'control')
addArtifact(artifacts, notarizationReceiptPath, notarizationReceiptName, 'control')
}
return {
schema: 'hololake.release-broadcast-operator-plan/v1',
state: 'EXACT_SIGNED_NOTARIZED_HUMAN_APPROVED_BUNDLE_VERIFIED',
releaseId,
version,
sourceCommit: pipelineReceipt.sourceCommit,
broadcastSha256,
approvalId,
publicPrefix: normalizedPublicPrefix,
artifacts: [...artifacts.values()],
}
}
function copyFileNoFollow(source, destination, mode) {
const sourceDescriptor = fs.openSync(source, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW)
let destinationDescriptor = null
try {
const sourceInfo = fs.fstatSync(sourceDescriptor)
if (!sourceInfo.isFile() || (sourceInfo.mode & 0o022) !== 0) fail('HOLOLAKE_RELEASE_OPERATOR_SOURCE_CHANGED')
destinationDescriptor = fs.openSync(destination, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, mode)
const buffer = Buffer.allocUnsafe(1024 * 1024)
let position = 0
while (position < sourceInfo.size) {
const read = fs.readSync(sourceDescriptor, buffer, 0, Math.min(buffer.length, sourceInfo.size - position), position)
if (read <= 0) fail('HOLOLAKE_RELEASE_OPERATOR_SOURCE_TRUNCATED')
let written = 0
while (written < read) written += fs.writeSync(destinationDescriptor, buffer, written, read - written)
position += read
}
fs.fsyncSync(destinationDescriptor)
} finally {
if (destinationDescriptor !== null) fs.closeSync(destinationDescriptor)
fs.closeSync(sourceDescriptor)
}
}
function writeJsonExclusive(file, value, mode) {
const descriptor = fs.openSync(file, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, mode)
try {
fs.writeFileSync(descriptor, `${JSON.stringify(value, null, 2)}\n`)
fs.fsyncSync(descriptor)
} finally {
fs.closeSync(descriptor)
}
}
function activationFor(plan) {
return {
schema: 'hololake.release-broadcast-activation/v1',
state: 'HUMAN_APPROVED_SIGNED_NOTARIZED_RELEASE_ACTIVE',
releaseId: plan.releaseId,
version: plan.version,
broadcastRelativePath: `releases/${plan.version}/latest.json`,
broadcastSha256: plan.broadcastSha256,
pipelineReceiptRelativePath: `releases/${plan.version}/pipeline-receipt.json`,
humanApprovalReceipt: plan.approvalId,
humanApprovalReceiptRelativePath: `releases/${plan.version}/human-approval.json`,
}
}
function prepareCandidate(candidateRoot, plan, { enforceRootOwner, trustedGroupId }) {
const releases = path.join(candidateRoot, 'releases')
const releaseDirectory = path.join(releases, plan.version)
fs.mkdirSync(releaseDirectory, { recursive: true, mode: enforceRootOwner ? 0o750 : 0o700 })
for (const artifact of plan.artifacts) {
const destination = path.join(releaseDirectory, artifact.name)
copyFileNoFollow(artifact.source, destination, enforceRootOwner ? 0o640 : 0o600)
if (enforceRootOwner) fs.chownSync(destination, 0, trustedGroupId)
}
const activationPath = path.join(candidateRoot, 'ACTIVE.json')
writeJsonExclusive(activationPath, activationFor(plan), enforceRootOwner ? 0o640 : 0o600)
if (enforceRootOwner) {
for (const directory of [candidateRoot, releases, releaseDirectory]) {
fs.chownSync(directory, 0, trustedGroupId)
fs.chmodSync(directory, 0o750)
}
fs.chownSync(activationPath, 0, trustedGroupId)
}
const state = loadRuntimeState(candidateRoot, { enforceRootOwner, publicPrefix: plan.publicPrefix })
if (state.state !== 'READY_SIGNED_NOTARIZED_BROADCAST') {
fail(`HOLOLAKE_RELEASE_OPERATOR_CANDIDATE_INVALID:${state.reasonCode || state.state}`)
}
return { releaseDirectory, activationPath }
}
function requireExpected(plan, expected) {
for (const [field, code] of [
['releaseId', 'HOLOLAKE_RELEASE_OPERATOR_EXPECTED_RELEASE_ID_MISMATCH'],
['version', 'HOLOLAKE_RELEASE_OPERATOR_EXPECTED_VERSION_MISMATCH'],
['sourceCommit', 'HOLOLAKE_RELEASE_OPERATOR_EXPECTED_SOURCE_COMMIT_MISMATCH'],
['broadcastSha256', 'HOLOLAKE_RELEASE_OPERATOR_EXPECTED_BROADCAST_SHA256_MISMATCH'],
]) {
if (requireText(expected?.[field], `${code}_REQUIRED`) !== plan[field]) fail(code)
}
}
function replaceActivation(stateRoot, candidateActivation, previousBytes, enforceRootOwner, trustedGroupId, publicPrefix) {
const tempActivation = path.join(stateRoot, `.ACTIVE.${crypto.randomUUID()}.tmp`)
copyFileNoFollow(candidateActivation, tempActivation, enforceRootOwner ? 0o640 : 0o600)
if (enforceRootOwner) fs.chownSync(tempActivation, 0, trustedGroupId)
fs.renameSync(tempActivation, path.join(stateRoot, 'ACTIVE.json'))
const committed = loadRuntimeState(stateRoot, { enforceRootOwner, publicPrefix })
if (committed.state === 'READY_SIGNED_NOTARIZED_BROADCAST') return committed
const failedActive = path.join(stateRoot, 'ACTIVE.json')
if (previousBytes === null) {
fs.unlinkSync(failedActive)
} else {
const rollback = path.join(stateRoot, `.ACTIVE.rollback.${crypto.randomUUID()}.tmp`)
const descriptor = fs.openSync(rollback, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, enforceRootOwner ? 0o640 : 0o600)
try {
fs.writeFileSync(descriptor, previousBytes)
fs.fsyncSync(descriptor)
} finally {
fs.closeSync(descriptor)
}
if (enforceRootOwner) fs.chownSync(rollback, 0, trustedGroupId)
fs.renameSync(rollback, failedActive)
}
fail(`HOLOLAKE_RELEASE_OPERATOR_POST_COMMIT_INVALID:${committed.reasonCode || committed.state}`)
}
function acquireOperatorLock(stateRoot, enforceRootOwner, trustedGroupId) {
const lockDirectory = path.join(stateRoot, '.operator-lock')
try {
fs.mkdirSync(lockDirectory, { mode: enforceRootOwner ? 0o750 : 0o700 })
} catch (error) {
if (error?.code === 'EEXIST') fail('HOLOLAKE_RELEASE_OPERATOR_LOCKED')
throw error
}
try {
if (enforceRootOwner) fs.chownSync(lockDirectory, 0, trustedGroupId)
writeJsonExclusive(path.join(lockDirectory, 'owner.json'), {
schema: 'hololake.release-broadcast-operator-lock/v1',
pid: process.pid,
acquiredAt: new Date().toISOString(),
}, enforceRootOwner ? 0o640 : 0o600)
if (enforceRootOwner) fs.chownSync(path.join(lockDirectory, 'owner.json'), 0, trustedGroupId)
return lockDirectory
} catch (error) {
fs.rmSync(lockDirectory, { recursive: true, force: true })
throw error
}
}
export function verifyReleaseBundle(sourceDirectory, humanApprovalPath) {
const plan = inspectReleaseBundle(sourceDirectory, humanApprovalPath)
const candidateRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'hololake-release-operator-verify-'))
try {
prepareCandidate(candidateRoot, plan, { enforceRootOwner: false, trustedGroupId: process.getgid?.() ?? 0 })
return { ...plan, artifacts: plan.artifacts.map(({ name, type }) => ({ name, type })) }
} finally {
fs.rmSync(candidateRoot, { recursive: true, force: true })
}
}
export function activateRelease({
sourceDirectory,
humanApprovalPath,
stateRoot,
expected,
enforceRootOwner = true,
publicPrefix = DEFAULT_PUBLIC_PREFIX,
}) {
if (enforceRootOwner && process.getuid?.() !== 0) fail('HOLOLAKE_RELEASE_OPERATOR_ROOT_REQUIRED')
const root = path.resolve(stateRoot)
const rootInfo = requireTrustedDirectory(root, { enforceRootOwner })
const trustedGroupId = rootInfo.gid
const lockDirectory = acquireOperatorLock(root, enforceRootOwner, trustedGroupId)
let candidateRoot = null
try {
const plan = inspectReleaseBundle(sourceDirectory, humanApprovalPath, { enforceRootOwner, publicPrefix })
requireExpected(plan, expected)
candidateRoot = fs.mkdtempSync(path.join(root, '.candidate-'))
const candidate = prepareCandidate(candidateRoot, plan, { enforceRootOwner, trustedGroupId })
const releasesRoot = path.join(root, 'releases')
if (!fs.existsSync(releasesRoot)) fs.mkdirSync(releasesRoot, { mode: enforceRootOwner ? 0o750 : 0o700 })
requireTrustedDirectory(releasesRoot, { enforceRootOwner })
if (enforceRootOwner) {
fs.chownSync(releasesRoot, 0, trustedGroupId)
fs.chmodSync(releasesRoot, 0o750)
}
const finalRelease = path.join(releasesRoot, plan.version)
if (fs.existsSync(finalRelease)) fail('HOLOLAKE_RELEASE_OPERATOR_VERSION_ALREADY_STAGED')
const activePath = path.join(root, 'ACTIVE.json')
const previousBytes = fs.existsSync(activePath) ? readJson(activePath, { enforceRootOwner }).bytes : null
fs.renameSync(candidate.releaseDirectory, finalRelease)
let committed
try {
committed = replaceActivation(
root,
candidate.activationPath,
previousBytes,
enforceRootOwner,
trustedGroupId,
plan.publicPrefix,
)
} catch (error) {
fs.rmSync(finalRelease, { recursive: true, force: true })
throw error
}
return {
schema: 'hololake.release-broadcast-operator-receipt/v1',
state: 'ACTIVATED_EXPLICIT_SERVICE_RESTART_REQUIRED',
releaseId: plan.releaseId,
version: plan.version,
sourceCommit: plan.sourceCommit,
broadcastSha256: plan.broadcastSha256,
approvalId: plan.approvalId,
publicPrefix: plan.publicPrefix,
automaticUpload: false,
automaticActivation: false,
automaticRestart: false,
runtimeStateAfterDiskCommit: committed.state,
}
} finally {
if (candidateRoot) fs.rmSync(candidateRoot, { recursive: true, force: true })
fs.rmSync(lockDirectory, { recursive: true, force: true })
}
}
function parseArguments(argv) {
const command = argv[0]
const values = {}
for (let index = 1; index < argv.length; index += 1) {
const key = argv[index]
if (!key.startsWith('--') || index + 1 >= argv.length) fail('HOLOLAKE_RELEASE_OPERATOR_ARGUMENT_INVALID')
values[key.slice(2)] = argv[++index]
}
return { command, values }
}
export function main(argv = process.argv.slice(2)) {
const { command, values } = parseArguments(argv)
const sourceDirectory = requireText(values.source, 'HOLOLAKE_RELEASE_OPERATOR_SOURCE_REQUIRED')
const humanApprovalPath = requireText(values['human-approval'], 'HOLOLAKE_RELEASE_OPERATOR_HUMAN_APPROVAL_PATH_REQUIRED')
if (command === 'verify') {
process.stdout.write(`${JSON.stringify(verifyReleaseBundle(sourceDirectory, humanApprovalPath), null, 2)}\n`)
return
}
if (command !== 'activate') fail('HOLOLAKE_RELEASE_OPERATOR_COMMAND_INVALID:verify|activate')
const receipt = activateRelease({
sourceDirectory,
humanApprovalPath,
stateRoot: requireText(values['state-root'], 'HOLOLAKE_RELEASE_OPERATOR_STATE_ROOT_REQUIRED'),
publicPrefix: values['public-prefix'] || DEFAULT_PUBLIC_PREFIX,
expected: {
releaseId: values['expect-release-id'],
version: values['expect-version'],
sourceCommit: values['expect-source-commit'],
broadcastSha256: values['expect-broadcast-sha256'],
},
})
process.stdout.write(`${JSON.stringify(receipt, null, 2)}\n`)
}
if (isMainModule(process.argv[1], import.meta.url)) {
try {
main()
} catch (error) {
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`)
process.exitCode = 1
}
}

View file

@ -0,0 +1,19 @@
{
"schema": "hololake.release-public-route/v1",
"state": "DEPLOYED_EMPTY_FAIL_CLOSED",
"publicBaseUrl": "https://guanghulab.com/hololake/releases",
"releaseEndpoint": "https://guanghulab.com/hololake/releases/latest.json",
"publicPathPrefix": "/hololake/releases",
"originNode": "JD-FD-PRIMARY",
"originListener": "127.0.0.1:3940",
"frontDoorNode": "BS-GZ-006",
"frontDoorLoopbackPort": 19440,
"proxyRequestUriPolicy": "PRESERVE_FULL_PUBLIC_PATH",
"allowedMethods": ["GET", "HEAD"],
"requestBodyAllowed": false,
"latestCachePolicy": "NO_STORE",
"packageCachePolicy": "PUBLIC_IMMUTABLE",
"automaticUpload": false,
"automaticActivation": false,
"deployed": true
}

View file

@ -0,0 +1,54 @@
#!/usr/bin/env node
const PORT_PATTERN = /^(?:[1-9]\d{3,4})$/
const fail = (code) => {
throw new Error(code)
}
export function renderFrontDoorSnippet(portValue) {
const text = String(portValue ?? '')
if (!PORT_PATTERN.test(text)) fail('HOLOLAKE_RELEASE_FRONT_DOOR_PORT_REQUIRED')
const port = Number(text)
if (!Number.isInteger(port) || port < 1024 || port > 65535) fail('HOLOLAKE_RELEASE_FRONT_DOOR_PORT_INVALID')
return `location = /hololake/releases {
return 308 /hololake/releases/;
}
location ^~ /hololake/releases/ {
limit_except GET HEAD { deny all; }
client_max_body_size 0;
proxy_pass http://127.0.0.1:${port};
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Connection "";
proxy_set_header Authorization "";
proxy_set_header Cookie "";
proxy_set_header X-Forwarded-For "";
proxy_set_header X-Forwarded-Host "";
proxy_set_header X-Forwarded-Proto "";
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_connect_timeout 2s;
proxy_send_timeout 10s;
proxy_read_timeout 60s;
}
`
}
export function main(argv = process.argv.slice(2)) {
const portIndex = argv.indexOf('--loopback-port')
if (portIndex < 0 || portIndex + 1 >= argv.length || argv.length !== 2) {
fail('HOLOLAKE_RELEASE_FRONT_DOOR_USAGE:--loopback-port PORT')
}
process.stdout.write(renderFrontDoorSnippet(argv[portIndex + 1]))
}
if (process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href) {
try {
main()
} catch (error) {
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`)
process.exitCode = 1
}
}

View file

@ -0,0 +1,282 @@
#!/usr/bin/env node
import crypto from 'node:crypto'
import fs from 'node:fs'
import http from 'node:http'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const MAX_CONTROL_BYTES = 1024 * 1024
export const DEFAULT_PUBLIC_PREFIX = '/hololake/releases'
const VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/
const SHA256_PATTERN = /^[a-f0-9]{64}$/
const fail = (code) => {
throw new Error(code)
}
const sha256 = (bytes) => crypto.createHash('sha256').update(bytes).digest('hex')
const requireText = (value, code) => {
if (typeof value !== 'string' || value.trim() === '') fail(code)
return value.trim()
}
export function normalizePublicPrefix(value) {
const prefix = requireText(value, 'HOLOLAKE_RELEASE_PUBLIC_PREFIX_REQUIRED')
if (!prefix.startsWith('/') || prefix.endsWith('/') || prefix.includes('//') || prefix.includes('?') || prefix.includes('#')) {
fail('HOLOLAKE_RELEASE_PUBLIC_PREFIX_INVALID')
}
const normalized = path.posix.normalize(prefix)
if (normalized !== prefix || normalized === '/' || normalized.split('/').some((segment) => segment === '..')) {
fail('HOLOLAKE_RELEASE_PUBLIC_PREFIX_INVALID')
}
return prefix
}
function trustedRegularFile(file, { enforceRootOwner, maxBytes = null }) {
const info = fs.lstatSync(file)
if (!info.isFile() || info.isSymbolicLink()) fail('HOLOLAKE_RELEASE_FILE_NOT_REGULAR')
if ((info.mode & 0o022) !== 0) fail('HOLOLAKE_RELEASE_FILE_WRITABLE_BY_NON_OWNER')
if (enforceRootOwner && info.uid !== 0) fail('HOLOLAKE_RELEASE_FILE_NOT_ROOT_OWNED')
if (maxBytes !== null && info.size > maxBytes) fail('HOLOLAKE_RELEASE_CONTROL_FILE_TOO_LARGE')
return info
}
function safeRelative(root, value, code) {
const relative = requireText(value, code)
if (path.isAbsolute(relative) || relative.includes('\0')) fail(code)
const resolved = path.resolve(root, relative)
if (!resolved.startsWith(`${root}${path.sep}`)) fail(code)
return resolved
}
function readTrustedJson(file, options) {
trustedRegularFile(file, { ...options, maxBytes: MAX_CONTROL_BYTES })
return { bytes: fs.readFileSync(file), value: JSON.parse(fs.readFileSync(file, 'utf8')) }
}
function validatePlatform(platform, releaseDirectory, enforceRootOwner, sourceCommit, publicPrefix) {
const url = new URL(requireText(platform?.url, 'HOLOLAKE_RELEASE_PACKAGE_URL_REQUIRED'))
if (url.protocol !== 'https:' || url.username || url.password || url.search || url.hash) {
fail('HOLOLAKE_RELEASE_PACKAGE_URL_INVALID')
}
const packageName = decodeURIComponent(path.posix.basename(url.pathname))
if (!packageName || packageName === '.' || packageName === '..') fail('HOLOLAKE_RELEASE_PACKAGE_NAME_INVALID')
if (!url.pathname.startsWith(`${publicPrefix}/`) || url.pathname === `${publicPrefix}/latest.json` || url.pathname === `${publicPrefix}/health`) {
fail('HOLOLAKE_RELEASE_PACKAGE_PUBLIC_PREFIX_MISMATCH')
}
const packagePath = safeRelative(releaseDirectory, packageName, 'HOLOLAKE_RELEASE_PACKAGE_PATH_INVALID')
const packageInfo = trustedRegularFile(packagePath, { enforceRootOwner })
if (!Number.isSafeInteger(platform.size) || platform.size <= 0 || platform.size !== packageInfo.size) {
fail('HOLOLAKE_RELEASE_PACKAGE_SIZE_MISMATCH')
}
if (!SHA256_PATTERN.test(platform.sha256 || '') || sha256(fs.readFileSync(packagePath)) !== platform.sha256) {
fail('HOLOLAKE_RELEASE_PACKAGE_SHA256_MISMATCH')
}
requireText(platform.signature, 'HOLOLAKE_RELEASE_PACKAGE_SIGNATURE_REQUIRED')
const codeReceiptId = requireText(platform.platformCodeSignatureReceipt, 'HOLOLAKE_RELEASE_CODESIGN_RECEIPT_REQUIRED')
const notarizationReceiptId = requireText(platform.notarizationReceipt, 'HOLOLAKE_RELEASE_NOTARIZATION_RECEIPT_REQUIRED')
const codeReceipt = readTrustedJson(
safeRelative(releaseDirectory, `${codeReceiptId}.json`, 'HOLOLAKE_RELEASE_CODESIGN_RECEIPT_PATH_INVALID'),
{ enforceRootOwner },
).value
const notarizationReceipt = readTrustedJson(
safeRelative(releaseDirectory, `${notarizationReceiptId}.json`, 'HOLOLAKE_RELEASE_NOTARIZATION_RECEIPT_PATH_INVALID'),
{ enforceRootOwner },
).value
if (
codeReceipt?.schema !== 'hololake.platform-code-signature-receipt/v1' ||
codeReceipt?.state !== 'DEVELOPER_ID_SIGNATURE_STRICT_AND_GATEKEEPER_ACCEPTED' ||
codeReceipt?.sourceCommit !== sourceCommit
) fail('HOLOLAKE_RELEASE_CODESIGN_RECEIPT_INVALID')
if (
notarizationReceipt?.schema !== 'hololake.apple-notarization-receipt/v1' ||
notarizationReceipt?.state !== 'APPLE_NOTARIZATION_ACCEPTED_AND_STAPLED' ||
notarizationReceipt?.sourceCommit !== sourceCommit
) fail('HOLOLAKE_RELEASE_NOTARIZATION_RECEIPT_INVALID')
return { pathname: url.pathname, file: packagePath, size: packageInfo.size }
}
function loadActiveRelease(stateRoot, enforceRootOwner, publicPrefix) {
const activationPath = path.join(stateRoot, 'ACTIVE.json')
if (!fs.existsSync(activationPath)) {
return { state: 'EMPTY_FAIL_CLOSED', release: null, reasonCode: null, publicPrefix }
}
const activation = readTrustedJson(activationPath, { enforceRootOwner }).value
if (
activation?.schema !== 'hololake.release-broadcast-activation/v1' ||
activation?.state !== 'HUMAN_APPROVED_SIGNED_NOTARIZED_RELEASE_ACTIVE'
) fail('HOLOLAKE_RELEASE_ACTIVATION_INVALID')
const releaseId = requireText(activation.releaseId, 'HOLOLAKE_RELEASE_ID_REQUIRED')
const version = requireText(activation.version, 'HOLOLAKE_RELEASE_VERSION_REQUIRED')
if (!VERSION_PATTERN.test(version)) fail('HOLOLAKE_RELEASE_VERSION_INVALID')
if (!SHA256_PATTERN.test(activation.broadcastSha256 || '')) fail('HOLOLAKE_RELEASE_BROADCAST_SHA256_INVALID')
requireText(activation.humanApprovalReceipt, 'HOLOLAKE_RELEASE_HUMAN_APPROVAL_REQUIRED')
const broadcastPath = safeRelative(stateRoot, activation.broadcastRelativePath, 'HOLOLAKE_RELEASE_BROADCAST_PATH_INVALID')
const pipelinePath = safeRelative(stateRoot, activation.pipelineReceiptRelativePath, 'HOLOLAKE_RELEASE_PIPELINE_PATH_INVALID')
const approvalPath = safeRelative(stateRoot, activation.humanApprovalReceiptRelativePath, 'HOLOLAKE_RELEASE_HUMAN_APPROVAL_PATH_INVALID')
const broadcastDocument = readTrustedJson(broadcastPath, { enforceRootOwner })
const pipelineReceipt = readTrustedJson(pipelinePath, { enforceRootOwner }).value
const approvalReceipt = readTrustedJson(approvalPath, { enforceRootOwner }).value
if (sha256(broadcastDocument.bytes) !== activation.broadcastSha256) fail('HOLOLAKE_RELEASE_BROADCAST_SHA256_MISMATCH')
if (
pipelineReceipt?.schema !== 'hololake.signed-release-pipeline-receipt/v1' ||
pipelineReceipt?.state !== 'SIGNED_NOTARIZED_RELEASE_BROADCAST_READY_FOR_JD_CONTROLLER_UPLOAD' ||
pipelineReceipt?.broadcastSha256 !== activation.broadcastSha256 ||
!/^[a-f0-9]{40}$/.test(pipelineReceipt?.sourceCommit || '') ||
pipelineReceipt?.automaticUpload !== false ||
pipelineReceipt?.automaticActivation !== false
) fail('HOLOLAKE_RELEASE_PIPELINE_RECEIPT_INVALID')
if (
approvalReceipt?.schema !== 'hololake.release-broadcast-human-approval/v1' ||
approvalReceipt?.state !== 'HUMAN_APPROVED_EXACT_SIGNED_NOTARIZED_RELEASE' ||
approvalReceipt?.approvalId !== activation.humanApprovalReceipt ||
approvalReceipt?.releaseId !== releaseId ||
approvalReceipt?.version !== version ||
approvalReceipt?.broadcastSha256 !== activation.broadcastSha256
) fail('HOLOLAKE_RELEASE_HUMAN_APPROVAL_INVALID')
const broadcast = broadcastDocument.value
if (
broadcast?.schema !== 'hololake.release-broadcast/v1' ||
broadcast?.releaseId !== releaseId ||
broadcast?.version !== version ||
broadcast?.hololake?.restart?.required !== true ||
broadcast?.hololake?.restart?.automaticAllowed !== false ||
broadcast?.hololake?.rollback?.supported !== true ||
broadcast?.hololake?.rollback?.healthReceiptRequired !== true ||
!broadcast.platforms || typeof broadcast.platforms !== 'object' || Array.isArray(broadcast.platforms) ||
Object.keys(broadcast.platforms).length === 0
) fail('HOLOLAKE_RELEASE_BROADCAST_INVALID')
const releaseDirectory = path.dirname(broadcastPath)
const packages = new Map()
for (const platform of Object.values(broadcast.platforms)) {
const accepted = validatePlatform(platform, releaseDirectory, enforceRootOwner, pipelineReceipt.sourceCommit, publicPrefix)
if (packages.has(accepted.pathname)) fail('HOLOLAKE_RELEASE_PACKAGE_ROUTE_COLLISION')
packages.set(accepted.pathname, accepted)
}
return {
state: 'READY_SIGNED_NOTARIZED_BROADCAST',
release: { releaseId, version, broadcastBytes: broadcastDocument.bytes, packages },
reasonCode: null,
publicPrefix,
}
}
export function loadRuntimeState(stateRoot, { enforceRootOwner = false, publicPrefix = DEFAULT_PUBLIC_PREFIX } = {}) {
const resolvedRoot = path.resolve(stateRoot)
try {
const normalizedPrefix = normalizePublicPrefix(publicPrefix)
return loadActiveRelease(resolvedRoot, enforceRootOwner, normalizedPrefix)
} catch (error) {
return {
state: 'LOCKED_INVALID_RELEASE_EVIDENCE',
release: null,
reasonCode: error instanceof Error ? error.message : 'HOLOLAKE_RELEASE_UNKNOWN_FAILURE',
publicPrefix: null,
}
}
}
function jsonResponse(response, status, value) {
const body = Buffer.from(`${JSON.stringify(value)}\n`)
response.writeHead(status, {
'Content-Type': 'application/json; charset=utf-8',
'Content-Length': body.length,
'Cache-Control': 'no-store',
'X-Content-Type-Options': 'nosniff',
})
response.end(body)
}
export function createReleaseServer(runtimeState) {
return http.createServer((request, response) => {
response.setHeader('X-Content-Type-Options', 'nosniff')
if (!['GET', 'HEAD'].includes(request.method || '')) {
response.writeHead(405, { Allow: 'GET, HEAD', 'Cache-Control': 'no-store' })
return response.end()
}
const pathname = new URL(request.url || '/', 'http://127.0.0.1').pathname
const publicHealthPath = runtimeState.publicPrefix ? `${runtimeState.publicPrefix}/health` : null
const publicLatestPath = runtimeState.publicPrefix ? `${runtimeState.publicPrefix}/latest.json` : null
if (pathname === '/health' || pathname === publicHealthPath) {
const status = runtimeState.state === 'LOCKED_INVALID_RELEASE_EVIDENCE' ? 503 : 200
return jsonResponse(response, status, {
schema: 'hololake.release-broadcast-health/v1',
state: runtimeState.state,
updateAvailable: runtimeState.release !== null,
automaticUpload: false,
automaticActivation: false,
upstreamUpdateSources: [],
...(runtimeState.publicPrefix ? {
publicPathPrefix: runtimeState.publicPrefix,
releaseEndpointPath: `${runtimeState.publicPrefix}/latest.json`,
} : {}),
...(runtimeState.release ? { releaseId: runtimeState.release.releaseId, version: runtimeState.release.version } : {}),
...(runtimeState.reasonCode ? { reasonCode: runtimeState.reasonCode } : {}),
})
}
if (pathname === '/latest.json' || pathname === publicLatestPath) {
if (runtimeState.state === 'EMPTY_FAIL_CLOSED') {
response.writeHead(204, { 'Cache-Control': 'no-store' })
return response.end()
}
if (!runtimeState.release) {
response.writeHead(503, { 'Cache-Control': 'no-store' })
return response.end()
}
response.writeHead(200, {
'Content-Type': 'application/json; charset=utf-8',
'Content-Length': runtimeState.release.broadcastBytes.length,
'Cache-Control': 'no-store',
'X-Content-Type-Options': 'nosniff',
})
return response.end(request.method === 'HEAD' ? undefined : runtimeState.release.broadcastBytes)
}
const packageFile = runtimeState.release?.packages.get(pathname)
if (packageFile) {
response.writeHead(200, {
'Content-Type': 'application/octet-stream',
'Content-Length': packageFile.size,
'Cache-Control': 'public, max-age=31536000, immutable',
'X-Content-Type-Options': 'nosniff',
})
if (request.method === 'HEAD') return response.end()
return fs.createReadStream(packageFile.file).on('error', () => response.destroy()).pipe(response)
}
response.writeHead(404, { 'Cache-Control': 'no-store' })
response.end()
})
}
export function main(env = process.env) {
const host = env.HOLOLAKE_RELEASE_HOST || '127.0.0.1'
if (host !== '127.0.0.1') fail('HOLOLAKE_RELEASE_LOOPBACK_BIND_REQUIRED')
const port = Number(env.HOLOLAKE_RELEASE_PORT || 3940)
if (!Number.isInteger(port) || port < 1024 || port > 65535) fail('HOLOLAKE_RELEASE_PORT_INVALID')
const stateRoot = path.resolve(env.HOLOLAKE_RELEASE_STATE_ROOT || '/var/lib/guanghu/hololake-release-broadcast')
const publicPrefix = env.HOLOLAKE_RELEASE_PUBLIC_PREFIX || DEFAULT_PUBLIC_PREFIX
const runtimeState = loadRuntimeState(stateRoot, {
enforceRootOwner: env.HOLOLAKE_RELEASE_ENFORCE_ROOT_OWNER === '1',
publicPrefix,
})
const server = createReleaseServer(runtimeState)
server.on('clientError', (_error, socket) => socket.end('HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n'))
server.listen(port, host, () => {
process.stdout.write(`${JSON.stringify({ schema: 'hololake.release-broadcast-startup/v1', host, port, state: runtimeState.state })}\n`)
})
return server
}
export function isMainModule(argvPath, moduleUrl) {
return Boolean(argvPath) && fs.realpathSync(path.resolve(argvPath)) === fs.realpathSync(fileURLToPath(moduleUrl))
}
if (isMainModule(process.argv[1], import.meta.url)) {
try {
main()
} catch (error) {
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`)
process.exitCode = 1
}
}