diff --git a/PLAN.md b/PLAN.md index 79acafd..b68a02e 100644 --- a/PLAN.md +++ b/PLAN.md @@ -113,11 +113,48 @@ - `Fabric.Desktop` - `Fabric.Android` +## 7.1 消息编号与顺序语义(已定) +- 每个 Guild 服务为其管理的**每个 Channel/DM 独立分配递增消息序号** `seq`(从 1 开始) +- 消息主键使用 `message_id`(UUID/ULID 均可),排序与断片检测以 `seq` 为准 +- 服务端返回消息默认按 `seq ASC` +- 客户端允许短暂乱序显示,但收到 `seq` 断片时必须触发 range 回补 +- 回补接口:`GET /channels/:id/messages?seq_from=&seq_to=`(DM 同理) +- 一致性目标:**同一 Channel/DM 的最终可见顺序与服务端 `seq` 一致** + +## 7.2 插件扩展契约 v1(已定) +> 本契约为平台中立能力,`Fabric.OpenclawPlugin` 只是其中一个实现方。 + +### A) 出站事件(Fabric -> Plugin) +- 采用 Webhook POST(MVP) +- 事件信封固定字段: + - `event_id`(全局唯一) + - `event_type`(如 `message.created` / `message.updated` / `message.deleted`) + - `occurred_at`(ISO 时间) + - `guild_id` / `channel_id` / `actor_id` + - `data`(事件载荷) +- 鉴权:`X-Fabric-Signature`(HMAC-SHA256,密钥为每个插件独立 secret) +- 幂等:消费端以 `event_id` 去重 + +### B) 入站调用(Plugin -> Fabric) +- 使用 Bot Token(Bearer)访问 Fabric API +- 写接口支持 `Idempotency-Key`,重复提交返回同一结果 +- 标准错误码: + - `400` 参数错误 + - `401/403` 鉴权或权限失败 + - `404` 资源不存在 + - `409` 冲突(如 seq 窗口不匹配) + - `429` 限流 + - `5xx` 服务端错误 + +### C) 重试与限流 +- Webhook 非 2xx 视为失败,指数退避重试:1s / 2s / 4s / 8s / 16s(最多 5 次) +- API 限流采用令牌桶,返回 `429` + `Retry-After` + ## 8. 当前状态 - 所有仓库已创建为 Public - `Fabric.*` 已作为子模块挂载到 `Fabric` - 本体保持平台中立:不包含 OpenClaw 专属业务逻辑 - OpenClaw 相关能力集中在 `Fabric.OpenclawPlugin` - 已确定:Guild 可分布在不同服务器;中心服务/ Guild 服务双层架构 -- 待定:消息顺序一致性细则、插件扩展契约 v1 细节 +- 已确定:消息顺序一致性细则、插件扩展契约 v1 - 本文件为第一版规划,后续按里程碑持续细化