开放注册表协议(Open Registry Protocol)
版本:1.0 Qomicex 插件商店的 API 协议已抽象为开放标准,允许第三方实现兼容的注册表(镜像/私有仓库/内网定制源),启动器通过多源发现机制对接任意兼容实现。1. 核心概念
一个**注册表(Registry)**是一个 HTTP API 端点,提供插件元数据查询与分发。注册表有两种身份:
启动器在
settings.registryUrl 中配置源列表,按优先级依次尝试。
2. 端点子集
2.1 核心端点(镜像必须实现)
Plugin 对象(核心字段):
{id, slug, name, description, category?, tags[], iconUrl?, latestVersion?, downloadsCount, ratingAverage?, ratingCount, createdAt}。
2.2 可选端点(镜像可不实现)
启动器对可选端点采用优雅降级:不可用时对应 UI 功能隐藏或禁用。
2.3 公共约定
- Base URL:注册表 API 根路径,如
https://plugins.qomicex.top/api/v1 - 请求/响应:JSON,字段命名 camelCase;时间为 ISO 8601
- 错误格式:统一
{ "error": { "code": "...", "message": "..." } },HTTP 状态码语义化 - 分页:
page(从 1 起)、pageSize(默认 20,上限 50) - 缓存:插件列表建议 15s、详情建议 300s、注册表元数据建议 60s
3. 注册表元数据 GET /registry
注册表的身份牌。启动器发现 registryUrl 后发出的第一个请求即为此端点,用于确认兼容性:
mirrors字段的镜像域用于竞速下载而非 API 回退。API 回退由启动器registryUrl多源列表控制。
4. 客户端发现机制
4.1 配置方式
启动器设置支持插件式多源发现:- 主源(
primary: true):启动器默认查询的注册表 - 备源(
primary: false):主源不可达或超时时自动回退(备源为只读,写操作仅在主源尝试) - 优先级(
priority):数字越小越优先
4.2 启动流程
- 启动器对所有
enabled: true的源并行发出GET /registry - 检测
apiVersion >= 1且capabilities包含至少list、detail、download→ 标记为可用 - 按
priority排序,选择第一个可用的为主源 - 缓存所有源的
pluginCount,界面中注明插件来源 - 主源连续失败 N 次后自动切换至存量可用源(如无可用则暂停轮询)
4.3 回退策略
5. 下载双通道与 SHA-256 校验
5.1 双通道语义
GET /plugins/:slug/versions/:version/download 返回:
sha256 校验完整性。
5.2 校验强制规则
- 下载完成后必须计算 SHA-256,与响应中的
sha256比对(全小写 hex) - 不匹配 → 拒绝安装,且不留存篡改包
- 镜像返回的
sha256必须与主源完全一致——镜像不可修改包内容
5.3 镜像包体要求
镜像重传包体时必须:- 保持包内文件结构完全不变(不可重打包、修改 manifest、增减文件)
signature.json、signature.cert.json原样保留(签名链必须完整传递,接收方验签依赖包内证书)- 以 200 状态码返回,
Content-Type: application/octet-stream或application/zip
6. 签名链要求(ADR-050)
开放注册表协议对签名的要求只针对包体完整性,不要求镜像自身提供签名验证服务:6.1 包内签名链结构
- 镜像不得重新打包,不得修改
signature.json/signature.cert.json或包内任何文件 - 镜像可在响应头附加额外校验摘要(如
X-Checksum-SHA256),但不可替代包内签名 - 启动器收到包后先校验 Ed25519 签名再安装,镜像服务无需关心验签细节
7. 自建镜像指南
7.1 方案 A:Cloudflare Worker 复制(共享负载)
最适合分担官方商店下载流量的场景:- Fork / 部署
qomicex-plugin-store仓库的 Worker 代码到自己的 Cloudflare 账号 - 配置专属
CDN_BASE_URL(R2 或外部存储)与MIRROR_BASE_URL - 周期性把主商店的插件数据同步到自己的 D1(
wrangler d1 execute --file=sync.sql) - 在启动器设置中添加
registryUrl: "https://你的域名/api/v1"作为备源 - 下载流量指向你自己的 R2 / CDN
7.2 方案 B:纯静态托管(只读镜像)
如果只做只读缓存,无需 Worker 计算能力:- 周期性抓取主商店的
GET /plugins列表 + 各详情页,生成registry.json静态文件 - 把下载的
.qplugin包上传到自己的 CDN / 对象存储 - 托管
registry.json与下载文件在同一域下 - 提供静态
GET /registry元数据端点(返回registry.json内容) - 静态镜像只能提供核心读端点,不支持
check-updates(需要计算能力,capabilities 中如实声明)
7.3 方案 C:自建完整注册表(独立源)
运行自己的审核/组织/认证流程:- 完整实现核心端点 +
GET /registry - 可选实现
auth、reviews等端点(capabilities 中如实声明) - 配置自己的签名根公钥(
PLUGIN_ROOT_PUBLIC_KEY),开发者上传公钥获证书后签名上传 - 客户端配置
registryUrl后即可作为完整独立源使用
7.4 验证镜像兼容性
8. 启动器集成方案(TODO)
当前启动器后端services/plugin_store.rs 使用固定的 QOMICEX_STORE_API_BASE 环境变量作为单源代理。多源集成的改动点:
建议分步计划:
- 后端加
GET /store/registry透传(独立小端点,不破坏现有语义) - 后端
store_api_base()参数化,按来源选择 base URL - 前端设置页加
registryUrl输入(可叠加多条) - 安装/更新从指定源拉取;未指定时默认官方源
🚧 上述集成尚未实现,当前 launcher 仍为单源固定代理模式。本规范作为开放生态基础,由后续 PHASE 任务细化实施。