# 架构设计 > 系统结构、职责边界、数据模型与发布流水线。协议字段以 [api.md](api.md)(权威源 `soft_quay` 仓库)为准;原始设计规格见 [softbox-catalog-design.md](softbox-catalog-design.md)。 ## 一、信任模型(一切设计的出发点) 客户端 `soft_quay` 对远端内容的信任**仅来自 Ed25519 签名**: ```text 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 作为跨实现回归基线,发布端不得自举期望值。 2. **私钥保管是最高安全目标**:私钥泄露 = 可伪造任意清单 / 包记录 / 许可证 = 客户端全线沦陷。 3. **客户端不做在线校验**:下架、撤销、版本兼容都必须能"离线表达"在签名文件里(status 字段、签名撤销名单 + 宽限期)。 ## 二、组件与职责 ```text ┌─────────────────────────────────────────────┐ 子软件 app-* CI │ 构建标准 ZIP 包 + Release 元数据 │ └───────────────┬─────────────────────────────┘ │ 上传候选包 ▼ ┌──────────────────────────────────────────────────────────────┐ │ soft_quay_web │ │ ┌────────────┐ ┌────────────┐ ┌──────────────────────┐ │ │ │ Ingestion │──►│ Registry │──►│ Manifest Generator │ │ │ │ 包接收校验 │ │ 元数据/发布 │ │ 双通道清单组装 │ │ │ └────────────┘ │ 记录 (DB) │ └──────────┬───────────┘ │ │ │ └────────────┘ │ 待签名规范字节 │ │ │ size/SHA-256 ▼ │ │ │ ┌──────────────────────┐ │ │ │ │ Signing Service │ │ │ │ │ (Ed25519 私钥,隔离/ │ │ │ │ │ KMS/HSM,受限接口) │ │ │ │ └──────────┬───────────┘ │ │ ▼ ▼ │ │ ┌────────────┐ ┌────────────┐ ┌──────────────────────┐ │ │ │ License & │ │ Web 管理端 │ │ Publisher (发布器) │ │ │ │ Revocation │ │ (UI) │ │ 上传对象存储/CDN │ │ │ └────────────┘ └────────────┘ └──────────┬───────────┘ │ │ │ 审计日志 (append-only) │ │ └────────┼──────────────────────────────────────┼──────────────┘ ▼ ▼ 审计/合规存档 对象存储 / CDN(静态托管) │ HTTPS ▼ soft_quay 客户端 ``` | 组件 | 职责 | 不含 | | --- | --- | --- | | Ingestion | 接收子软件 CI 的 ZIP 候选包;校验包协议结构(app.json/files.json/payload)、计算 size 与 SHA-256、比对声明版本/ID/架构 | 构建子软件、跑子软件业务 | | Registry | 软件元数据、发布记录、包坐标(url/size/sha256)、status、channel、Catalog 版本 | 子软件源码、客户端状态 | | Manifest Generator | 从 Registry 按 channel 组装双通道清单,产出**待签名规范字节** | 签名(委托签名服务) | | Signing Service | 唯一持有 Ed25519 私钥;只对清单/许可证/撤销名单三类受控结构签名 | 业务逻辑、任意数据签名 | | License & Revocation | 绑定 machine_hash + products 签发许可证;维护签名撤销名单 + 宽限期 | 保存原始硬件序列号/MAC | | Publisher | 签名清单、ZIP 包、图标上传对象存储/CDN;保证原子发布(先包后清单) | 生成未签名/未校验产物 | | Web 管理端 | 发布者操作界面与编排;签名经受控接口调用 | 直接持有私钥 | | Audit | append-only 记录每次发布/下架/撤销/签发 | 可被覆盖的可变日志 | ### 关键边界 - **签名服务是唯一持钥点**:其余组件(含 Web 后台)只能提交"受限结构 + 请求签名",拿回签名串,拿不到私钥。 - **Web 管理端不等于签名端**:私钥不进 Web 进程。 - **协议 Schema / corpus 单一权威源**:引用 `soft_quay/schemas/` 与 `canonical-vectors.json`,CI 校验发布端产物能被同一份 corpus 与 Schema 通过。 ## 三、数据模型(建议,W-201 定稿) > 首期里程碑(协议对齐)不需要数据库;下面是 Registry 落地时的起点草案,定稿后更新本节并删除"建议"标注。 ```text Software 1 ──── * Release 1 ──── * PackageArtifact │ │ │ └──── * AuditEvent(所有实体的操作都产生) └ id 永久稳定 License * ──── RevocationEntry(按 license_id 撤销) ``` | 实体 | 关键字段 | 说明 | | --- | --- | --- | | Software | `id`(永久稳定)、name、description、category、tags、icon(sha256)、homepage、tutorial、entry_exe、requires_admin、status | 客户端列表页唯一来源;一行对应清单里一个 app | | Release | software_id、version(SemVer)、channel(modern/win7)、min_os、architectures、created_at、catalog_version | 一次版本发布;同 software 同 channel 只有一个 active release 进清单 | | PackageArtifact | release_id、arch(386/amd64)、url、size、sha256、signature、ingested_at | 来自 Ingestion 的校验结果;url 为发布后的绝对 HTTPS | | License | license_id、machine_hash、products[]、issued_at、perpetual、update_policy、rebind_policy | 不保存原始硬件标识 | | RevocationEntry | license_id、revoked_at、reason 摘要 | 进入签名撤销名单 | | AuditEvent | actor、action、target、content_digest、signature_fingerprint、at | append-only,不可修改 | ## 四、发布流水线 ```text 子软件 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`);只生成实际支持并测试过的目标。 - **原子性**:包必须先于清单可用,避免客户端拿到指向尚未上传包的清单。 ## 五、签名与密钥管理 - **私钥隔离**:理想部署为 KMS/HSM 或独立最小权限签名服务;Web 后台与业务进程只经受控接口请求签名,不接触私钥材料(保管方案 W-003 裁定)。 - **只签受控结构**:清单 / 许可证 / 撤销名单;不对任意字节签名。 - **公钥分发**:客户端内置公钥;测试用公钥见 corpus。正式公钥的内置与更新方式随密钥轮换设计裁定(Backlog,需客户端协议升级)。 - **签名审计**:每次签名请求记录操作者、目标结构摘要、时间、密钥指纹。 ## 六、版本 / 协议兼容管理 | 版本类型 | 示例 | 用途 | | --- | --- | --- | | 产品版本 | 1.4.2 | 用户看到的软件版本 | | SDK 版本 | sdk/core v1.2.0 | 公共能力兼容性 | | 软件包协议 | schema_version 1 | 盒子与包的结构协议 | | Catalog 版本 | 2026.07.16.1 | 目录发布时间 | 原则:SDK 升级不强迫历史软件立即升级;盒子至少兼容当前与前一个包协议版本;清单顶层 `min_box_version` 声明所需最低盒子版本。 ## 七、开发顺序 见 [任务路线图](06-tasks.md):Phase 0 裁定与骨架 → Phase 1 协议对齐核心(最高风险先行)→ Phase 2 登记与本地模拟发布闭环 → Phase 3 签名隔离与正式发布 → Phase 4 许可证与撤销 → Phase 5 Web 管理端与审计。