Files
qinglong/docs/adr/ADR-0205-physical-edge-init-managed-service-start-evidence.md
T

6.9 KiB
Raw Blame History

ADR-0205:物理 Edge Init-managed Service 首次 Active 候选证据

  • 状态:Accepted
  • 日期:2026-07-29
  • 关联 RFCQL-RFC-0001 D-86、D-87、D-175、D-194、D-195
  • 关联 ADRADR-0088、ADR-0193、ADR-0194、ADR-0204

背景

ADR-0204 已证明不同 Linux boot 中,最终 AI-excluded native application closure 可以从 recorder spawn() 到唯一正式 active,但 recorder 本身已经加载 Node 也没有经过 systemd/OpenRC。它因此仍把 power_on_cold_node_and_service_manager_start_to_first_ready 保留为 broad Gate。

完整 firmware 上电时间不能从 Linux 用户态可靠取得。/proc/uptime 从 Linux 内核时钟开始,不包含 bootloader/firmware;安全实现必须拆开这一边界,而不是把 kernel uptime 改名为 power-on latency。

决策

1. 新增非 package、无自动整机 authority 的三阶段记录器

根命令 evidence:physical-edge-service-start 提供:

  • inspect:复用 ADR-0204 的 exact 12-package artifact 与 Node inventory
  • prepare:创建 fresh Edge deployment、证据 wrapper、FIFO 和 digest-bound session
  • resume:只读核验新 boot、init 状态、进程身份和正式 active 后发布 report。

记录器不新增 workspace package、生产依赖、daemon、timer、watcher、端口或 Cluster import。它绝不执行 installsystemctl enable/startrc-updaterc-service start、reboot、poweroff、stop、disable 或文件清理。

2. Operator 必须显式安装并启用 exact descriptor

prepare 使用正式 prepareLocalDeployment

  • Profile 固定为 Edge
  • service kind 由 manifest 固定为 systemd|openrc
  • 仍使用 production renderer 的 User/Group、WorkingDirectory、resource limit、 SIGTERM、restart 和 hardening contract
  • systemd 的 probe 目录位于 deployment root 内,满足 ProtectSystem=strict + ReadWritePaths=<deploymentRoot>

prepare 输出而不执行:

  • descriptor source/destination 与 SHA-256
  • /usr/bin/install 的逐参数 invocation
  • systemctl enable <unit>rc-update add <service> default 的逐参数 invocation。

session 精确绑定这些参数、目标 mode、service name、status manager 与 enable executable/hash、wrapper hash、artifact/Node、UID、prepare boot 和所有 scratch path。systemd 两者都是 systemctlOpenRC 分别是 rc-servicerc-update。 operator 审查后以 root 安装/enable,再在工具外正常重启。resume 要求目标 descriptor 为 root-owned、single-link、exact mode/content。

3. POSIX wrapper 在 Node 之前建立时间锚点

证据 wrapper 是私有 0700 POSIX shell 文件。它在执行 Node 之前:

  1. 复验 exact node --config <path> 参数和已准备 FIFO
  2. /proc/sys/kernel/random/boot_id/proc/uptime 读取 boot/start
  3. 以 noclobber 创建 0600 start/event/stderr 文件;
  4. 才启动 exact Node binary、正式 @qinglong/local-application/dist/cli.js 和 production config。

wrapper 逐行复制 application stdout。遇到同时包含正式 component/event/Profile/ AI status 的候选行时,立即读取同一 /proc/uptime,以 event ordinal 发布一次性 active record。resume 使用 Node exact JSON parser 重新验证整个 event log、唯一 active 和 ordinalshell substring 不能自行形成通过结论。第二个 active、已有 record、partial JSON、非零 stderr 或 boot/monotonic 逆序均失败关闭。

wrapper 不是旁路 daemon:它就是 evidence service 的 main process,转发终止信号, 并等待唯一 Node child。systemd 必须把 wrapper PID 报为 MainPIDOpenRC 必须由 rc-service status 和 default runlevel 同时证明 active/enabled。

4. Resume 必须复验实时 service 与进程树

resume 在读取报告文件前要求:

  • 与 prepare 不同且与 wrapper record 相同的 boot ID
  • 当前 boot age、架构、文件系统、UID、Node 和 manifest 一致;
  • virtualizationIndicators 为空,容器/VM 直接拒绝;
  • artifact metadata、wrapper、manager 和 installed descriptor 未漂移;
  • systemd loaded/active/running/enabled、exact FragmentPath/MainPID,或 OpenRC active + default runlevel
  • wrapper/node PID 仍存活,Node PPid 为 wrapperUID、/proc/exe 与完整 cmdline 精确匹配。

最后重算完整 artifact content。报告记录:

  • serviceStartBootAgeMs
  • activeBootAgeMs / bootToActiveMs
  • serviceStartToActiveMs
  • active event ordinal 和 live process start ticks。

所有三项时延都必须落在 manifest 的显式预算内。report 与统一 importer 都重新 计算 qualification,不能信任报告自带 passed:true

5. 结论继续保持候选与窄作用域

通过的报告增加:

kernel_boot_to_init_managed_native_application_active

并把 broad Gate 细化为仍未完成的:

  • firmware_and_bootloader_power_on_to_linux_kernel_clock
  • direct_release_unit_without_evidence_wrapper

报告永久 supported:false,并明确不证明 exclusive cold page cache/dynamic linker provenance、active 前 RSS/I/O、service stop/disable、突然断电、Compose、 Standalone/Cluster 或 release attestation。证据 wrapper 将测得时延作为安全上界, 但它不是最终直连 Node 的 release unit;必须保留 equivalence Gate。

验收证据

  • Linux recorder manifest/CLI/wrapper/session/record/init/report/POSIX syntax/OpenRC executable split/virtualization/FIFO-child 契约 13/13
  • importer same-device/current-boot/qualification 再裁决与 remaining Gate 细化 3/3
  • importer 3/3Linux 专项合计 16/16macOS 为 12 pass/1 条件 skip
  • exact Node 24.18.0 bookworm-slim digest 在只读 rootfs、无网络、cap-drop、 no-new-privileges、128 MiB/64 PID 下完成真实 FIFO、active ordinal 和 SIGTERM wrapper smoke;该容器只证明脚本兼容,不是物理/init 报告;
  • wrapper 静态门不含 reboot/poweroff/systemctl/rc-service/rc-update/sudo
  • 实现不新增 workspace package、生产依赖或常驻采集资源。

macOS 开发机不能运行 Linux PID 1、/proc 和真实 enable/reboot,所以没有产生 物理报告。Accepted 只表示协议、采集器和失败关闭门已实现;固定 systemd/OpenRC 设备的 operator install/reboot/resume 仍是发布候选 Gate。

被拒绝的替代方案

  • 使用 Date.now() 作为 power-on 时间:墙钟可跳变,也没有 firmware 起点。
  • 由 Node recorder 在 reboot 后启动 NodeNode 已被 recorder 自己预热。
  • 自动安装/enable/reboot:扩大整机破坏 authority,且不能保留人工审查边界。
  • 只读取 journal 文本时间:日志持久化、clock domain 和旧 boot 过滤不稳定。
  • 把 wrapper descriptor 称为最终 release unit:证据 shim 改变了进程树。
  • 新增 boot-agent package/daemon:增加低配 Edge 的交付和常驻成本。