Integrate verified installation flow (T-302)
This commit is contained in:
@@ -47,7 +47,7 @@ SoftBox 软件盒子是一个使用 Go + Gio 开发的 Windows 桌面客户端,
|
||||
|
||||
## 当前阶段
|
||||
|
||||
当前项目已完成 Phase 0~2、T-301 与审核整改 `T-604`~`T-614`。Windows 安全路径阻断项、图标缓存资源边界、后台结果回 UI 线程的事件接线、双适配器交互契约、`VisibleItems` 快照生命周期、双端 Gio shell 职责拆分、unsafe cache 安全诊断/runbook、ZIP 中央目录/EOCD(含 ZIP64)预扫描、安装文件/目录/journal 的代码层耐久顺序以及 Catalog canonicalization/签名静态 corpus 均已关闭;下一步正式落成 T-302。物理断电、文件锁与杀毒软件干扰验证仍后置到 T-302/T-601。
|
||||
当前项目已完成 Phase 0~2、T-301、T-302 与审核整改 `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。物理断电、文件锁与杀毒软件干扰验证保留到 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-614:图标缓存资源边界、UI 线程事件接线、双 Gio 适配器交互契约、`VisibleItems` generation 生命周期、双端 `shell.go` 同 package 镜像职责拆分、unsafe cache 诊断/人工恢复指引、ZIP 中央目录/EOCD 预扫描、安装耐久顺序和 Catalog 静态签名向量;下一步正式落成并执行 T-302,再继续 T-303 与 Phase 4-6。T-302/T-601 仍须补真实 Windows 环境的断电/干扰注入。
|
||||
5. 已完成 T-606~T-614:图标缓存资源边界、UI 线程事件接线、双 Gio 适配器交互契约、`VisibleItems` generation 生命周期、双端 `shell.go` 同 package 镜像职责拆分、unsafe cache 诊断/人工恢复指引、ZIP 中央目录/EOCD 预扫描、安装耐久顺序和 Catalog 静态签名向量;已完成 T-302:已验签 Catalog 选择与同句柄 size/SHA、严格 app.json、安全 staging/switch/健康与记录写回滚链路。下一步正式落成并执行 T-303,再继续 Phase 4-6。T-601 仍须补真实 Windows 环境的断电/干扰注入。
|
||||
|
||||
## 领取任务规则
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ T-301 下载队列:
|
||||
- cancel 一旦先于 completion 取得线性化点,即使 body close/sync 报错也记录后继续精确清理;若 completion 先完成,后续 cancel 明确拒绝。known-total 完整 part 在同进程 resume/retry 与启动恢复中都直接 finalize,不发送 offset==total 的 Range。
|
||||
- 写入句柄的文件身份贯穿 sync/close 与 rename 前后核对,防止活跃 `.part` 路径被替换后发布错误文件。崩溃恢复对账 metadata、part、final 三份事实:完整 part 可 finalize,已 rename 的 final 可补 completed metadata;缺 final 的 completed、part+final、超出 expected/unknown 上限均 fail closed。
|
||||
- 事件投递失败通过 `OnObserverError` 显式报告,不改变 durable transfer 结果;application/UI 启动或重连后用 `Queue.Tasks()` 对账终态,避免 DownloadCompleted 等一次性通知丢失后永久停链。
|
||||
- DownloadCompleted 仅证明传输字节完整落盘。下载元数据和 `.download` 可被本地篡改,T-302 的 `application.InstallService` 不得把它们当信任根,而是接收已验签/过滤 Catalog `Entry` + architecture,确认其与 `App.Packages[architecture]` 精确对应。它将该 Catalog size/SHA-256 交给 `Extractor.ExtractVerifiedFile`,后者以同一打开的普通完成文件先 size、再 SHA-256、再 ZIP 预扫描/解析;package `signature` 仅由外层 Catalog 签名覆盖,当前没有独立包级验签域。
|
||||
- DownloadCompleted 仅证明传输字节完整落盘。下载元数据和 `.download` 可被本地篡改,T-302 的 `core/application/install.InstallService` 不得把它们当信任根,而是接收已验签/过滤 Catalog `Entry` + architecture,确认其与 `App.Packages[architecture]` 精确对应。它将该 Catalog size/SHA-256 交给 `Extractor.ExtractVerifiedFile`,后者以同一打开的普通完成文件先 size、再 SHA-256、再 ZIP 预扫描/解析;package `signature` 仅由外层 Catalog 签名覆盖,当前没有独立包级验签域。
|
||||
|
||||
### 4.3 事件模型
|
||||
|
||||
@@ -185,7 +185,7 @@ Phase 1 原子切换原型把 `install-transaction.json` 与目录现实共同
|
||||
|
||||
T-613 已把该状态机的代码层耐久顺序收敛为:payload 的 CRC/长度检查后 `Sync`/`Close` → staging 子目录到根及其父目录同步 → prepared journal 的临时文件 `Sync`/`Close` 与 root 栅栏 → 每次目录 rename 的 root 栅栏与下一 phase journal → committed journal 的 root 栅栏 → backup/journal 清理的 root 栅栏。所有栅栏通过 installer 内部接口复用;非 Windows 使用目录 `File.Sync`,Windows 用 Win7 已有的 `CreateFile(FILE_FLAG_BACKUP_SEMANTICS)` 读写目录句柄和 `FlushFileBuffers`,失败一律 fail closed。测试可注入失败并验证状态机保留可恢复 journal,但这仍不是物理掉电证明。
|
||||
|
||||
真实断电时的硬件/驱动缓存、杀毒软件/文件锁干扰和目标文件系统行为仍需 T-302/T-601 在 Windows VM/真机做故障注入,当前结论不替代硬件级断电验证。
|
||||
真实断电时的硬件/驱动缓存、杀毒软件/文件锁干扰和目标文件系统行为仍需 T-601 在 Windows VM/真机做故障注入;T-302 的代码级链路与单元测试不替代硬件级断电验证。
|
||||
|
||||
盒子自更新由独立 `SoftBoxUpdater.exe` 完成(传入 PID、暂存目录、目标目录;等待退出→备份→切换→启动新版→失败恢复)。
|
||||
|
||||
|
||||
+2
-2
@@ -42,13 +42,13 @@
|
||||
|
||||
#### Phase 1 交叉审核加固
|
||||
|
||||
Phase 1 安全整改按 `docs/review/phase1-security-review.md` 的交叉复核定稿顺序串行落成。T-605、T-612、T-613 与 T-614 已关闭;T-613 建立文件、目录和 journal 的代码层耐久顺序,T-614 冻结 Catalog canonicalization/签名静态 corpus 与客户端拒绝规则。下一步按路线图正式落成并执行 T-302;物理断电验证仍后置到 T-302/T-601。
|
||||
Phase 1 安全整改按 `docs/review/phase1-security-review.md` 的交叉复核定稿顺序串行落成。T-605、T-612、T-613 与 T-614 已关闭;T-613 建立文件、目录和 journal 的代码层耐久顺序,T-614 冻结 Catalog canonicalization/签名静态 corpus 与客户端拒绝规则。T-302 已将这些原型整合到同句柄 Catalog size/SHA、严格 app.json、安全 staging/switch/回滚的安装 use case;物理断电验证保留到 T-601。
|
||||
|
||||
| ID | 任务 | 依赖 | 验收要点 |
|
||||
| --- | --- | --- | --- |
|
||||
| T-605 | 统一 Windows 安全路径校验并封堵 ZIP 逃逸 | T-102, T-201, T-202, T-604 | Catalog/ZIP/installed-app 共用逐段 Windows 安全相对路径策略;拒绝尾随空格/点与 DOS 设备名;输出路径增加 destination 包含性兜底;原生 Windows 用例证明不写出 staging |
|
||||
| T-612 | 在 ZIP 打开前限制包大小与中央目录元数据 | T-605 | 已验签 Catalog size、已完成普通下载文件长度与同句柄 EOCD/ZIP64 预扫描一致;在 `zip.NewReader` 前限制原始包、中央目录与声明条目数 |
|
||||
| T-613 | 建立安装文件与目录事务耐久顺序 | T-612 | payload Sync、staging tree/journal/rename/remove 的目录栅栏;Windows `FlushFileBuffers` fail-closed;物理断电故障注入仍后置到 T-302/T-601 |
|
||||
| T-613 | 建立安装文件与目录事务耐久顺序 | T-612 | payload Sync、staging tree/journal/rename/remove 的目录栅栏;Windows `FlushFileBuffers` fail-closed;物理断电故障注入仍后置到 T-601 |
|
||||
| T-614 | 冻结 Catalog 规范化与签名跨实现测试向量 | T-613 | 静态 canonical bytes/Ed25519 test vectors 覆盖 Unicode、surrogate、`-0`/大整数、嵌套 signature 与 Base64;客户端不自举期望值,外部发布端可消费同一 corpus |
|
||||
|
||||
### Phase 2 · 清单与软件列表
|
||||
|
||||
+2
-2
@@ -153,7 +153,7 @@ T-102 Phase 1 原型进一步固定:
|
||||
- ZIP 名称只接受 UTF-8 `/` 分隔的规范 Windows 安全相对路径;逐段拒绝反斜杠、盘符、冒号/NTFS ADS、NUL/控制字符、Windows 禁止字符、`.`/`..`、首尾 ASCII 空格、尾随句点、DOS 设备名及大小写折叠后的重复输出路径。
|
||||
- 顶层只允许必需的 `app.json`、可选 `files.json` 与 `payload/`;只把 `payload/` 内容写入全新的 staging。
|
||||
- 拒绝符号链接、设备/管道等特殊文件和加密条目。
|
||||
- T-302 的 `application.InstallService` 只接收已验签、严格解析并按目标过滤后的 Catalog `Entry` + architecture 与 `.download` 候选路径。它必须确认 entry/package 与 `App.Packages[architecture]` 精确对应;不得从 T-301 task、`DownloadCompleted` payload 或本地 metadata 取得 app/version/size/hash。外层 Catalog Ed25519 签名覆盖嵌套 package 的 `size`、`sha256` 与 `signature` 文本;当前协议未定义 package `signature` 的独立待签名字节/公钥域,客户端不得臆造第二套包级验签。
|
||||
- T-302 的 `core/application/install.InstallService` 只接收已验签、严格解析并按目标过滤后的 Catalog `Entry` + architecture 与 `.download` 候选路径。它必须确认 entry/package 与 `App.Packages[architecture]` 精确对应;不得从 T-301 task、`DownloadCompleted` payload 或本地 metadata 取得 app/version/size/hash。外层 Catalog Ed25519 签名覆盖嵌套 package 的 `size`、`sha256` 与 `signature` 文本;当前协议未定义 package `signature` 的独立待签名字节/公钥域,客户端不得臆造第二套包级验签。
|
||||
- `Extractor.ExtractVerifiedFile` 必须接收该 Catalog package 的 `size`、`sha256` 与 app identity expectation。它以一次 `Lstat → open → fstat → Lstat` 取得普通 `.download` 文件,并在**同一打开句柄**上先精确核对 `expectedPackageSize`、再计算/常量时间比较 SHA-256;任一失败时不得构造 ZIP reader、读取 app.json 或创建 staging。T-301 的 known-total 完成文件已经以 Catalog size 限长,但 T-302 仍须执行上述重新对账,不能信任可篡改的下载 metadata。
|
||||
- 构造 `zip.Reader` 前只读取文件尾部至多 65,557 字节以定位 EOCD,并按需读取固定的 ZIP64 locator/EOCD 记录;校验单磁盘、中央目录 offset/size/entries 的边界及 entries/中央目录大小硬上限。当前默认上限为:原始包 4 GiB、中央目录 64 MiB、10,000 个条目、总展开 4 GiB、单条及总体压缩比 200:1。大小不一致、原始包超限、中央目录超限、声明条目超限分别保留 `ErrArchiveSizeMismatch`、`ErrArchiveTooLarge`、`ErrCentralDirectoryTooLarge`、`ErrTooManyEntries` 错误链;格式、截断、跨盘或不一致 ZIP64 归入 `ErrInvalidArchive`。
|
||||
- SHA-256 通过后,预扫描继续使用**同一文件句柄**和已核对的长度创建 `zip.NewReader`;完整中央目录/路径/entrypoint/类型/CRC/展开量预检仍是第二道防线。合法 ZIP64 被支持,不因 32 位 EOCD 哨兵值误拒绝。T-302 按真实包体分布复核上述暂定限额后再冻结。
|
||||
@@ -218,7 +218,7 @@ T-613 为该原型建立了 fail-closed 的耐久顺序:每个 payload 先完成
|
||||
|
||||
T-302 在 Switcher 的 health 阶段先运行必需的注入 health check,再原子写入新 `installed-app.json`;health 或记录写失败都必须触发既有 rollback,使旧 current/记录保持可用。只有 health 与记录均成功后才写 committed 并清理 backup/journal。
|
||||
|
||||
这些栅栏与注入失败测试只证明代码层面的调用顺序和 fail-closed 行为,不证明断电后硬件/驱动缓存、网络文件系统、文件锁或杀毒软件的物理表现。T-302/T-601 仍须在目标 Windows VM/真机执行断电与干扰故障注入。
|
||||
这些栅栏与注入失败测试只证明代码层面的调用顺序和 fail-closed 行为,不证明断电后硬件/驱动缓存、网络文件系统、文件锁或杀毒软件的物理表现。T-302 已完成代码整合;T-601 仍须在目标 Windows VM/真机执行断电与干扰故障注入。
|
||||
|
||||
### 2.6 下载任务元数据 download-task.json(本地)
|
||||
|
||||
|
||||
@@ -13,22 +13,22 @@
|
||||
## 当前快照
|
||||
|
||||
- 日期:2026-07-18
|
||||
- 阶段:Phase 2 已完成(T-201~T-204);Phase 3 的 T-301 可恢复下载队列已完成;审核整改 T-604~T-614 已完成;T-302 安装流程整合已正式落成、待领取并执行
|
||||
- 阶段:Phase 2 已完成(T-201~T-204);Phase 3 的 T-301 可恢复下载队列与 T-302 安装流程整合已完成;审核整改 T-604~T-614 已完成;下一步应正式落成并执行 T-303
|
||||
- 技术栈:根 Go 1.25 workspace 只纳入 core/app-modern,`app-win7/go.work` 独立纳入 core/app-win7;版本闸门证明 modern Gio v0.10.1 与 win7 Gio v0.6.0 不交叉解析
|
||||
- 生产代码:core 已有 Catalog/本地状态/存储、共享 Windows 安全相对路径策略与静态跨实现 canonicalization/Ed25519 vector corpus(拒绝非法 surrogate、`-0` 和非唯一 Base64 signature,大整数保持 token)、安全 ZIP 解压/回滚原型(Extractor 在同一普通文件句柄上核对 expected Catalog size 后有界预扫 EOCD/ZIP64、中央目录与条目数,每个 payload Sync/Close 后同步 staging tree 及父目录;transaction/switch/rollback/recovery 的 journal、rename、清理经统一 fail-closed 耐久栅栏,Windows 使用目录句柄 FlushFileBuffers)、发布稳定只读 generation 的无 IO 软件列表模型、按 key in-flight + 流式有界读取 + 32 MiB/256-key LRU 的可信图标缓存、图标 Load/Decode 事件发布用例、有界 application event relay,以及默认并发 2 的持久可恢复下载队列;modern/win7 主循环已接 relay/Invalidate,AppShell 已实现搜索/分类/视图、惰性列表、详情右栏、完整图标失败 identity 生命周期与仅 `unsafe_cache` 可见的安全 locator/人工恢复提示,并按 root/header/catalog/detail/style 同 package 镜像职责拆文件
|
||||
- 测试:core 覆盖 Catalog 静态 canonicalization/Ed25519 vectors、非法 surrogate/`-0`/Base64 fail-closed、列表快照 generation/零复制、SemVer/12 状态、本地安装记录、Windows dot-space/设备名/Unicode 折叠路径攻击、ZIP destination 包含性与 EOCD/ZIP64 原始包/中央目录/条目数预扫描、payload/staging tree/journal/rename/rollback/recovery/cleanup 耐久顺序及错误注入、Windows 原生目录 `FlushFileBuffers`、图标并发/取消/读取边界/LRU、真实目录/symlink fail-closed 与 cache→`unsafe_cache` event、relay 背压与关闭、下载并发/暂停/取消/重试/Range/断连/恢复/事件失败与文件身份替换;两个 app 覆盖 Editor/视图/分类/行/恢复/关闭接线、500 项 viewport、AppID 控件与分类控件生命周期、详情上下文、空状态语义、UI drain 前后、图标失败身份生命周期与 `unsafe_cache` 详情语义;安装恢复矩阵保持通过
|
||||
- 生产代码:core 已有 Catalog/本地状态/存储、共享 Windows 安全相对路径策略与静态跨实现 canonicalization/Ed25519 vector corpus(拒绝非法 surrogate、`-0` 和非唯一 Base64 signature,大整数保持 token)、安全 ZIP 解压/回滚原型及 T-302 安装 use case(`core/application/install.InstallService` 只取已过滤 Catalog entry + architecture,`Extractor.ExtractVerifiedFile` 在同一普通文件句柄按 size→SHA-256→EOCD/ZIP64→严格 app.json→安全 staging 的顺序处理,每个实际 payload 文件 hash 写入 installed-app;health 或记录写失败经 Switcher 回滚),transaction/switch/rollback/recovery 的 journal、rename、清理经统一 fail-closed 耐久栅栏,Windows 使用目录句柄 FlushFileBuffers)、发布稳定只读 generation 的无 IO 软件列表模型、按 key in-flight + 流式有界读取 + 32 MiB/256-key LRU 的可信图标缓存、图标 Load/Decode 事件发布用例、有界 application event relay,以及默认并发 2 的持久可恢复下载队列;modern/win7 主循环已接 relay/Invalidate,AppShell 已实现搜索/分类/视图、惰性列表、详情右栏、完整图标失败 identity 生命周期与仅 `unsafe_cache` 可见的安全 locator/人工恢复提示,并按 root/header/catalog/detail/style 同 package 镜像职责拆文件
|
||||
- 测试:core 覆盖 Catalog 静态 canonicalization/Ed25519 vectors、非法 surrogate/`-0`/Base64 fail-closed、列表快照 generation/零复制、SemVer/12 状态、本地安装记录、Windows dot-space/设备名/Unicode 折叠路径攻击、ZIP destination 包含性与 EOCD/ZIP64 原始包/中央目录/条目数预扫描、T-302 同句柄 package size/SHA、严格/有界 app.json、payload hash 记录、Catalog 选择拒绝、transaction recovery、health/记录写失败回滚、payload/staging tree/journal/rename/rollback/recovery/cleanup 耐久顺序及错误注入、Windows 原生目录 `FlushFileBuffers`、图标并发/取消/读取边界/LRU、真实目录/symlink fail-closed 与 cache→`unsafe_cache` event、relay 背压与关闭、下载并发/暂停/取消/重试/Range/断连/恢复/事件失败与文件身份替换;两个 app 覆盖 Editor/视图/分类/行/恢复/关闭接线、500 项 viewport、AppID 控件与分类控件生命周期、详情上下文、空状态语义、UI drain 前后、图标失败身份生命周期与 `unsafe_cache` 详情语义;安装恢复矩阵保持通过
|
||||
- 数据:`schemas/` 已有 manifest/app.json/installed-app.json/download-task.json v1 Schema并注明 Windows 路径运行时权威规则;`testdata/catalog/` 有公开虚构清单样例和 v1 静态 canonicalization/Ed25519 corpus;`testdata/zip/` 与 `testdata/download/` 记录运行时生成的攻击/传输矩阵
|
||||
- 标准启动路径:`./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-614 已以静态 corpus 冻结客户端 Catalog canonicalization/签名行为,外部 `softbox-catalog` 消费 corpus 的 CI 证据仍需跨仓库协调,但不阻止落成 T-302。物理断电、文件锁/杀毒软件干扰仍需 T-302/T-601 的目标 Windows VM/真机故障注入
|
||||
- 当前 blocker:无;T-614 已以静态 corpus 冻结客户端 Catalog canonicalization/签名行为,外部 `softbox-catalog` 消费 corpus 的 CI 证据仍需跨仓库协调,但不阻止 T-303。物理断电、文件锁/杀毒软件干扰仍需 T-601 的目标 Windows VM/真机故障注入
|
||||
|
||||
## 当前目录要点
|
||||
|
||||
| 路径 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `docs/` | 已有 | harness coding 文档集(本次初始化完成) |
|
||||
| `docs/tasks/` | 已有 | Phase 0~2、T-301 与 T-604~T-614 已完成;T-302 安装流程整合已落成且可领取 |
|
||||
| `docs/tasks/` | 已有 | Phase 0~2、T-301、T-302 与 T-604~T-614 已完成;下一步按路线图落成 T-303 失败处理与磁盘预检查任务 |
|
||||
| `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 职责文件 |
|
||||
@@ -40,9 +40,9 @@
|
||||
|
||||
任务状态以 `docs/tasks/` 各任务文件 frontmatter 的 `status` 为准。本节只写项目级摘要:
|
||||
|
||||
- 已完成: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-604`~`T-614`。
|
||||
- 已完成: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-302`;审核整改 `T-604`~`T-614`。
|
||||
- 正在进行:无。
|
||||
- 下一个可领取任务:T-302(依赖 T-301/T-102/T-103 均已完成)。T-302/T-601 的物理断电与干扰故障注入仍保留为发布前环境验证。
|
||||
- 下一个可领取任务:暂无;应按 Phase 3 路线图先将 T-303 失败处理与磁盘预检查正式落成任务文件,再领取。T-601 的物理断电与干扰故障注入仍保留为发布前环境验证。
|
||||
|
||||
## 当前可运行内容
|
||||
|
||||
|
||||
+12
-6
@@ -3,12 +3,12 @@ id: T-302
|
||||
title: 安装流程整合
|
||||
phase: 3
|
||||
deps: [T-301, T-102, T-103]
|
||||
status: TODO
|
||||
status: DONE
|
||||
created: 2026-07-18
|
||||
issue: null
|
||||
context_ref: null
|
||||
context_ref: 6575c9ad9b997366514277a925196b2e52f16f75
|
||||
claim_branch: null
|
||||
work_branch: null
|
||||
work_branch: agent/codex/T-302
|
||||
write_paths:
|
||||
- docs/tasks/T-302.md
|
||||
- core/application/
|
||||
@@ -16,6 +16,8 @@ write_paths:
|
||||
- core/storage/
|
||||
- docs/api.md
|
||||
- docs/04-architecture.md
|
||||
- docs/00-ai-start-here.md
|
||||
- docs/06-tasks.md
|
||||
- docs/current-state.md
|
||||
---
|
||||
|
||||
@@ -27,7 +29,7 @@ T-301 只能把网络字节可靠地落为隔离的 `.download`;下载任务元
|
||||
|
||||
## 方案
|
||||
|
||||
1. 在 `core/application` 落地 `InstallService`:请求包含已过滤的 `catalog.Entry`、目标 architecture 和 `.download` 路径。服务必须拒绝不可安装 entry、缺失 package、architecture 与 `App.Packages[architecture]` 不一致的选择;不得从 `downloader.Task`、`DownloadCompletedPayload` 或本地 metadata 重新取得 app/version/size/hash。
|
||||
1. 在 `core/application/install` 落地 `InstallService`:请求包含已过滤的 `catalog.Entry`、目标 architecture 和 `.download` 路径。服务必须拒绝不可安装 entry、缺失 package、architecture 与 `App.Packages[architecture]` 不一致的选择;不得从 `downloader.Task`、`DownloadCompletedPayload` 或本地 metadata 重新取得 app/version/size/hash。该 application 子包独立于被 Catalog 图标投递依赖的父包,避免反向 import cycle。
|
||||
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` 的协议语义和后续修复功能边界。
|
||||
@@ -47,7 +49,7 @@ T-301 只能把网络字节可靠地落为隔离的 `.download`;下载任务元
|
||||
|
||||
- 不修改 Catalog 签名协议、Schema 或密钥;不为 nested package `signature` 虚构独立验签算法。外层已验签 Catalog 是本任务唯一的密码学身份来源。
|
||||
- 不做磁盘空间预检、程序占用/退出等待、面向 UI 的完整错误码映射或下载重试策略(T-303/T-401);不强杀或自动启动包内程序。
|
||||
- 不做 Gio 安装面板、下载完成到安装调用的 UI 编排或物理断电/杀毒软件/文件锁故障注入。T-302 只提供无头 core use case;真实 Windows VM/真机故障注入仍由 T-302/T-601 发布前环境验证完成。
|
||||
- 不做 Gio 安装面板、下载完成到安装调用的 UI 编排或物理断电/杀毒软件/文件锁故障注入。T-302 只提供无头 core use case;真实 Windows VM/真机故障注入转入 T-601 发布前环境验证。
|
||||
- 不改变 `files.json` 的 v1/v1.1 协议或实现修复功能,不引入数据库、第三方包、Gio、Windows API 或 Go 1.21+ API。
|
||||
|
||||
## 协作约束
|
||||
@@ -58,4 +60,8 @@ T-301 只能把网络字节可靠地落为隔离的 `.download`;下载任务元
|
||||
|
||||
## 执行记录
|
||||
|
||||
- 2026-07-18:正式落成。冻结可信输入、同句柄 size/SHA/ZIP 顺序、严格 app.json 对齐、实际 payload 文件记录、health 内记录写入回滚语义和后续任务边界;待领取后执行基线验证与实现。
|
||||
- 2026-07-18:正式落成。冻结可信输入、同句柄 size/SHA/ZIP 顺序、严格 app.json 对齐、实际 payload 文件记录、health 内记录写入回滚语义和后续任务边界。
|
||||
- 2026-07-18:领取任务,基线为 `6575c9ad9b997366514277a925196b2e52f16f75`,工作分支 `agent/codex/T-302`;下一步运行统一初始化/完整基线,再开始实现。
|
||||
- 2026-07-18:基线通过:`./init.ps1` 完成治理、core 架构/Go 版本闸门、Go 1.20 core vet/test、modern/Win7 test/build 与 Python harness 校验。
|
||||
- 2026-07-18:实现 `core/application/install.InstallService`、同句柄 `Extractor.ExtractVerifiedFile`、严格且有 1 MiB 上限的 app.json 校验、payload 观测 hash 清单和 `InstalledAppStore.EnsureAppRoot`;Catalog 依赖父 application 包的既有图标投递链会产生 import cycle,因此 use case 放在独立 application 子包,未改变 Gio/UI 边界。
|
||||
- 2026-07-18:复核成功/size+hash+选择失败/严格 manifest/非普通文件/manifest 上限/transaction recovery/health 与记录写失败回滚;`go -C core vet ./...`、`go -C core test -count=1 ./...` 和 `go -C core test -count=10 ./installer ./application/install` 全部通过。真实 Windows 断电、文件锁/杀毒软件故障注入未在当前环境执行,保留为 T-601 发布前验证。
|
||||
|
||||
Reference in New Issue
Block a user