Integrate validated catalog loading (T-201)
This commit is contained in:
@@ -103,8 +103,10 @@ soft_quay/
|
||||
|
||||
- 软件主键是永久稳定的 `id`(小写英文/数字/短横线),不用名称;下架用 `status`,不用名称前缀。
|
||||
- 清单验签失败时**拒绝**,回退到最后一次验证成功的缓存,绝不接受未验证的新内容。
|
||||
- Phase 1 清单签名原型会拒绝重复字段、尾随 JSON 与非整数数字;签名域为移除顶层 `signature` 后的受限规范 JSON,细节见 [api.md](api.md)。
|
||||
- Catalog 正式加载顺序为 HTTPS 获取 → 验签 → 严格字段/Schema/channel 校验 → 缓存替换 → 目标过滤;签名正确但结构或目标通道不匹配的远端内容不能挤掉最后可消费缓存。
|
||||
- 清单解析拒绝未知字段、重复字段/软件 ID、尾随 JSON、非整数数字、非 HTTPS URL 与 architectures/packages 映射不一致;签名域为移除顶层 `signature` 后的受限规范 JSON,细节见 [api.md](api.md)。
|
||||
- channel 分 `modern` / `win7`,更新器必须校验 channel + min_os,禁止交叉升级。
|
||||
- `category` 提供稳定单分类,`tags` 用于搜索和多标签展示;hidden 项从远端目录隐藏,deprecated 与不兼容项保留可见原因但不提供安装包操作。
|
||||
|
||||
### 4.2 本地动态数据(JSON + 原子写入)
|
||||
|
||||
|
||||
+14
-7
@@ -29,8 +29,9 @@
|
||||
"version": "1.2.0",
|
||||
"channel": "stable",
|
||||
"status": "active",
|
||||
"category": "开发工具",
|
||||
"tags": ["工具", "JSON"],
|
||||
"icon": "sha256:...",
|
||||
"icon": "sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"homepage": "https://example.com",
|
||||
"tutorial": "https://example.com/tutorial",
|
||||
"min_os": "windows-7-sp1",
|
||||
@@ -53,21 +54,27 @@
|
||||
|
||||
行为要求:
|
||||
|
||||
- 网络成功:验签通过才替换本地缓存;验签失败**拒绝**,继续用最后一次验证成功的缓存。
|
||||
- 网络成功:按“HTTPS 获取 → 验签 → Schema/字段/目标 channel 校验 → 替换缓存”处理;任一步失败都**拒绝**新内容,继续用最后一次验证且客户端可消费的缓存。
|
||||
- 网络失败:用缓存;清单过期给提示,但保留已安装软件的启动能力。
|
||||
- 下架:显式 `status: deprecated | hidden`,不用名称前缀。
|
||||
- 过滤:按 `min_os` 与 `architectures` 过滤;不兼容软件可见说明但不可下载。
|
||||
- 分类:`category` 是单一稳定分类,`tags` 是搜索/多标签展示数据;两者都不得为空。
|
||||
- 过滤:先校验 manifest `channel`,再按 `min_os`、`architectures` 和 `packages` 过滤;不兼容软件可见说明但不可下载。
|
||||
- 状态:`active` 可安装;`deprecated` 可见但不可新装/更新;`hidden` 不进入目录结果,但本地已安装记录仍由本地状态模块保留。
|
||||
- URL:Catalog、package、homepage、tutorial 只接受无用户信息、无 fragment 的绝对 HTTPS URL。
|
||||
- 架构:MVP Schema 接受 `386` / `amd64`;一个 app 的 `architectures` 必须与 `packages` 键一一对应。当前两个客户端发布目标仍是 amd64。
|
||||
- 系统版本:`min_os` v1 只允许 `windows-7-sp1`、`windows-10`、`windows-11`;更高系统可消费更低最低版本的软件。
|
||||
- Schema:客户端协议文件为 `schemas/manifest.schema.json`;标准包元数据为 `schemas/app.schema.json`。运行时还会执行 JSON Schema 难以表达的重复 ID、架构映射和 channel 目标一致性检查。
|
||||
|
||||
### 1.1 Phase 1 签名域原型
|
||||
### 1.1 Catalog 签名域
|
||||
|
||||
T-101 验证采用以下签名域,供客户端与后续发布器实现对齐:
|
||||
客户端采用以下签名域,供发布器实现对齐:
|
||||
|
||||
1. 输入必须是单个 UTF-8 JSON object;重复字段、尾随 JSON、浮点/指数数字直接拒绝。
|
||||
2. 读取顶层 `signature`(标准 Base64 编码的 64 字节 Ed25519 签名),然后从对象中移除该字段。
|
||||
3. 对剩余值递归规范化:对象键按 Unicode 字符串升序排列;数组保持原顺序;字符串按 JSON 转义;数字仅允许 JSON 整数并保持其合法十进制写法;不保留无意义空白。
|
||||
4. Ed25519 直接签名/验证上述规范 JSON 字节。
|
||||
|
||||
这是 Phase 1 风险原型结论。T-201 正式接入时必须与 `softbox-catalog` 发布端做跨实现向量测试,再冻结 Schema、密钥 ID/轮换字段和版本兼容策略;在此之前不得另造签名域。
|
||||
T-201 已把该签名域接入正式客户端加载链路并用客户端测试向量覆盖。`softbox-catalog` 发布端仍必须补跨实现向量测试;密钥 ID/轮换字段尚未定稿,在单公钥协议升级前不得另造签名域。
|
||||
|
||||
## 2. 标准软件包协议 v1(ZIP)
|
||||
|
||||
@@ -223,7 +230,7 @@ V1.1:命名管道 `\\.\pipe\softbox.<app-id>`,盒子发送 `{"command": "prepare
|
||||
|
||||
## 待实现时确认
|
||||
|
||||
- 清单签名封装格式(签名域、密钥轮换字段)定稿后同步 `schemas/`。
|
||||
- 清单密钥 ID/轮换字段定稿后同步 `schemas/`。
|
||||
- 错误码完整枚举表。
|
||||
- 图标资源的分发方式(内嵌哈希 vs 独立 URL)。
|
||||
- 撤销名单的结构与宽限期时长。
|
||||
|
||||
+10
-10
@@ -13,36 +13,36 @@
|
||||
## 当前快照
|
||||
|
||||
- 日期:2026-07-16
|
||||
- 阶段:M2 已完成(清单验签、ZIP 安全解压、staging/current/backup 切换与崩溃恢复原型全部验证)
|
||||
- 阶段:Phase 2 进行中;T-201 Catalog 正式接入已完成,下一步 T-202 本地安装状态识别
|
||||
- 技术栈:根 Go workspace 纳入 core/app-modern/app-win7 三模块;`app-win7/go.work` 隔离 Go 1.20.14 构建;modern Gio v0.10.1 与 win7 Gio v0.6.0 已实际接入
|
||||
- 生产代码:core 已有状态/事件、Catalog 验签/缓存、ZIP 安全解压和安装事务切换/恢复原型;modern/win7 均可打开最小 AppShell
|
||||
- 测试:core 覆盖 Catalog、ZIP 攻击矩阵及安装成功/回滚/多阶段崩溃恢复;两个 app 覆盖 AppShell 与平台 stub
|
||||
- 数据:`testdata/catalog/` 有公开虚构清单样例;`testdata/zip/` 记录运行时生成的 ZIP 攻击矩阵
|
||||
- 生产代码:core 已有状态/事件、Catalog HTTPS 获取/验签/严格解析/缓存/目标过滤、ZIP 安全解压和安装事务切换/恢复原型;modern/win7 均可打开最小 AppShell
|
||||
- 测试:core 覆盖 Catalog 恶意/结构/通道/HTTPS/过滤、ZIP 攻击矩阵及安装成功/回滚/多阶段崩溃恢复;两个 app 覆盖 AppShell 与平台 stub
|
||||
- 数据:`schemas/` 已有 manifest/app.json v1 Schema;`testdata/catalog/` 有公开虚构清单样例;`testdata/zip/` 记录运行时生成的 ZIP 攻击矩阵
|
||||
- 标准启动路径:`./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-201
|
||||
- 当前 blocker:无;下一步按路线图落成并领取 T-202
|
||||
|
||||
## 当前目录要点
|
||||
|
||||
| 路径 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `docs/` | 已有 | harness coding 文档集(本次初始化完成) |
|
||||
| `docs/tasks/` | 已有 | Phase 0 与 Phase 1 的任务均已完成;T-201 待按路线图落成 |
|
||||
| `docs/tasks/` | 已有 | Phase 0、Phase 1 与 T-201 已完成;T-202 待按路线图落成 |
|
||||
| `scripts/` | 已有 | harness 治理、core 边界、Go 版本检查与 Phase 0 双平台验证入口 |
|
||||
| `core/` | 已建 | Go 1.20 兼容;已有状态/事件与 Phase 1 三项安全原型 |
|
||||
| `core/` | 已建 | Go 1.20 兼容;已有状态/事件、正式 Catalog 客户端与 Phase 1 安装安全原型 |
|
||||
| `app-modern/` | 已建 | Go 1.25.0 + Gio v0.10.1;可打开 Modern AppShell |
|
||||
| `app-win7/` | 已建 | Go 1.20 + Gio v0.6.0;可打开带 Legacy 标识的 AppShell |
|
||||
| `schemas/` | 待建 | 协议 JSON Schema(T-201) |
|
||||
| `schemas/` | 已建 | `manifest.schema.json` 与 `app.schema.json` |
|
||||
| `testdata/` | 已建 | 当前包含 Catalog 假数据与恶意样例;后续任务继续扩展 |
|
||||
|
||||
## 任务状态
|
||||
|
||||
任务状态以 `docs/tasks/` 各任务文件 frontmatter 的 `status` 为准。本节只写项目级摘要:
|
||||
|
||||
- 已完成:Phase 0 的 `T-001`~`T-004`;Phase 1 的 `T-101`、`T-102`、`T-103`。
|
||||
- 已完成:Phase 0 的 `T-001`~`T-004`;Phase 1 的 `T-101`、`T-102`、`T-103`;Phase 2 的 `T-201`。
|
||||
- 正在进行:无。
|
||||
- 下一个可领取任务:按路线图落成并领取 `T-201 catalog 模块正式接入`。
|
||||
- 下一个可领取任务:按路线图落成并领取 `T-202 本地安装状态识别`。
|
||||
|
||||
## 当前可运行内容
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
id: T-201
|
||||
title: Catalog 模块正式接入
|
||||
phase: 2
|
||||
deps: [T-101]
|
||||
status: DONE
|
||||
created: 2026-07-16
|
||||
issue: null
|
||||
context_ref: 9da72ca0d8563fb5dca8a5675461e49dc656b74e
|
||||
claim_branch: null
|
||||
work_branch: agent/codex/T-201
|
||||
write_paths:
|
||||
- docs/tasks/T-201.md
|
||||
- core/catalog/
|
||||
- schemas/
|
||||
- testdata/catalog/
|
||||
- testdata/README.md
|
||||
- docs/api.md
|
||||
- docs/04-architecture.md
|
||||
- docs/current-state.md
|
||||
---
|
||||
|
||||
## 问题 / 背景
|
||||
|
||||
Phase 1 已验证 Catalog 顶层签名与最后有效缓存回退,但仍只有“可信 JSON 字节”,没有正式的 HTTPS 获取、协议字段校验、modern/win7 通道约束、OS/架构过滤和上下架处理。若在结构或通道校验前写缓存,签名正确但客户端无法消费的清单也可能替换最后可用版本。
|
||||
|
||||
## 方案
|
||||
|
||||
1. 在 `core/catalog` 建立 manifest/app/package 强类型模型和严格解析校验,拒绝未知字段、重复软件 ID、非法枚举、非 HTTPS 包 URL及不一致的架构映射。
|
||||
2. Loader 支持在缓存替换前执行文档 validator;正式 Client 固定按“验签 → Schema/通道校验 → 缓存 → 目标过滤”加载。
|
||||
3. 增加有体积上限的 HTTPS Fetcher,并保留 Fetcher/Cache 注入以便无网络测试。
|
||||
4. 目标过滤同时处理 manifest channel、`min_os`、`architectures`、package 架构与 `status`:hidden 不展示,deprecated 与 incompatible 可见但不可安装并给出稳定原因码。
|
||||
5. 在 `schemas/` 落地 manifest 与 app.json 的 JSON Schema;同步协议与架构文档。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- 签名、结构、通道全部通过后才替换缓存;结构非法或通道错误时回退最后验证且可消费的缓存。
|
||||
- HTTP 获取只允许 HTTPS、拒绝非 2xx/超限响应。
|
||||
- modern/win7、最低 OS、386/amd64 与 package 映射过滤正确。
|
||||
- active 可安装;deprecated 可见不可安装;hidden 不进入结果;不兼容项可见并返回稳定原因。
|
||||
- `manifest.schema.json` 与 `app.schema.json` 可由标准 JSON 解析器读取,示例字段与 `docs/api.md` 一致。
|
||||
- Go 1.20 core vet/test、完整双目标闸门和治理校验通过。
|
||||
|
||||
## 边界(不改什么)
|
||||
|
||||
- 不实现 installed-app.json、SemVer 比较和本地 12 状态识别(T-202)。
|
||||
- 不实现 Gio 列表、详情或图标资源下载(T-203/T-204)。
|
||||
- 不冻结密钥轮换字段或图标 URL;发布端跨实现签名向量仍需在独立仓库对齐。
|
||||
- 不引入第三方 Schema、HTTP 或 SemVer 依赖。
|
||||
|
||||
## 协作约束
|
||||
|
||||
未启用 Gitea;本任务在 `agent/codex/T-201` 分支串行执行。正式 Client 必须保护“最后可消费缓存”,不能把 validator 放到缓存写入之后。
|
||||
|
||||
## 执行记录
|
||||
|
||||
- 2026-07-16:建立 manifest/app/package 强类型模型、严格 Parser 与正式 Client;加载顺序固定为“HTTPS 获取 → Ed25519 验签 → 字段/Schema/channel 校验 → 缓存替换 → 目标过滤”。
|
||||
- 2026-07-16:Loader 增加缓存写入前 DocumentValidator;测试证明签名正确但 channel/结构不匹配的远端清单不会覆盖最后可消费缓存。
|
||||
- 2026-07-16:增加有响应体上限和 HTTPS 重定向约束的 HTTPFetcher;错误状态、非 HTTPS 与超限响应均返回稳定错误。
|
||||
- 2026-07-16:实现 modern/win7、Windows 7 SP1/10/11、386/amd64 过滤;active 可安装,deprecated 与 incompatible 可见不可安装并带稳定原因,hidden 不进入目录结果。
|
||||
- 2026-07-16:正式协议补充必填 `category`,与 `tags` 分别承担单分类与搜索标签;图标仍仅定义 `sha256:` 内容引用,未越权确定分发 URL。
|
||||
- 2026-07-16:新增 `schemas/manifest.schema.json`、`schemas/app.schema.json`,并同步 `docs/api.md`、`docs/04-architecture.md`、`docs/current-state.md` 与公开虚构 testdata。
|
||||
- 定向验证通过:`go -C core test -count=1 ./catalog`。
|
||||
- Schema 语法验证通过:`python -m json.tool schemas/manifest.schema.json`、`python -m json.tool schemas/app.schema.json`。
|
||||
- 完整验证通过:`./scripts/verify_phase0.ps1`,包含 Go 1.20.14 core vet/test、治理/边界/版本检查及 modern/win7 双目标测试与构建。
|
||||
- 提交前检查通过:`git diff --check`。
|
||||
Reference in New Issue
Block a user