Files
soft_quay_web/docs/softbox-catalog-design.md
T
ilaandClaude Fable 5 a89821a571 Initialize harness coding docs from design spec
Split docs/softbox-catalog-design.md into the numbered harness doc set
(00-06, api.md, current-state, agent-context, tasks) following the
harness_coding_docs template and soft_quay conventions. Register the
nine open decision items from the design spec into the 06-tasks
roadmap as W- tasks and backlog entries. Keep the original design
spec as an archived design input with a header note.

Recreated after the repository's previous git history was lost to an
external reset; content matches the original initial commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 00:43:58 +08:00

21 KiB

soft_quay_web 设计说明(愿景 · 架构 · 协议契约)

定位说明(2026-07-20):本文是立项前的原始设计规格,内容已拆分进本仓库 harness coding 编号文档 (01-vision.md / 02-requirements.md / 03-tech-stack.md / 04-architecture.md / api.md / 06-tasks.md 的裁定清单)。 日常开发以编号文档为准,与本文冲突时以编号文档为准;本文保留作设计输入存档,不再逐项维护。

本文是 soft_quay_web(SoftBox 软件盒子的中央发布 / 登记系统;其 Web 管理端即本仓库 soft_quay_web)的设计规格。 权威协议以客户端仓库 soft_quay/docs/api.md、soft_quay/schemas/*.json 和 soft_quay/testdata/catalog/canonical-vectors.json 为准;本文引用而非另建一份,两者变化时同步。 状态:尚未落地,属客户端 02-requirements.md 第七节待确认风险。本文供另起本仓库时作为规格起点。 更新日期:2026-07-19


一、愿景

让 SoftBox 的软件发布者(自己)能够集中、安全、可审计地把自家系列软件发布给所有盒子用户:一处登记元数据、一处签名、一处托管,客户端离线即可验真。

发布者在一个后台里完成"登记软件 → 接收构建包 → 校验 → 签名 → 生成双通道清单 → 上传 → 发现新版本",而签名私钥永不离开发布系统,客户端只内置公钥。

它把整个 SoftBox 产品家族的"信任根"收敛到一处:客户端拿到的每一份清单、每一个安装包、每一张许可证,都能用内置 Ed25519 公钥离线验签,不依赖任何在线接口的可用性。

设计原则

  • 静态分发优先:最终产物是放在对象存储 / CDN 上的静态签名文件,不是运行时动态 API;客户端离线验签。
  • 私钥隔离至上:Ed25519 私钥是整个体系的信任根,只存在于受控签名服务,绝不进客户端、代码仓库或普通后台进程。
  • 协议以客户端为权威源:清单 / 包协议 Schema 和签名向量 corpus 以 soft_quay 为准,发布端字节级对齐,不另造 canonicalizer 或第二套验签域。
  • 通道隔离:modern / win7 双通道全程不交叉,Win7 用户永不拿到无法启动的现代版包。
  • 可审计:每次发布、下架、撤销、许可证签发都有不可否认的记录。

二、定位与范围

2.1 一句话定位

soft_quay_web = 软件登记 + 构建包接收校验 + Ed25519 签名服务 + 双通道清单生成 + 对象存储发布 + 许可证/撤销签发 + Web 管理后台;产物是静态签名文件,信任根是私钥。

2.2 做什么

见第五节功能清单。

2.3 明确不做

  • 不含子软件业务源码——那些在各自 app-* 仓库。
  • 不含盒子的下载 / 更新 / 安装 / 授权实现——那些在 soft_quay 客户端。
  • 不是动态在线 API / 应用商店服务——无面向客户端的运行时接口、无账号会话;客户端只拉静态签名文件。
  • 不生成未测试目标的占位包。
  • 不定义第二套包级验签域——外层清单 Ed25519 签名已覆盖 package 的 url/size/sha256/signature 文本(见 §6.4)。

三、与客户端的信任模型(核心)

这是本系统一切设计的出发点。客户端 soft_quay 对远端内容的信任仅来自 Ed25519 签名:

soft_quay_web(持私钥)          soft_quay 客户端(内置公钥)
─────────────────────────         ─────────────────────────
用受限规范 JSON + 私钥签名   ──►   拉取 → 去掉顶层 signature → 同规则规范化
生成 manifest-modern/win7.json     → Ed25519 验签 → Schema/channel/架构过滤
上传对象存储 / CDN(HTTPS)          → 缓存;验签失败则拒绝、退回上次可信缓存
包 url/size/sha256 写入清单         → 下载 → 同句柄 size→SHA-256→安全解压

由此推出对本系统的硬性要求:

  1. 规范化必须字节级一致:发布端与客户端对同一 JSON 输入必须产出逐字节相同的规范字节与签名。二者共用 canonical-vectors.json corpus 作为跨实现回归基线,发布端不得用自身 canonicalizer 重新生成期望值。
  2. 私钥保管是最高安全目标:私钥泄露 = 可伪造任意清单/包记录/许可证 = 客户端全线沦陷。
  3. 客户端不做在线校验:因此下架、撤销、版本兼容都必须能"离线表达"在签名文件里(status 字段、签名撤销名单 + 宽限期)。

四、系统架构

4.1 组件

             ┌─────────────────────────────────────────────┐
子软件 app-* CI │ 构建标准 ZIP 包 + Release 元数据             │
             └───────────────┬─────────────────────────────┘
                             │ 上传候选包
                             ▼
┌──────────────────────────────────────────────────────────────┐
│ soft_quay_web                                                │
│                                                                │
│  ┌────────────┐   ┌────────────┐   ┌──────────────────────┐   │
│  │ Ingestion  │──►│ Registry   │──►│ Manifest Generator   │   │
│  │ 包接收校验  │   │ 元数据/发布 │   │ 双通道清单组装        │   │
│  └────────────┘   │ 记录 (DB)  │   └──────────┬───────────┘   │
│        │          └────────────┘              │ 待签名规范字节  │
│        │ size/SHA-256                          ▼               │
│        │                          ┌──────────────────────┐    │
│        │                          │ Signing Service      │    │
│        │                          │ (Ed25519 私钥,隔离/  │    │
│        │                          │  KMS/HSM,受限接口)  │    │
│        │                          └──────────┬───────────┘    │
│        │                                     │ 签名             │
│        ▼                                     ▼                 │
│  ┌────────────┐   ┌────────────┐   ┌──────────────────────┐   │
│  │ License &  │   │ Web 管理端  │   │ Publisher (发布器)    │   │
│  │ Revocation │   │ soft_quay_ │   │ 上传对象存储/CDN      │   │
│  │ 签发       │   │ web(UI)   │   │                       │   │
│  └────────────┘   └────────────┘   └──────────┬───────────┘   │
│        │ 审计日志 (append-only)                 │              │
└────────┼──────────────────────────────────────┼──────────────┘
         ▼                                        ▼
   审计/合规存档                       对象存储 / CDN(静态托管)
                                       manifest-*.json / *.zip / icons
                                                  │ HTTPS
                                                  ▼
                                          soft_quay 客户端

4.2 组件职责

组件 职责 不含
Ingestion(接收校验) 接收子软件 CI 的 ZIP 候选包;校验包协议结构(app.json/files.json/payload)、计算 size 与 SHA-256、比对声明版本/ID/架构 构建子软件、跑子软件业务
Registry(登记库) 软件元数据、发布记录、包坐标(url/size/sha256)、status、channel、Catalog 版本 子软件源码、客户端状态
Manifest Generator 从 Registry 按 channel 组装 manifest-modern.json / manifest-win7.json,产出待签名规范字节 签名(委托签名服务)
Signing Service 唯一持有 Ed25519 私钥;对规范字节签名(清单/许可证/撤销名单);理想部署为 KMS/HSM 或独立最小权限服务 业务逻辑、任意数据签名(只签受控结构)
License & Revocation 绑定 machine_hash + products 签发许可证;维护签名撤销名单 + 宽限期 保存原始硬件序列号/MAC
Publisher(发布器) 把签名清单、ZIP 包、图标上传对象存储 / CDN;保证原子发布(先传包再切清单) 生成未签名/未校验产物
Web 管理端(soft_quay_web) 发布者操作界面:登记/发布/下架/撤销、发布记录浏览、许可证签发、审计查看 直接持有私钥(经受控签名服务接口)
Audit append-only 记录每次发布/下架/撤销/签发 可被覆盖的可变日志

4.3 关键边界

  • 签名服务是唯一持钥点:其余组件(含 Web 后台)只能提交"受限结构 + 请求签名",拿回签名串,拿不到私钥。
  • Web 管理端不等于签名端:soft_quay_web 负责人机交互与编排,签名经受控接口调用签名服务;私钥不进 Web 进程。
  • 协议 Schema / corpus 单一权威源:引用 soft_quay/schemas/ 与 canonical-vectors.json,CI 校验发布端产物能被同一份 corpus 与 Schema 通过。

五、功能清单

5.1 软件登记与元数据

维护每款软件的元数据(客户端列表页唯一来源),字段与约束见 §6.1:稳定 id、name、description、version、channel、status、category、tags、icon、homepage、tutorial、min_os、architectures、entry_exe、requires_admin、packages。

5.2 构建包接收与校验(Ingestion)

接收子软件 CI 产出的标准 ZIP 包并校验:

  • 包结构:根 app.json + 可选 files.json + payload/;
  • app.json 与登记的 id/version/channel/min_os/architecture 一致;
  • 计算 size 与 SHA-256,写入发布记录;
  • 只接受实际支持并测试过的目标,不生成未测试平台占位包。

5.3 发布记录(Release)

每次发布登记包的下载坐标与校验信息:url(绝对 HTTPS)、size、sha256、signature(见 §6.4)。

5.4 Schema 校验(协议权威)

发布前用 soft_quay/schemas/manifest.schema.json、app.schema.json 校验:Schema 合规、无未知/重复/缺失字段、id 唯一、SemVer 合法、architectures 与 packages 键一一对应、channel 目标一致、URL 为绝对 HTTPS。

5.5 Ed25519 签名(核心)

  • 签名域 = 移除顶层 signature 后的受限规范 JSON(§6.3);
  • signature 为唯一标准 padded Base64;
  • 与客户端共用 canonical-vectors.json 做跨实现回归。

5.6 双通道清单生成

产出 manifest-modern.json 与 manifest-win7.json,channel 字段隔离,互不交叉。

5.7 发布流水线

见 §七。

5.8 下架与撤销

  • 软件下架用 status(active / deprecated / hidden),不改名;
  • 维护签名的许可证撤销名单,客户端缓存 + 网络失败宽限期。

5.9 许可证签发

绑定 machine_hash + products 签发 Ed25519 许可证(§6.5);不保存原始硬件标识。

5.10 版本 / 协议兼容管理

版本类型 示例 用途
产品版本 1.4.2 用户看到的软件版本
SDK 版本 sdk/core v1.2.0 公共能力兼容性
软件包协议 schema_version 1 盒子与包的结构协议
Catalog 版本 2026.07.16.1 目录发布时间

原则:SDK 升级不强迫历史软件立即升级;盒子至少兼容当前与前一个包协议版本;清单顶层 min_box_version 声明所需最低盒子版本。

5.11 审计

append-only 记录发布/下架/撤销/许可证签发,含操作者、时间、内容摘要、签名指纹。


六、数据与协议契约

以下字段与约束必须与 soft_quay/schemas/*.json 和 api.md 一致;此处为发布端视角的摘要,冲突时以客户端仓库为准。

6.1 Catalog 清单 v1(manifest-{modern,win7}.json)

顶层(additionalProperties: false,全部必填):

字段 约束
schema_version 常量 1
channel modern 或 win7
generated_at RFC3339 date-time
min_box_version SemVer
apps app 数组
signature Ed25519,^[A-Za-z0-9+/]{86}==$

每个 app(additionalProperties: false):

字段 约束
id ^[a-z0-9-]+$,永久稳定不可变
name / description 非空字符串
version SemVer 2.0.0
channel 常量 stable
status active / deprecated / hidden
category 非空(单一分类)
tags 非空字符串数组(≥1)
icon ^sha256:[0-9A-Fa-f]{64}$(内容引用,非 URL;可选)
homepage / tutorial 绝对 HTTPS(可选)
min_os windows-7-sp1 / windows-10 / windows-11
architectures `["386"
entry_exe 安全相对路径(拒绝首尾空格/尾随点/DOS 设备名/反斜杠/`:<>"
requires_admin 布尔
packages {386?, amd64?},≥1;每个含 url/size/sha256/signature

package 对象:url(绝对 HTTPS)、size(整数 ≥1)、sha256(64 hex)、signature(Ed25519)。

6.2 通用约定

  • 传输 HTTPS,JSON UTF-8;时间 RFC3339(UTC)。
  • URL 只接受无用户信息、无 fragment 的绝对 HTTPS。
  • 数字仅整数 token(签名域拒绝浮点/指数/-0,大整数保持 token 不失精度)。

6.3 签名域(必须与客户端字节对齐)

  1. 输入为单个 UTF-8 JSON object;拒绝重复键、尾随数据、浮点/指数数字、非法 Unicode surrogate。
  2. 读取顶层 signature(标准 padded Base64,严格解码为 64 字节;拒绝 CR/LF、其他空白、缺失/额外 padding),从对象移除该字段。
  3. 对剩余值递归规范化:对象键按 Unicode 码点升序、数组保序、字符串按 JSON 转义、数字仅整数 token、无多余空白。
  4. Ed25519 对上述规范字节签名。

跨实现回归:soft_quay/testdata/catalog/canonical-vectors.json 含测试公钥(public_key_base64)与向量(document / signed_payload_base64 / signature / want_error),覆盖 Unicode 键序、转义、<>&/U+2028/U+2029、合法/非法 surrogate、-0/大整数、嵌套 signature、Base64 变体。发布端 CI 必读该 corpus 断言,不得自举期望值。

6.4 package.signature 的语义(待定,见未定项)

当前客户端不独立验证 package 的 signature——其文本已被外层清单 Ed25519 签名覆盖,客户端不臆造第二套包级验签域。但 Schema 要求该字段存在且形状合法。发布端 v1 须产出形状合法的 Ed25519 串;其独立签名域(待签名字节 + 公钥)尚未定义,是未定项。

6.5 许可证(server 签发 → 客户端离线验证)

{
  "schema_version": 1,
  "license_id": "lic-...",
  "machine_hash": "...",
  "products": ["product-json-parser"],
  "issued_at": "2026-07-16T00:00:00Z",
  "perpetual": true,
  "update_policy": "updates-until-2027-12-31",
  "rebind_policy": "self-service-1-per-90d",
  "signature": "..."
}
  • machine_hash 由客户端平台层多硬件标识清洗生成;许可证不保存原始序列号/MAC。
  • Ed25519 签名;客户端内置公钥离线验签,保存于 licenses/,更新不覆盖。
  • 撤销名单同样签名 + 客户端缓存 + 网络失败宽限期。
  • 子软件用 SDK licensing 逻辑独立再验证(签名 + machine_hash + product_id)。

6.6 标准软件包协议 v1(ZIP,发布端负责接收校验)

<id>_<version>_windows_<arch>.zip
├─ app.json      # schema_version/id/name/vendor/version/channel/min_os/
│                #  architecture/entrypoint/working_directory/product_id/
│                #  supports_trial/requires_admin/data_policy/update_policy
├─ files.json    # 解压后文件清单(v1.1 强制,v1 推荐)
└─ payload/      # 实际安装文件

发布端校验 app.json 与登记一致、payload 结构合法,并计算整包 SHA-256 写入清单;data_policy 固定 local-app-data、update_policy 固定 managed-by-softbox。


七、发布流水线

子软件 CI 产出标准 ZIP 包 + Release 元数据
  → Ingestion 校验包结构 / app.json 一致性 / 计算 size + SHA-256
  → Registry 登记发布记录(url 坐标、status、channel、Catalog 版本)
  → Schema 校验(manifest/app schema)
  → Manifest Generator 组装 modern/win7 待签名规范字节
  → Signing Service 用 Ed25519 私钥签名
  → CI 用 canonical-vectors corpus + Schema 回归验证产物
  → Publisher 原子上传:先传 ZIP 包/图标到对象存储,再切换签名清单
  → soft_quay 客户端发现新版本

一个产品可产出多目标(如 json-parser_1.4.2_windows_amd64.zip、..._win7_amd64.zip、..._win7_386.zip);只生成实际支持并测试过的目标。原子性要求:包必须先于清单可用,避免客户端拿到指向尚未上传包的清单。


八、签名与密钥管理

  • 私钥隔离:理想部署为 KMS/HSM 或独立最小权限签名服务;Web 后台与业务进程只经受控接口请求签名,不接触私钥材料。
  • 只签受控结构:签名服务只对"清单 / 许可证 / 撤销名单"这几类已知结构签名,不对任意字节签名(防被当通用签名 oracle)。
  • 公钥分发:客户端内置公钥;测试用公钥见 corpus。正式公钥的内置与更新方式随密钥轮换设计裁定。
  • 审计:每次签名请求记录操作者、目标结构摘要、时间、密钥指纹。

九、技术选型建议(soft_quay_web)

待定,以下为建议,立项时在本仓库 tech-stack 文档固定。

  • 形态:Web 管理后台 + 后端 API + 独立签名服务 + 对象存储集成。
  • 后端语言:建议 Go(与客户端同栈,可直接复用同一套 canonical/verify 实现与 Schema,天然字节对齐;这是选 Go 的最强理由)。若选其他语言,必须用 corpus 做严格字节回归。
  • 存储:发布记录用关系型库;产物用对象存储 / CDN。
  • 签名:私钥入 KMS/HSM 或隔离服务;绝不入库、不进 Web 进程环境变量明文。
  • 协议 Schema / corpus:以 soft_quay 为权威源引用(git submodule 或版本化拷贝 + CI 校验一致),不另建。

十、未定项 / 待确认(立项前必须裁定)

项 说明
签名私钥管理 谁持有、如何保管与轮换、签发流程;私钥绝不进客户端/仓库/Web 进程
密钥 ID / 轮换字段 清单/许可证尚无 key ID / rotation 字段;api.md 注明"单公钥协议升级前不得另造签名域",多公钥/轮换需先做协议升级
package.signature 独立语义 v1 客户端不独立验;若要独立包级验签,需定义待签名字节 + 公钥域(见 §6.4)
正式域名与对象存储 清单/包的正式 HTTPS 域名、对象存储/CDN 选型、带宽成本与防盗链策略
图标分发字段 图标从内容哈希(sha256:)到实际下载位置/分辨率变体的发布端映射格式(api.md 待实现项)
撤销名单结构 revocation list 字段结构与宽限期时长
跨仓库 CI 对齐 发布端消费同一 corpus / Schema 的 CI 证据需与 soft_quay(T-614)跨仓库协调
授权产品映射 product_id 与许可证 products 的登记与映射管理
发布端形态与权限模型 Web 后台的操作者权限、审批流(谁能发布/下架/撤销/签发)

十一、首期落地建议

  • 首期用本地 / 静态文件模拟:本地生成签名清单 + 本地 HTTP 静态服务,即可让客户端跑通"清单→下载→安装"闭环,不必先建正式对象存储。
  • 私钥先用离线生成的测试密钥对(与客户端内置测试公钥、corpus public_key_base64 配对);正式私钥管理另裁。
  • 先落协议对齐再落 UI:第一里程碑做到"能产出被 soft_quay 客户端验签通过、被 corpus + Schema 回归通过的 manifest",再迭代 Web 管理界面。
  • 协议 Schema 与 corpus 以 soft_quay 为权威源引用,避免漂移。

本文为设计规格;字段与协议细节以 soft_quay/docs/api.md 与 soft_quay/schemas/ 为准,两者变化时同步本文。