Define self update task (T-403)

This commit is contained in:
ila
2026-07-19 21:42:23 +08:00
parent 339beaa9b3
commit 2900deba4f
3 changed files with 72 additions and 5 deletions
+2 -2
View File
@@ -47,7 +47,7 @@ SoftBox 软件盒子是一个使用 Go + Gio 开发的 Windows 桌面客户端,
## 当前阶段
当前项目已完成 Phase 0~2、T-301~T-303、T-615 与审核整改 `T-604`~`T-614`。Windows 安全路径阻断项、图标缓存资源边界、后台结果回 UI 线程的事件接线、双适配器交互契约、`VisibleItems` 快照生命周期、双端 Gio shell 职责拆分、unsafe cache 安全诊断/runbook、ZIP 中央目录/EOCD(含 ZIP64)预扫描、安装文件/目录/journal 的代码层耐久顺序、Catalog canonicalization/签名静态 corpus,以及同句柄 Catalog size/SHA→严格 app.json→staging/switch/回滚安装链均已关闭;T-303 已将 verified-package 的 staging 前磁盘/运行状态预检和稳定失败码落实到 core,T-615 已将 ZIP 输入/staging 输出 I/O 分界、平台磁盘满分类和清理失败恢复落实到 core。T-401 已完成完整路径进程检测、受控启动和 Switcher 临界区复查;T-402 已完成子软件更新的确认关闭、自然退出等待和可信安装器编排。下一步正式落成 T-403。物理断电、文件锁与杀毒软件干扰验证保留到 T-601 发布前环境验证。
当前项目已完成 Phase 0~2、T-301~T-303、T-615 与审核整改 `T-604`~`T-614`。Windows 安全路径阻断项、图标缓存资源边界、后台结果回 UI 线程的事件接线、双适配器交互契约、`VisibleItems` 快照生命周期、双端 Gio shell 职责拆分、unsafe cache 安全诊断/runbook、ZIP 中央目录/EOCD(含 ZIP64)预扫描、安装文件/目录/journal 的代码层耐久顺序、Catalog canonicalization/签名静态 corpus,以及同句柄 Catalog size/SHA→严格 app.json→staging/switch/回滚安装链均已关闭;T-303 已将 verified-package 的 staging 前磁盘/运行状态预检和稳定失败码落实到 core,T-615 已将 ZIP 输入/staging 输出 I/O 分界、平台磁盘满分类和清理失败恢复落实到 core。T-401 已完成完整路径进程检测、受控启动和 Switcher 临界区复查;T-402 已完成子软件更新编排;T-403 已正式落成,下一步实现 SoftBox 自更新助手、健康确认与恢复。物理断电、文件锁与杀毒软件干扰验证保留到 T-601 发布前环境验证。
优先路径:
@@ -55,7 +55,7 @@ SoftBox 软件盒子是一个使用 Go + Gio 开发的 Windows 桌面客户端,
2. 已完成 Phase 1:清单验签、ZIP 安全解压、原子切换回滚原型。
3. 已完成 Phase 2 与 T-301:清单/列表/详情/图标缓存 + 可恢复下载队列。
4. 已完成 T-604:modern/Win7 workspace 与 Gio 版本解析彻底隔离。
5. 已完成 T-606~T-615:图标缓存资源边界、UI 线程事件接线、双 Gio 适配器交互契约、`VisibleItems` generation 生命周期、双端 `shell.go` 同 package 镜像职责拆分、unsafe cache 诊断/人工恢复指引、ZIP 中央目录/EOCD 预扫描、安装耐久顺序、Catalog 静态签名向量,以及 staging 输出 I/O 根因与磁盘满诊断;已完成 T-302/T-303:已验签 Catalog 选择与同句柄 size/SHA、严格 app.json、安全 staging/switch/健康与记录写回滚链路,以及 staging 前磁盘/运行状态预检与稳定失败码。T-401 已完成进程检测、受控启动与切换临界区复查;T-402 已完成关闭确认、自然退出等待和更新编排;下一步正式落成 T-403。T-601 仍须补真实 Windows 环境的断电/干扰注入。
5. 已完成 T-606~T-615:图标缓存资源边界、UI 线程事件接线、双 Gio 适配器交互契约、`VisibleItems` generation 生命周期、双端 `shell.go` 同 package 镜像职责拆分、unsafe cache 诊断/人工恢复指引、ZIP 中央目录/EOCD 预扫描、安装耐久顺序、Catalog 静态签名向量,以及 staging 输出 I/O 根因与磁盘满诊断;已完成 T-302/T-303:已验签 Catalog 选择与同句柄 size/SHA、严格 app.json、安全 staging/switch/健康与记录写回滚链路,以及 staging 前磁盘/运行状态预检与稳定失败码。T-401 已完成进程检测、受控启动与切换临界区复查;T-402 已完成关闭确认、自然退出等待和更新编排;T-403 已正式落成,当前执行 SoftBoxUpdater 自更新与健康恢复;完成后进入 Phase 5。T-601 仍须补真实 Windows 环境的断电/干扰注入。
## 领取任务规则
+3 -3
View File
@@ -22,14 +22,14 @@
- 标准启动路径:`./init.sh` / `./init.ps1`(同步依赖、执行完整 Phase 0 闸门、打印双目标构建命令)
- 标准验证路径:`bash scripts/verify_phase0.sh` / `./scripts/verify_phase0.ps1`
- 版本管理:git 已初始化,main 分支,远端 origin 为 Gitea `opc/soft_quay`;harness 文档已提交
- 当前 blocker:可正式落成 T-403。下载 completed 文件的生产消费、许可证策略与完整端到端 cmd/UI 编排仍未装配;T-402 因而没有注入 allow-all 授权或伪装更新闭环。T-614 的外部 `softbox-catalog` 消费 corpus CI 证据仍需跨仓库协调;物理断电、文件锁/杀毒软件干扰仍需 T-601 的目标 Windows VM/真机故障注入
- 当前 blocker:T-403 已正式落成,当前执行 SoftBoxUpdater 的受限 CLI、主 PID 自然退出、健康确认和可恢复自更新事务。可信自更新包下载/签名、许可证策略与完整端到端 cmd/UI 编排仍未装配;不得为此执行未验证 staging 或伪装自更新闭环。T-614 的外部 `softbox-catalog` 消费 corpus CI 证据仍需跨仓库协调;物理断电、文件锁/杀毒软件干扰仍需 T-601 的目标 Windows VM/真机故障注入
## 当前目录要点
| 路径 | 状态 | 说明 |
| --- | --- | --- |
| `docs/` | 已有 | harness coding 文档集(本次初始化完成) |
| `docs/tasks/` | 已有 | Phase 0~2、T-301~T-303、T-604~T-615、T-401 与 T-402 已完成;下一项为 T-403 |
| `docs/tasks/` | 已有 | Phase 0~2、T-301~T-303、T-604~T-615、T-401 与 T-402 已完成;T-403 已正式落成,正在执行 |
| `scripts/` | 已有 | harness 治理、core 边界、Go 版本检查与 Phase 0 双平台验证入口 |
| `core/` | 已建 | Go 1.20 兼容;已有正式 Catalog、本地状态/存储、共享 Windows safepath、列表模型、有界并发图标缓存、图标事件/relay、可恢复下载队列与 Phase 1 安装安全原型 |
| `app-modern/` | 已建 | Go 1.25.0 + Gio v0.10.1;Modern AppShell 已接入虚拟列表、详情、图标事件 drain/过期拒绝和内存 ImageOp,并拆为五类 shell 职责文件 |
@@ -43,7 +43,7 @@
- 已完成:Phase 0 的 `T-001`~`T-004`;Phase 1 的 `T-101`、`T-102`、`T-103`;Phase 2 的 `T-201`~`T-204`;Phase 3 的 `T-301`~`T-303` 与 `T-615`;审核整改 `T-604`~`T-614`;Phase 4 的 `T-401`、`T-402`。
- 正在进行:无。
- 正在准备领取:T-403(依赖 T-402 已完成);应先正式落成并提交该任务,再开始 SoftBox 自身更新实现。T-601 的物理断电与干扰故障注入仍保留为发布前环境验证。
- 正在进行:T-403(依赖 T-402 已完成);完成、验证并提交后,才可按路线图正式落成 Phase 5 的 T-501。T-601 的物理断电与干扰故障注入仍保留为发布前环境验证。
## 当前可运行内容
+67
View File
@@ -0,0 +1,67 @@
---
id: T-403
title: SoftBox 自更新助手与健康确认恢复
phase: 4
deps: [T-402]
status: TODO
created: 2026-07-19
issue: null
context_ref: null
claim_branch: null
work_branch: null
write_paths:
- docs/tasks/T-403.md
- core/updater/
- app-modern/platform/windows/
- app-win7/platform/windows/
- app-modern/cmd/softbox/
- app-win7/cmd/softbox/
- app-modern/cmd/softboxupdater/
- app-win7/cmd/softboxupdater/
- scripts/verify_phase0.ps1
- scripts/verify_phase0.sh
- docs/api.md
- docs/03-tech-stack.md
- docs/04-architecture.md
- docs/00-ai-start-here.md
- docs/current-state.md
---
## 问题 / 背景
Phase 4 的子软件更新已能在用户关闭子软件后安全委托既有安装事务,但 SoftBox 主程序自身不能在运行中替换 EXE。当前架构/API 只描述了 `SoftBoxUpdater.exe --pid --staging --target` 的目标形状,仓库没有独立 updater、主进程退出等待、受限自更新目录布局、健康确认或中断恢复。因此下载到 staging 的新版无法安全激活,也不能在新版未正常启动时可靠保留旧版恢复路径。
自更新更新的是盒子 `app/`,不是 `apps/<id>/`。若助手接受任意 target/staging、跟随 symlink,或把“子进程已创建”误当成健康,可能覆盖 `data/`、`licenses/` 或把不可用新版永久设为 current。当前没有可信自更新包下载/签名消费源,本任务只能提供独立、受约束的本地切换与恢复机制,不能伪称在线自更新已经接通。
## 方案
1. 新建 Go 1.20 兼容的 `core/updater`,固定布局为 `<root>/app`(target)、`<root>/staging/<request-id>`(已由可信外层准备的新目录)、`<root>/backups/<request-id>`、`self-update-transaction.json` 与健康确认文件。请求只接受正主进程 PID、safe request ID、绝对且严格满足该布局的 staging/target;逐项 `Lstat` 拒绝 symlink、非目录、交叉 root、预存 backup/journal 异常,绝不接受 UI/CLI 传入可执行参数或任意移动路径。
2. updater 先恢复上次未完成 transaction,再等待原主 PID 自然退出;取消、超时和等待错误均不触碰 target。退出后按 journal 栅栏执行 `prepared → target_backed_up → staging_activated → launched → committed`:只可把 old `app` 改名为本 request 的 backup、把同 root staging 改名为 `app`;每步用临时 JSON + 原子替换并同步目录。任何启动前/启动失败路径尝试恢复 old app;无法恢复时保留可验证 journal/backup,下一次 updater 可恢复,绝不删除 data/licenses。
3. 新版只能以已验证绝对 `<root>/app/SoftBox.exe`、固定工作目录和内部固定 `--softbox-update-health <request-id>` 参数启动。`SoftBox.exe` 在 Gio Layout 之前(非 UI goroutine I/O)从自己的可执行路径推导同一 root,校验 request ID 和 health locator 后原子写入仅含 request ID 的健康确认;不得接受路径、URL 或任意命令。助手等待匹配确认后才 committed/清理 backup;超时、错误或错误 request ID 均返回稳定失败,保留恢复材料。新版已运行但未确认且 Windows 拒绝 rollback 时 fail closed 留 journal,不强杀;后续受控 updater 在主 PID 退出后恢复。
4. 两端 `platform/windows` 增加一致的主 PID 自然退出和固定内部健康启动边界。Windows 以 `OpenProcess(SYNCHRONIZE)` + 可取消的短 `WaitForSingleObject` 轮询实现,不将无权限/不存在 PID 当作“已退出”;启动不经 shell/PATH、只传固定 health flag。非 Windows stub 明确返回不支持。clock/process/launcher seam 覆盖已退出、正常退出、取消、超时、OpenProcess/wait 错误与参数固定性。
5. 两端新增无 Gio 的 `cmd/softboxupdater`,严格解析 `--pid`、`--staging`、`--target`(内部 request ID 由助手生成),装配 core/platform 后以非 0 退出失败;主 cmd 只识别内部 health flag 并继续正常启动,不增加用户可传的任意执行入口。验证脚本同时构建主 EXE 和 Updater EXE;文档定义内部健康文件、恢复语义、真实下载/签名未装配事实与 T-601 真机限制。
## 验收要点
- core updater 拒绝非法 PID/request ID、相对/跨 root/不匹配布局、symlink/非目录、缺 staging、已有冲突 backup/journal;失败不改 target、staging、data 或 licenses。成功路径等待原 PID 退出,正确 rename/sync/journal,固定启动新 app,收到匹配 health request ID 后才 committed 并清理 backup/journal。
- PID 等待的取消、超时、OpenProcess/Wait 错误、launcher 失败、health 超时/错误 ID、每个 rename/journal 故障和崩溃注入均有稳定错误;可恢复时 old app 恢复且可启动,无法立即恢复时 journal/backup 保留供下次 `Recover`,不强杀新/旧进程。
- 新主程序只响应固定内部 health flag,从自身 `app/SoftBox.exe` 推导 root 并原子写入最小确认,不在 Gio Layout I/O;不匹配 flag/request/layout 不写文件。双端 `SoftBoxUpdater.exe` CLI 拒绝多余/无效参数,使用平台 PID 等待和固定启动调用。
- core 无 Windows/Gio/第三方依赖;双端平台 public contract 与 non-Windows stub 一致;Windows amd64 交叉编译主程序和 Updater,脚本/CI 闸门覆盖两个 EXE。真实 Windows 文件锁、杀毒/断电以及 UAC/签名发布行为仍由 T-601/T-603 验证。
- `go -C core vet ./...`、`go -C core test -count=1 ./...`、`go -C core test -count=10 ./updater`、两个主程序和 Updater 的 Windows amd64 构建、`./scripts/verify_phase0.ps1`、`python scripts/validate_agent_context.py`、`python scripts/validate_harness_governance.py` 全部通过;执行记录如实写明未装配可信自更新包下载/签名来源。
## 边界(不改什么)
- 不实现自更新 Catalog/package 下载、Ed25519 签名、SHA-256 校验、版本检查或自动触发;staging 只可由后续可信外层提供,不能把任意下载文件解压/执行。
- 不触碰 `apps/<id>/` 子软件安装事务、`data/`、`licenses/`、子软件更新、授权策略或 allow-all 注入;不实现 updater 自更新、MSI、服务、注册表、shell script、强杀、命名管道或 UI 进度窗口。
- 不把 Windows API/Gio/SQLite 引入 core,不升级 Go/Gio/依赖,不开放 `SoftBox.exe` 的用户自定义 path/args/command;内部 health flag 仅由 updater 固定生成。
- 不把单元测试等同于断电、文件锁、杀毒和 Windows VM/真机结论;这些保留 T-601/T-603。
## 协作约束
- 当前项目为单 Agent 串行模式;当前 Agent 独占全部 `write_paths`,自行完成规格、实现、审查、测试和提交,不启动子 Agent。
- 先提交本任务规格和项目快照;领取后将本文件改为 `DOING`,填写当前 HEAD 的 `context_ref` 与 `work_branch: agent/codex/T-403`,再重新记录基线和实现。
- 本任务完成后停止;后续 Phase 5 许可证任务仍需按路线图另行正式落成,不能因自更新程序存在而假定下载、签名或发布流水线已完成。
## 执行记录
- 2026-07-19:正式落成。以 T-402 完成后的 Phase 4 依赖为基线,冻结独立 updater、受限根目录、PID 自然退出、健康确认 journal 和可恢复 rollback 的最小自更新协议;明确可信 self-update 下载/签名、真机故障和发布签名继续后置。