From 29bb023455ce245dc44dbd5e61ced92cd647e071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Sat, 15 Aug 2026 23:16:37 +0800 Subject: [PATCH] feat(guanghu-os): add pre-root supervisor source slice --- .../hololake-platform/docs/ABSTRACTIONS.md | 7 + .../hololake-platform/docs/ARCHITECTURE.md | 8 ++ ...t-supervisor-and-linux-kernel-substrate.md | 39 ++++++ .../hololake-platform/guanghu-os/README.md | 18 +++ .../first-boot-supervisor.conf.example | 6 + .../hooks/guanghu-first-boot-supervisor | 17 +++ .../guanghu-first-boot-supervisor | 13 ++ .../build-guanghu-first-boot-initramfs.sh | 53 ++++++++ .../scripts/guanghu-first-boot-supervisor.sh | 127 ++++++++++++++++++ .../test-guanghu-first-boot-supervisor.sh | 104 ++++++++++++++ .../run-guanghu-native-quality-gate.sh | 2 + routing/guanghu-os-control-architecture.json | 7 +- .../guanghu-os-control-architecture.test.mjs | 5 +- 13 files changed, 403 insertions(+), 3 deletions(-) create mode 100644 product-source/hololake-platform/docs/adr/0176-guanghu-pre-root-supervisor-and-linux-kernel-substrate.md create mode 100644 product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/first-boot-supervisor.conf.example create mode 100755 product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/hooks/guanghu-first-boot-supervisor create mode 100755 product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/scripts/local-premount/guanghu-first-boot-supervisor create mode 100755 product-source/hololake-platform/guanghu-os/scripts/build-guanghu-first-boot-initramfs.sh create mode 100755 product-source/hololake-platform/guanghu-os/scripts/guanghu-first-boot-supervisor.sh create mode 100755 product-source/hololake-platform/guanghu-os/scripts/test-guanghu-first-boot-supervisor.sh diff --git a/product-source/hololake-platform/docs/ABSTRACTIONS.md b/product-source/hololake-platform/docs/ABSTRACTIONS.md index 5624abf0f..627942826 100644 --- a/product-source/hololake-platform/docs/ABSTRACTIONS.md +++ b/product-source/hololake-platform/docs/ABSTRACTIONS.md @@ -1404,3 +1404,10 @@ server deployment. - **`.github/workflows/release.yml`** — Alpha prereleases from every push to `main` using calendar-semver technical versions (`YYYY.M.D-alpha.N`) and clean `Alpha YYYY.M.D.N` release names. GitHub alpha tags zero-pad the prerelease sequence (`alpha-vYYYY.M.D-alpha.NNNN`) so GitHub release ordering stays chronological while the shipped app version remains `YYYY.M.D-alpha.N`. Publishes `alpha/latest.json` with macOS Apple Silicon/Intel, Linux x64, and Windows x64 updater entries, then refreshes the legacy `latest.json` / `latest-canary.json` aliases to the alpha feed. The Windows job always requires Tauri updater signatures, uses Authenticode signing and `Get-AuthenticodeSignature` verification when Windows certificate secrets are present, and warns while building updater-signed-only artifacts when those secrets are absent. The Linux job uses Tauri's stock linuxdeploy AppImage output plugin and validates that installer and updater-signature artifacts exist before upload. The docs/release Pages job reads the stable manifest from the latest stable release asset instead of copying the live Pages URL, uploads the built site as a Pages artifact, and deploys it with GitHub's official Pages action so the public updater JSON changes as part of the release workflow. Changes to the shared artifact workflow are not ignored by the alpha trigger, so release-pipeline fixes produce a fresh alpha run. macOS release assets use `Tolaria__macOS_Silicon` and `Tolaria__macOS_Intel` base names. Packaged builds pass the computed version as `VITE_SENTRY_RELEASE`, which is retained as a diagnostic build-version tag but not registered as a normal Sentry release for alpha builds. - **`.github/workflows/release-stable.yml`** — Stable releases from `stable-vYYYY.M.D` tags. Publishes `stable/latest.json`, macOS Apple Silicon and Intel DMG/updater artifacts, Windows x64 installers plus Tauri-signed updater bundles, Linux x86_64 `.deb` / `.rpm` / AppImage artifacts, and a static public download page that starts selected non-Windows installers without replacing the page with a blank download navigation. Windows visitors see an explicit installer action and managed-device guidance instead of an automatic download. Authenticode publisher signing is added to Windows artifacts when certificate secrets are configured; until then, the workflow warns and publishes updater-signed-only Windows artifacts. Linux visitors default to the AppImage target while the page exposes RPM as a manual Linux package option when the stable release includes one. The Linux job uses the same stock Tauri/linuxdeploy AppImage packaging and artifact validation as alpha releases. The Pages job reads the alpha manifest from the latest alpha release asset instead of copying the live Pages URL, uploads the built site as a Pages artifact, and deploys it with GitHub's official Pages action so stable and alpha manifests stay fresh. Stable macOS DMG/updater assets use the same `Tolaria__macOS_Silicon` and `Tolaria__macOS_Intel` base names. Packaged builds pass the computed stable version as `VITE_SENTRY_RELEASE`, which is registered as Sentry's release. - **Beta cohorts** are handled in PostHog targeting only. There is no beta updater feed. +# Guanghu first-boot handoff + +The pre-root handoff is evidence from one kernel boot, not an authority token. +It binds node, DMI instance, boot ID, root UUID, rescue entry, and the pending +repository bridge before full Linux userspace starts. Later control layers +must re-read live state and must not infer persistent Guanghu master control +from the handoff alone. diff --git a/product-source/hololake-platform/docs/ARCHITECTURE.md b/product-source/hololake-platform/docs/ARCHITECTURE.md index cf90060fe..c674d7b01 100644 --- a/product-source/hololake-platform/docs/ARCHITECTURE.md +++ b/product-source/hololake-platform/docs/ARCHITECTURE.md @@ -1521,3 +1521,11 @@ Features that work on both platforms without changes: **Capabilities:** `src-tauri/capabilities/default.json` targets desktop; `mobile.json` targets iOS/Android with a minimal permission set. **Detailed feasibility report:** `docs/IPAD-PROTOTYPE.md` +# Guanghu pre-root control slice + +The Guanghu OS transition includes a fail-closed initramfs stage before the +complete Ubuntu root filesystem is mounted. Its source lives under +`guanghu-os/scripts/guanghu-first-boot-supervisor.sh` with packaging in +`guanghu-os/packaging/initramfs-tools/`. It produces a boot-scoped handoff for +the later hosted repository bridge; it is not yet the persistent first-boot +supervisor or final on-demand Linux topology. diff --git a/product-source/hololake-platform/docs/adr/0176-guanghu-pre-root-supervisor-and-linux-kernel-substrate.md b/product-source/hololake-platform/docs/adr/0176-guanghu-pre-root-supervisor-and-linux-kernel-substrate.md new file mode 100644 index 000000000..eb476ab31 --- /dev/null +++ b/product-source/hololake-platform/docs/adr/0176-guanghu-pre-root-supervisor-and-linux-kernel-substrate.md @@ -0,0 +1,39 @@ +--- +type: ADR +id: "0176" +title: "Guanghu pre-root supervisor over a Linux hardware-compatibility substrate" +status: accepted +date: 2026-08-15 +refines: "0175" +--- + +# 光湖先启动监督器与 Linux 硬件兼容底座 + +## 背景 + +`JD-FD-PRIMARY` 是运行在 KVM 上的云主机。当前现场没有向来宾暴露 VMX/SVM,也没有 +`/dev/kvm`,因此不能在现有光湖小内核下面再用硬件虚拟化启动一套完整 Linux 来宾。把完整 +Ubuntu 永久作为先启动宿主,又不能满足 ADR-0175 的光湖先启动主控。 + +## 决定 + +第一现实切片使用当前受支持的 Linux 内核与 initramfs 作为硬件兼容底座,但在挂载完整 +Ubuntu 根系统之前运行光湖监督器。监督器必须绑定精确节点、DMI、根 UUID、本轮启动 ID、显式 +内核启动标记、Linux 救援槽和仓库桥名称,随后留下同一启动周期的受限交接状态。完整 Linux +用户态在这个时点保持休眠;后续阶段只允许把登记的仓库数据面接成有界协作层。 + +这条路线不把 Linux 内核删除,也不把内核驱动归属误写成系统主权。主权仍由谁先恢复光湖控制 +状态、签发后续生命周期、验收回读、收回协作层以及保留救援决定。 + +## 当前边界 + +initramfs 前置脚本和交接合同只证明“完整根系统之前已有光湖控制状态”的源码能力。脚本返回后 +尚未证明监督器跨 `switch_root` 持续存活,也没有证明完整 Linux 用户态可以按需唤醒和收回。 +因此以下谓词继续为零: + +- `independent_guanghu_first_boot_supervisor`; +- `linux_on_demand_subcontrol`; +- `final_guanghu_os_master`。 + +下一门先在京东同核 QEMU 中证明前置执行与失败关闭,再单独实现跨根切换的持续监督实体;任何 +真实 GRUB、initramfs 默认项、重启或磁盘更改仍需服务器工作单、回滚和节点自有回执。 diff --git a/product-source/hololake-platform/guanghu-os/README.md b/product-source/hololake-platform/guanghu-os/README.md index 8dba48b23..4d34c3475 100644 --- a/product-source/hololake-platform/guanghu-os/README.md +++ b/product-source/hololake-platform/guanghu-os/README.md @@ -94,6 +94,24 @@ host. It cannot prove Guanghu-first boot control or the final topology. Those remain `0` until the same lifecycle is owned by an independently booted Guanghu supervisor and has a current JD server receipt. +## Pre-root Guanghu supervisor source slice + +`scripts/guanghu-first-boot-supervisor.sh` and the matching initramfs-tools +hook move the first deterministic Guanghu control state ahead of the complete +Ubuntu root filesystem. The pre-root step binds the exact JD DMI instance, +root UUID, boot ID, explicit `guanghu.first_boot=1` kernel marker, preserved +Linux rescue entry, and repository bridge. It then writes one boot-scoped +handoff under `/run/guanghu/first-boot` while the complete Linux userspace is +still classified as dormant. + +`scripts/build-guanghu-first-boot-initramfs.sh` builds a candidate without +changing the installed initramfs, GRUB, disk, or boot default. Path overrides +are accepted only inside the isolated test harness. The source contract and +fixture test do not prove that a Guanghu supervisor remains alive across +`switch_root`; independent first-boot control, physical deployment, and full +on-demand Linux subcontrol therefore remain `0` until separate QEMU and JD +receipts exist. See ADR-0176. + ## Language-primary boot target `guanghu-language-primary.target` makes the accepted cognitive-control model diff --git a/product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/first-boot-supervisor.conf.example b/product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/first-boot-supervisor.conf.example new file mode 100644 index 000000000..6ba553fce --- /dev/null +++ b/product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/first-boot-supervisor.conf.example @@ -0,0 +1,6 @@ +schema=guanghu.first-boot-supervisor/v1 +node_id=JD-FD-PRIMARY +instance_id=f3d4b730-7f02-452f-975b-7091a4800431 +root_uuid=9e4550a0-452b-4f28-b5a5-d5364aa450f6 +linux_rescue_entry=gnulinux-simple-9e4550a0-452b-4f28-b5a5-d5364aa450f6 +linux_code_bridge=hlcc-jd-candidate.service diff --git a/product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/hooks/guanghu-first-boot-supervisor b/product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/hooks/guanghu-first-boot-supervisor new file mode 100755 index 000000000..7cf7710b5 --- /dev/null +++ b/product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/hooks/guanghu-first-boot-supervisor @@ -0,0 +1,17 @@ +#!/bin/sh +set -eu + +PREREQ="" +prereqs() { echo "${PREREQ}"; } +case "${1:-}" in prereqs) prereqs; exit 0 ;; esac + +. /usr/share/initramfs-tools/hook-functions + +: "${GUANGHU_FIRST_BOOT_SUPERVISOR_SOURCE:?supervisor source is required}" +: "${GUANGHU_FIRST_BOOT_CONFIG_SOURCE:?configuration source is required}" +: "${GUANGHU_FIRST_BOOT_GRUB_SOURCE:?GRUB snapshot source is required}" + +copy_exec "${GUANGHU_FIRST_BOOT_SUPERVISOR_SOURCE}" /usr/lib/guanghu/guanghu-first-boot-supervisor +copy_file config "${GUANGHU_FIRST_BOOT_CONFIG_SOURCE}" /etc/guanghu/first-boot-supervisor.conf +copy_file config "${GUANGHU_FIRST_BOOT_GRUB_SOURCE}" /etc/guanghu/grub.cfg.snapshot +chmod 0600 "${DESTDIR}/etc/guanghu/first-boot-supervisor.conf" diff --git a/product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/scripts/local-premount/guanghu-first-boot-supervisor b/product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/scripts/local-premount/guanghu-first-boot-supervisor new file mode 100755 index 000000000..6bed8fa24 --- /dev/null +++ b/product-source/hololake-platform/guanghu-os/packaging/initramfs-tools/scripts/local-premount/guanghu-first-boot-supervisor @@ -0,0 +1,13 @@ +#!/bin/sh +set -eu + +PREREQ="" +prereqs() { echo "${PREREQ}"; } +case "${1:-}" in prereqs) prereqs; exit 0 ;; esac + +. /scripts/functions + +if ! /usr/lib/guanghu/guanghu-first-boot-supervisor pre-root; then + panic "Guanghu pre-root authority validation failed; refusing root handoff" + exit 1 +fi diff --git a/product-source/hololake-platform/guanghu-os/scripts/build-guanghu-first-boot-initramfs.sh b/product-source/hololake-platform/guanghu-os/scripts/build-guanghu-first-boot-initramfs.sh new file mode 100755 index 000000000..a247101ca --- /dev/null +++ b/product-source/hololake-platform/guanghu-os/scripts/build-guanghu-first-boot-initramfs.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +[[ $# -ge 3 && $# -le 4 ]] || { + echo "usage: build-guanghu-first-boot-initramfs.sh [kernel-version]" >&2 + exit 64 +} + +output=$(readlink -m "$1") +config=$(readlink -f "$2") +grub_snapshot=$(readlink -f "$3") +kernel_version=${4:-$(uname -r)} +source_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +supervisor=${source_root}/scripts/guanghu-first-boot-supervisor.sh +packaging=${source_root}/packaging/initramfs-tools + +command -v mkinitramfs >/dev/null +[[ -r /etc/initramfs-tools/initramfs.conf ]] || { + echo "host initramfs configuration is unavailable" >&2 + exit 1 +} +[[ -f ${config} && ! -L ${config} ]] || { + echo "first-boot configuration is missing or unsafe" >&2 + exit 1 +} +[[ -f ${grub_snapshot} && ! -L ${grub_snapshot} ]] || { + echo "GRUB snapshot is missing or unsafe" >&2 + exit 1 +} +grep -Fqx 'schema=guanghu.first-boot-supervisor/v1' "${config}" +grep -Fq 'gnulinux-simple-' "${grub_snapshot}" + +build_root=$(mktemp -d) +trap 'rm -rf "${build_root}"' EXIT +mkdir -p "${build_root}/conf.d" "${build_root}/hooks" \ + "${build_root}/scripts/local-premount" \ + "$(dirname "${output}")" +install -m 0644 /etc/initramfs-tools/initramfs.conf "${build_root}/initramfs.conf" +install -m 0644 /dev/null "${build_root}/modules" +cp "${packaging}/hooks/guanghu-first-boot-supervisor" "${build_root}/hooks/" +cp "${packaging}/scripts/local-premount/guanghu-first-boot-supervisor" \ + "${build_root}/scripts/local-premount/" +chmod 0755 "${build_root}/hooks/guanghu-first-boot-supervisor" \ + "${build_root}/scripts/local-premount/guanghu-first-boot-supervisor" + +export GUANGHU_FIRST_BOOT_SUPERVISOR_SOURCE=${supervisor} +export GUANGHU_FIRST_BOOT_CONFIG_SOURCE=${config} +export GUANGHU_FIRST_BOOT_GRUB_SOURCE=${grub_snapshot} +mkinitramfs -d "${build_root}" -o "${output}" "${kernel_version}" +chmod 0600 "${output}" +sha256sum "${output}" >"${output}.sha256" +printf 'GUANGHU_FIRST_BOOT_INITRAMFS_BUILT kernel=%s output=%s\n' \ + "${kernel_version}" "${output}" diff --git a/product-source/hololake-platform/guanghu-os/scripts/guanghu-first-boot-supervisor.sh b/product-source/hololake-platform/guanghu-os/scripts/guanghu-first-boot-supervisor.sh new file mode 100755 index 000000000..991272134 --- /dev/null +++ b/product-source/hololake-platform/guanghu-os/scripts/guanghu-first-boot-supervisor.sh @@ -0,0 +1,127 @@ +#!/bin/sh +set -eu + +die() { + printf 'GUANGHU_FIRST_BOOT_SUPERVISOR_FAIL_0: %s\n' "$1" >&2 + exit 1 +} + +test_root=${GUANGHU_FIRST_BOOT_TEST_ROOT:-} +if [ -n "${test_root}" ]; then + test_root=$(readlink -f "${test_root}") + [ -d "${test_root}" ] || die "test root is unavailable" + config_path=${GUANGHU_FIRST_BOOT_CONFIG:-} + state_root=${GUANGHU_FIRST_BOOT_STATE_ROOT:-} + dmi_path=${GUANGHU_FIRST_BOOT_DMI_PATH:-} + cmdline_path=${GUANGHU_FIRST_BOOT_CMDLINE_PATH:-} + boot_id_path=${GUANGHU_FIRST_BOOT_BOOT_ID_PATH:-} + grub_path=${GUANGHU_FIRST_BOOT_GRUB_PATH:-} + for override_path in "${config_path}" "${state_root}" "${dmi_path}" \ + "${cmdline_path}" "${boot_id_path}" "${grub_path}"; do + resolved_path=$(readlink -f "${override_path}") + case "${resolved_path}" in + "${test_root}"|"${test_root}"/*) ;; + *) die "test path escapes the isolated root" ;; + esac + done +else + [ -z "${GUANGHU_FIRST_BOOT_CONFIG:-}${GUANGHU_FIRST_BOOT_STATE_ROOT:-}${GUANGHU_FIRST_BOOT_DMI_PATH:-}${GUANGHU_FIRST_BOOT_CMDLINE_PATH:-}${GUANGHU_FIRST_BOOT_BOOT_ID_PATH:-}${GUANGHU_FIRST_BOOT_GRUB_PATH:-}" ] || + die "production path overrides are forbidden" + config_path=/etc/guanghu/first-boot-supervisor.conf + state_root=/run/guanghu/first-boot + dmi_path=/sys/class/dmi/id/product_uuid + cmdline_path=/proc/cmdline + boot_id_path=/proc/sys/kernel/random/boot_id + grub_path=/etc/guanghu/grub.cfg.snapshot +fi + +[ -f "${config_path}" ] && [ ! -L "${config_path}" ] || die "configuration is missing or unsafe" +mode=$(stat -c '%a' "${config_path}" 2>/dev/null || stat -f '%Lp' "${config_path}") +[ "${mode}" = 600 ] || die "configuration mode must be 0600" +if [ -z "${test_root}" ]; then + owner=$(stat -c '%u' "${config_path}" 2>/dev/null || stat -f '%u' "${config_path}") + [ "${owner}" = 0 ] || die "configuration must be root-owned" +fi + +schema= +node_id= +instance_id= +root_uuid= +linux_rescue_entry= +linux_code_bridge= +while IFS='=' read -r key value; do + case "${key}" in + schema) schema=${value} ;; + node_id) node_id=${value} ;; + instance_id) instance_id=${value} ;; + root_uuid) root_uuid=${value} ;; + linux_rescue_entry) linux_rescue_entry=${value} ;; + linux_code_bridge) linux_code_bridge=${value} ;; + ''|'#'*) ;; + *) die "unknown configuration field ${key}" ;; + esac +done <"${config_path}" + +[ "${schema}" = 'guanghu.first-boot-supervisor/v1' ] || die "configuration schema mismatch" +[ "${node_id}" = 'JD-FD-PRIMARY' ] || die "node identity mismatch" +printf '%s' "${instance_id}" | grep -Eq '^[0-9a-f-]{36}$' || die "instance id is malformed" +printf '%s' "${root_uuid}" | grep -Eq '^[0-9a-f-]{36}$' || die "root UUID is malformed" +printf '%s' "${linux_rescue_entry}" | grep -Eq '^gnulinux-simple-[0-9a-f-]{36}$' || die "rescue entry is malformed" +printf '%s' "${linux_code_bridge}" | grep -Eq '^[A-Za-z0-9_.@-]+\.service$' || die "code bridge unit is malformed" + +[ -r "${dmi_path}" ] || die "DMI identity is unavailable" +observed_instance=$(tr 'A-F' 'a-f' <"${dmi_path}" | tr -d '\r\n') +[ "${observed_instance}" = "${instance_id}" ] || die "DMI identity mismatch" +[ -r "${cmdline_path}" ] || die "kernel command line is unavailable" +cmdline=$(cat "${cmdline_path}") +case " ${cmdline} " in *' guanghu.first_boot=1 '*) ;; *) die "explicit first-boot marker is missing" ;; esac +case " ${cmdline} " in *" root=UUID=${root_uuid} "*) ;; *) die "root UUID binding is missing" ;; esac +[ -r "${grub_path}" ] || die "embedded rescue snapshot is unavailable" +grep -Fq "${linux_rescue_entry}" "${grub_path}" || die "Linux rescue entry is not preserved" +[ -r "${boot_id_path}" ] || die "boot id is unavailable" +boot_id=$(tr -d '\r\n' <"${boot_id_path}") +printf '%s' "${boot_id}" | grep -Eq '^[0-9a-f-]{36}$' || die "boot id is malformed" + +mkdir -p "${state_root}" +handoff_path=${state_root}/handoff.json + +write_handoff() { + temporary_path=${handoff_path}.tmp.$$ + printf '%s\n' \ + "{\"schema\":\"guanghu.first-boot-handoff/v1\",\"node_id\":\"${node_id}\",\"instance_id\":\"${instance_id}\",\"boot_id\":\"${boot_id}\",\"control\":\"GUANGHU_OS\",\"stage\":\"PRE_ROOT_SUPERVISOR_ACTIVE\",\"linux_kernel_role\":\"HARDWARE_COMPATIBILITY_SUBSTRATE\",\"full_linux_userspace\":\"DORMANT\",\"linux_code_bridge\":\"PENDING_BOUNDED_HANDOFF\",\"linux_rescue\":\"${linux_rescue_entry}\"}" \ + >"${temporary_path}" + chmod 0600 "${temporary_path}" + mv "${temporary_path}" "${handoff_path}" +} + +verify_handoff() { + [ -f "${handoff_path}" ] && [ ! -L "${handoff_path}" ] || die "first-boot handoff is missing or unsafe" + handoff=$(cat "${handoff_path}") + for binding in \ + '"schema":"guanghu.first-boot-handoff/v1"' \ + "\"node_id\":\"${node_id}\"" \ + "\"instance_id\":\"${instance_id}\"" \ + "\"boot_id\":\"${boot_id}\"" \ + '"control":"GUANGHU_OS"' \ + '"stage":"PRE_ROOT_SUPERVISOR_ACTIVE"' \ + '"full_linux_userspace":"DORMANT"' \ + '"linux_code_bridge":"PENDING_BOUNDED_HANDOFF"' \ + "\"linux_rescue\":\"${linux_rescue_entry}\""; do + printf '%s' "${handoff}" | grep -Fq "${binding}" || die "handoff binding mismatch" + done +} + +case "${1:-}" in + pre-root) + write_handoff + verify_handoff + printf 'GUANGHU_FIRST_BOOT_SUPERVISOR_ACTIVE node=%s boot_id=%s linux_userspace=DORMANT\n' \ + "${node_id}" "${boot_id}" + ;; + verify-handoff) + verify_handoff + printf 'GUANGHU_FIRST_BOOT_HANDOFF_VERIFIED node=%s boot_id=%s\n' \ + "${node_id}" "${boot_id}" + ;; + *) die "usage: guanghu-first-boot-supervisor " ;; +esac diff --git a/product-source/hololake-platform/guanghu-os/scripts/test-guanghu-first-boot-supervisor.sh b/product-source/hololake-platform/guanghu-os/scripts/test-guanghu-first-boot-supervisor.sh new file mode 100755 index 000000000..5cdad64da --- /dev/null +++ b/product-source/hololake-platform/guanghu-os/scripts/test-guanghu-first-boot-supervisor.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +source_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +supervisor=${source_root}/scripts/guanghu-first-boot-supervisor.sh +hook=${source_root}/packaging/initramfs-tools/hooks/guanghu-first-boot-supervisor +premount=${source_root}/packaging/initramfs-tools/scripts/local-premount/guanghu-first-boot-supervisor +builder=${source_root}/scripts/build-guanghu-first-boot-initramfs.sh +fixture=$(mktemp -d) +trap 'rm -rf "${fixture}"' EXIT + +mkdir -p "${fixture}/proc/sys/kernel/random" "${fixture}/dmi" \ + "${fixture}/grub" "${fixture}/run" +printf '%s\n' 'f3d4b730-7f02-452f-975b-7091a4800431' >"${fixture}/dmi/product_uuid" +printf '%s\n' '68d4a3c9-c866-4f4a-be2e-0aa5f41a61b1' \ + >"${fixture}/proc/sys/kernel/random/boot_id" +printf '%s\n' \ + 'console=ttyS0 guanghu.first_boot=1 root=UUID=9e4550a0-452b-4f28-b5a5-d5364aa450f6 ro' \ + >"${fixture}/proc/cmdline" +printf '%s\n' \ + "menuentry 'Ubuntu rescue' 'gnulinux-simple-9e4550a0-452b-4f28-b5a5-d5364aa450f6'" \ + >"${fixture}/grub/grub.cfg" +cat >"${fixture}/supervisor.conf" <<'EOF' +schema=guanghu.first-boot-supervisor/v1 +node_id=JD-FD-PRIMARY +instance_id=f3d4b730-7f02-452f-975b-7091a4800431 +root_uuid=9e4550a0-452b-4f28-b5a5-d5364aa450f6 +linux_rescue_entry=gnulinux-simple-9e4550a0-452b-4f28-b5a5-d5364aa450f6 +linux_code_bridge=hlcc-jd-candidate.service +EOF +chmod 0600 "${fixture}/supervisor.conf" + +env \ + GUANGHU_FIRST_BOOT_TEST_ROOT="${fixture}" \ + GUANGHU_FIRST_BOOT_CONFIG="${fixture}/supervisor.conf" \ + GUANGHU_FIRST_BOOT_STATE_ROOT="${fixture}/run" \ + GUANGHU_FIRST_BOOT_DMI_PATH="${fixture}/dmi/product_uuid" \ + GUANGHU_FIRST_BOOT_CMDLINE_PATH="${fixture}/proc/cmdline" \ + GUANGHU_FIRST_BOOT_BOOT_ID_PATH="${fixture}/proc/sys/kernel/random/boot_id" \ + GUANGHU_FIRST_BOOT_GRUB_PATH="${fixture}/grub/grub.cfg" \ + "${supervisor}" pre-root + +python3 - "${fixture}/run/handoff.json" <<'PY' +import json +import pathlib +import sys + +state = json.loads(pathlib.Path(sys.argv[1]).read_text()) +assert state == { + "schema": "guanghu.first-boot-handoff/v1", + "node_id": "JD-FD-PRIMARY", + "instance_id": "f3d4b730-7f02-452f-975b-7091a4800431", + "boot_id": "68d4a3c9-c866-4f4a-be2e-0aa5f41a61b1", + "control": "GUANGHU_OS", + "stage": "PRE_ROOT_SUPERVISOR_ACTIVE", + "linux_kernel_role": "HARDWARE_COMPATIBILITY_SUBSTRATE", + "full_linux_userspace": "DORMANT", + "linux_code_bridge": "PENDING_BOUNDED_HANDOFF", + "linux_rescue": "gnulinux-simple-9e4550a0-452b-4f28-b5a5-d5364aa450f6", +} +PY + +env \ + GUANGHU_FIRST_BOOT_TEST_ROOT="${fixture}" \ + GUANGHU_FIRST_BOOT_CONFIG="${fixture}/supervisor.conf" \ + GUANGHU_FIRST_BOOT_STATE_ROOT="${fixture}/run" \ + GUANGHU_FIRST_BOOT_DMI_PATH="${fixture}/dmi/product_uuid" \ + GUANGHU_FIRST_BOOT_CMDLINE_PATH="${fixture}/proc/cmdline" \ + GUANGHU_FIRST_BOOT_BOOT_ID_PATH="${fixture}/proc/sys/kernel/random/boot_id" \ + GUANGHU_FIRST_BOOT_GRUB_PATH="${fixture}/grub/grub.cfg" \ + "${supervisor}" verify-handoff + +cp "${fixture}/proc/cmdline" "${fixture}/proc/cmdline.good" +printf '%s\n' 'console=ttyS0 root=UUID=9e4550a0-452b-4f28-b5a5-d5364aa450f6 ro' \ + >"${fixture}/proc/cmdline" +if env \ + GUANGHU_FIRST_BOOT_TEST_ROOT="${fixture}" \ + GUANGHU_FIRST_BOOT_CONFIG="${fixture}/supervisor.conf" \ + GUANGHU_FIRST_BOOT_STATE_ROOT="${fixture}/run" \ + GUANGHU_FIRST_BOOT_DMI_PATH="${fixture}/dmi/product_uuid" \ + GUANGHU_FIRST_BOOT_CMDLINE_PATH="${fixture}/proc/cmdline" \ + GUANGHU_FIRST_BOOT_BOOT_ID_PATH="${fixture}/proc/sys/kernel/random/boot_id" \ + GUANGHU_FIRST_BOOT_GRUB_PATH="${fixture}/grub/grub.cfg" \ + "${supervisor}" pre-root >/dev/null 2>&1; then + echo "first-boot supervisor accepted a boot without its explicit kernel marker" >&2 + exit 1 +fi +mv "${fixture}/proc/cmdline.good" "${fixture}/proc/cmdline" + +if GUANGHU_FIRST_BOOT_CONFIG="${fixture}/supervisor.conf" \ + "${supervisor}" pre-root >/dev/null 2>&1; then + echo "production mode accepted path overrides" >&2 + exit 1 +fi + +grep -Fq 'copy_exec "${GUANGHU_FIRST_BOOT_SUPERVISOR_SOURCE}" /usr/lib/guanghu/guanghu-first-boot-supervisor' "${hook}" +grep -Fq '. /scripts/functions' "${premount}" +grep -Fq 'if ! /usr/lib/guanghu/guanghu-first-boot-supervisor pre-root; then' "${premount}" +grep -Fq 'panic "Guanghu pre-root authority validation failed; refusing root handoff"' "${premount}" +grep -Fq 'PREREQ=""' "${premount}" +grep -Fq 'install -m 0644 /etc/initramfs-tools/initramfs.conf "${build_root}/initramfs.conf"' "${builder}" +grep -Fq 'install -m 0644 /dev/null "${build_root}/modules"' "${builder}" + +echo GUANGHU_FIRST_BOOT_SUPERVISOR_CONTRACT_OK diff --git a/product-source/hololake-platform/guanghu-os/world-seed/scripts/run-guanghu-native-quality-gate.sh b/product-source/hololake-platform/guanghu-os/world-seed/scripts/run-guanghu-native-quality-gate.sh index 3d000d113..178f85ba7 100755 --- a/product-source/hololake-platform/guanghu-os/world-seed/scripts/run-guanghu-native-quality-gate.sh +++ b/product-source/hololake-platform/guanghu-os/world-seed/scripts/run-guanghu-native-quality-gate.sh @@ -94,6 +94,8 @@ run_gate shell_syntax bash -c \ _ "${source_root}" run_gate linux_subcontrol_docker_backend \ "${source_root}/scripts/test-linux-subcontrol-docker-backend.sh" +run_gate guanghu_first_boot_supervisor \ + "${source_root}/scripts/test-guanghu-first-boot-supervisor.sh" run_gate auditable_line_coverage_100_percent \ bash -c ' cargo llvm-cov clean --workspace --manifest-path "$1/Cargo.toml" diff --git a/routing/guanghu-os-control-architecture.json b/routing/guanghu-os-control-architecture.json index 59d736c81..e0af22c9d 100644 --- a/routing/guanghu-os-control-architecture.json +++ b/routing/guanghu-os-control-architecture.json @@ -1,7 +1,7 @@ { "schema": "guanghu.os-control-architecture/v1", "record_id": "HLP-GUANGHU-OS-CONTROL-001", - "version": "2026-08-15.9", + "version": "2026-08-15.10", "state": "CURRENT_CANONICAL", "final_topology": "GUANGHU_MASTER_WITH_ON_DEMAND_LINUX_SUBCONTROL_AND_RESCUE", "control_ownership": { @@ -39,7 +39,7 @@ "linux_on_demand_subcontrol": 0, "linux_rescue_preserved": 100, "final_guanghu_os_master": 0, - "next_engineering_gate": "BUILD_AND_PHYSICALLY_VERIFY_INDEPENDENT_GUANGHU_FIRST_BOOT_SUPERVISOR_WITH_BOUNDED_LINUX_CODE_BRIDGE_AND_RESCUE" + "next_engineering_gate": "BUILD_AND_VERIFY_JD_HOST_QEMU_PRE_ROOT_GUANGHU_SUPERVISOR_WITHOUT_BOOT_CHANGE" }, "implementation": { "guanghu_supervisor_lifecycle_contract_source": 100, @@ -70,6 +70,9 @@ "full_forgejo_equivalence": 0, "independent_guanghu_hosted_supervisor_bridge": 100, "linux_code_bridge_under_guanghu_supervisor": 100, + "guanghu_pre_root_supervisor_contract_source": 100, + "guanghu_first_boot_initramfs_builder_source": 100, + "jd_host_qemu_pre_root_supervisor": 0, "independent_guanghu_first_boot_supervisor": 0, "jd_physical_deployment": 0 }, diff --git a/routing/guanghu-os-control-architecture.test.mjs b/routing/guanghu-os-control-architecture.test.mjs index 5708e7b7c..4b62b72a6 100644 --- a/routing/guanghu-os-control-architecture.test.mjs +++ b/routing/guanghu-os-control-architecture.test.mjs @@ -44,7 +44,7 @@ test("current JD state stays transitional and cannot impersonate final master co }); test("the physical shadow and host QEMU cycles are registered without impersonating Guanghu-owned boot control", () => { - assert.equal(contract.version, "2026-08-15.9"); + assert.equal(contract.version, "2026-08-15.10"); assert.equal(contract.implementation.guanghu_supervisor_lifecycle_contract_source, 100); assert.equal(contract.implementation.target_readback_and_mandatory_reclaim_state_machine, 100); assert.equal(contract.implementation.declared_supervisor_core_line_and_function_coverage, 100); @@ -72,6 +72,9 @@ test("the physical shadow and host QEMU cycles are registered without impersonat assert.equal(contract.implementation.full_forgejo_equivalence, 0); assert.equal(contract.implementation.independent_guanghu_hosted_supervisor_bridge, 100); assert.equal(contract.implementation.linux_code_bridge_under_guanghu_supervisor, 100); + assert.equal(contract.implementation.guanghu_pre_root_supervisor_contract_source, 100); + assert.equal(contract.implementation.guanghu_first_boot_initramfs_builder_source, 100); + assert.equal(contract.implementation.jd_host_qemu_pre_root_supervisor, 0); assert.equal(contract.implementation.independent_guanghu_first_boot_supervisor, 0); assert.equal(contract.implementation.jd_physical_deployment, 0); assert.equal(contract.current_target_evidence.final_state, "DORMANT");