62 lines
6.7 KiB
Markdown
62 lines
6.7 KiB
Markdown
---
|
|
id: T-302
|
|
title: 安装流程整合
|
|
phase: 3
|
|
deps: [T-301, T-102, T-103]
|
|
status: TODO
|
|
created: 2026-07-18
|
|
issue: null
|
|
context_ref: null
|
|
claim_branch: null
|
|
work_branch: null
|
|
write_paths:
|
|
- docs/tasks/T-302.md
|
|
- core/application/
|
|
- core/installer/
|
|
- core/storage/
|
|
- docs/api.md
|
|
- docs/04-architecture.md
|
|
- docs/current-state.md
|
|
---
|
|
|
|
## 问题 / 背景
|
|
|
|
T-301 只能把网络字节可靠地落为隔离的 `.download`;下载任务元数据、完成路径和文件内容仍可被本地篡改,不能直接作为安装身份或可信包。T-102/T-612/T-613 已分别具备 ZIP 预扫描/安全解压和可恢复的 `staging → current → backup` 切换原型,但尚未把已验签 Catalog、完整包 SHA-256、严格 `app.json` 身份比对、安装记录和健康失败回滚串成一个可调用的 core use case。
|
|
|
|
本任务关闭这条生产安装链的代码级信任边界。外层 Catalog 的 Ed25519 签名覆盖嵌套 `packages[arch]` 的 `size`、`sha256` 与 `signature` 字段;当前协议没有定义 package `signature` 的独立待签名字节、密钥或轮换域,T-302 不得臆造第二套包级验签。它只接受已经由 `catalog.Client` 验签、严格解析并按目标过滤后的 Catalog 选择,并以该选择中的精确 size/SHA-256 重新验证本地完成文件。
|
|
|
|
## 方案
|
|
|
|
1. 在 `core/application` 落地 `InstallService`:请求包含已过滤的 `catalog.Entry`、目标 architecture 和 `.download` 路径。服务必须拒绝不可安装 entry、缺失 package、architecture 与 `App.Packages[architecture]` 不一致的选择;不得从 `downloader.Task`、`DownloadCompletedPayload` 或本地 metadata 重新取得 app/version/size/hash。
|
|
2. 在 `core/installer` 增加经过验证的包提取入口。它以一次 `Lstat → open → fstat → Lstat` 得到普通文件句柄,先确认实际长度精确等于 Catalog size、再以**同一文件句柄**计算 SHA-256,并以常量时间比较 Catalog hash;哈希不符时不得构造 `zip.Reader`、读取 `app.json` 或创建 staging。随后仍以同一句柄完成 EOCD/ZIP64/中央目录预扫描和 `zip.Reader` 构造,不能按路径重新打开。
|
|
3. 安全读取 ZIP 根目录唯一的 `app.json`(最大 1 MiB,严格 JSON、无未知字段/尾随值),校验 v1 的全部字段与共享 Windows 安全相对路径规则。身份字段必须与 Catalog 选择一致:`id`、`version`、`channel`、`min_os`、`architecture`、`entrypoint`、`requires_admin`;其余 v1 常量和值也必须符合 `schemas/app.schema.json`。只有通过比对后,才复用既有两阶段 ZIP 检查把 `payload/` 解压到全新的 `apps/<id>/staging`。
|
|
4. 解压复制时为每个实际 payload 文件计算 size/SHA-256,作为 `ExtractResult` 的已观察文件清单。`InstallService` 将此清单写入 `installed-app.json`,不信任或依赖可选的 `files.json` 作为新的信任根;保留 v1 `files.json` 的协议语义和后续修复功能边界。
|
|
5. 每次安装先对 app root 调用既有 `installer.Recover`。提取成功后以已有 `Switcher` 激活 staging;必需的注入 health check 先通过,随后在同一个 switch health 阶段原子写入新 `installed-app.json`,使 health/记录写失败走既有 rollback,保留旧 `current` 与旧记录。成功才清理 backup/journal。返回的阶段化错误和结果要能让后台调用方区分验证、解压、切换/回滚和记录失败;UI 仍只通过 application 事件/结果更新状态,不在 Gio Layout 做 IO。
|
|
6. 为上列顺序补齐隔离的单元/集成测试:成功安装、Catalog 选择不一致、非普通/替换的完成文件、size/SHA 不符(确认 ZIP/app.json/staging 未触及)、恶意或不匹配 `app.json`、完整安装记录文件清单、已有版本健康或记录写入失败后的回滚、安装前 transaction recovery。测试包只使用运行时生成的虚构 ZIP/哈希。
|
|
|
|
## 验收要点
|
|
|
|
- `InstallService` 的唯一可信输入是已验签/过滤 Catalog 的 entry + architecture;篡改下载 metadata、request/app ID 或 completed 路径不能改变实际验证的 package identity、size 或 SHA-256。
|
|
- 普通完成文件的 Catalog size 和 SHA-256 均在同一打开句柄上通过后,才允许 ZIP 预扫描、`app.json` 读取、staging 创建和 payload 写入;所有失败保留 `errors.Is` 可识别的根因。
|
|
- `app.json` 严格符合 v1,并与 Catalog 的 ID、版本、通道、最低系统、架构、入口和管理员标记一致;安全路径、未知字段、重复/缺失入口或不匹配一律拒绝。
|
|
- 成功链为 `recover → verify → manifest compare → safe staging extract → switch → health → installed-app record → committed cleanup`;记录含每个实际 payload 文件的安全相对路径、字节数和 SHA-256。
|
|
- health 或记录写失败时,已有版本的 `current` 与旧 `installed-app.json` 恢复并保持;首次安装不留下可执行 `current`。已有未完成 transaction 先按恢复状态机收敛。
|
|
- `go -C core vet ./...`、`go -C core test -count=1 ./...`、`./scripts/verify_phase0.ps1`、`python scripts/validate_agent_context.py` 与 `python scripts/validate_harness_governance.py` 全部通过;任务执行记录写明结果。
|
|
|
|
## 边界(不改什么)
|
|
|
|
- 不修改 Catalog 签名协议、Schema 或密钥;不为 nested package `signature` 虚构独立验签算法。外层已验签 Catalog 是本任务唯一的密码学身份来源。
|
|
- 不做磁盘空间预检、程序占用/退出等待、面向 UI 的完整错误码映射或下载重试策略(T-303/T-401);不强杀或自动启动包内程序。
|
|
- 不做 Gio 安装面板、下载完成到安装调用的 UI 编排或物理断电/杀毒软件/文件锁故障注入。T-302 只提供无头 core use case;真实 Windows VM/真机故障注入仍由 T-302/T-601 发布前环境验证完成。
|
|
- 不改变 `files.json` 的 v1/v1.1 协议或实现修复功能,不引入数据库、第三方包、Gio、Windows API 或 Go 1.21+ API。
|
|
|
|
## 协作约束
|
|
|
|
- 当前项目为单 Agent 串行模式;当前 Agent 独占全部 `write_paths`,自行完成设计、安全复核、测试和提交,不启动子 Agent。
|
|
- 先提交本任务规格与关联协议/架构/状态文档;领取后将本文件改为 `DOING`,填写当前 HEAD `context_ref` 与 `work_branch: agent/codex/T-302`,再运行基线和实现。
|
|
- T-303、T-401 及任何后置任务在本任务 `DONE`、验证与实现提交前不得领取或提前修改。
|
|
|
|
## 执行记录
|
|
|
|
- 2026-07-18:正式落成。冻结可信输入、同句柄 size/SHA/ZIP 顺序、严格 app.json 对齐、实际 payload 文件记录、health 内记录写入回滚语义和后续任务边界;待领取后执行基线验证与实现。
|