Files

98 lines
5.0 KiB
Markdown
Raw Permalink Normal View History

# 协议合约(发布端视角摘要)
> **权威源在客户端仓库**:`soft_quay/docs/api.md`、`soft_quay/schemas/*.json`、`soft_quay/testdata/catalog/canonical-vectors.json`。
> 本文是发布端视角的摘要与本仓库特有接口的合约位;字段冲突时以客户端仓库为准,协议变更必须先在客户端仓库定稿。
## 一、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"|"amd64"]`,唯一,≥1 |
| `entry_exe` | 安全相对路径(拒绝首尾空格/尾随点/DOS 设备名/反斜杠/`:<>"|?*`/`..`) |
| `requires_admin` | 布尔 |
| `packages` | `{386?, amd64?}`,≥1;键与 `architectures` 一一对应 |
package 对象:`url`(绝对 HTTPS)、`size`(整数 ≥1)、`sha256`(64 hex)、`signature`(Ed25519 形状)。
通用约定:传输 HTTPS,JSON UTF-8;时间 RFC3339(UTC);URL 无用户信息、无 fragment;数字仅整数 token(签名域拒绝浮点/指数/`-0`,大整数保持 token 不失精度)。
## 二、签名域(必须与客户端字节对齐)
1. 输入为单个 UTF-8 JSON object;拒绝重复键、尾随数据、浮点/指数数字、非法 Unicode surrogate。
2. 读取顶层 `signature`(标准 padded Base64,严格解码为 64 字节;拒绝 CR/LF、其他空白、缺失/额外 padding),从对象移除该字段。
3. 对剩余值递归规范化:对象键按 Unicode 码点升序、数组保序、字符串按 JSON 转义、数字仅整数 token、无多余空白。
4. Ed25519 对上述规范字节签名。
**跨实现回归**:corpus 含测试公钥(`public_key_base64`)与向量(`document` / `signed_payload_base64` / `signature` / `want_error`),覆盖 Unicode 键序、转义、`<>&`/U+2028/U+2029、合法/非法 surrogate、`-0`/大整数、嵌套 signature、Base64 变体。发布端 CI **必读该 corpus 断言,不得自举期望值**。
## 三、package.signature 的语义(未定项)
当前客户端**不独立验证** package 的 `signature`——其文本已被外层清单 Ed25519 签名覆盖。但 Schema 要求该字段存在且形状合法。发布端 v1 须产出形状合法的 Ed25519 串;其独立签名域(待签名字节 + 公钥)尚未定义,在客户端协议升级前**不得**自行定义(见 06-tasks Backlog)。
## 四、许可证 v1(签发 → 客户端离线验证)
```json
{
"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 签名;客户端内置公钥离线验签。
- 撤销名单同样签名 + 客户端缓存 + 网络失败宽限期;名单具体结构与宽限期时长是未定项(W-402)。
## 五、标准软件包协议 v1(ZIP,发布端负责接收校验)
```text
<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 的合约;各自任务落地时在本节定稿。
| 接口 | 说明 | 状态 |
| --- | --- | --- |
| Ingestion 提交接口 | 子软件 CI 提交候选 ZIP + Release 元数据的方式(HTTP 端点 / 对象存储投递)与认证 | 待定(W-202) |
| 签名服务接口 | 受控结构 + 请求签名 → 签名串;调用方拿不到私钥;每次请求审计 | 待定(W-301) |
| Web 管理端 API | 操作者认证与登记/发布/下架/撤销/签发操作 | 待定(W-501) |
| 静态产物布局 | 对象存储上 manifest-*.json / ZIP / 图标的路径布局与图标 `sha256:` → 实际位置映射 | 待定(W-204 首版本地布局;图标映射见 Backlog) |