跳转到主要内容

开放注册表协议(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 返回:
启动器竞速下载:同时发起主 URL 与镜像 URL 的请求,取先完成者。无论使用哪个 URL,都必须按 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 任务细化实施。