feat(routing): Envelope 三档路由 + traceId/hop 防环 + 离线补投 (PR6)#193
Open
raysonmeng wants to merge 1 commit into
Open
feat(routing): Envelope 三档路由 + traceId/hop 防环 + 离线补投 (PR6)#193raysonmeng wants to merge 1 commit into
raysonmeng wants to merge 1 commit into
Conversation
按 spec §3.2 把 broker 从纯 topic 扇出升级为身份感知路由,消费 Store(pending/getMembers)。 - 三档路由:per-ws handler 的 shouldDeliver 过滤——broadcast(无 to → 全发)、@提及(全发, 高亮 client 侧 mentions[])、DM(to:[id] → 仅命名身份,present to 即 DM、空 to → nobody,绝不退化广播)。 - loop prevention:from-skip(绝不回声发送者) + hop<=0 drop(多 hop 泛化)。 - 防伪:publish 入口运行期 envelope 校验(from 必对象/to 必数组/idempotencyKey/roomId 必非空 string) + 无条件 stamp env.from.agentId=认证身份(覆盖客户端伪造)。 - 离线补投:store_if_offline 对 intended(DM=to / broadcast=getMembers) 中不可达身份 enqueuePending; hello(welcome) 与 subscribe 后都 drainPendingTo 补收(覆盖「已连接未订阅」gap 窗口)。 - topicMembers Map<topic,Map<id,count>> 跟踪每 topic 可达身份(支持同身份多连接)。 - 双 hello 守卫(防身份重绑泄漏 topicMembers);drain 移出 auth try/catch(防 store 错误误踢连接)。 测试:broker-routing.test 12 用例(DM 隔离/broadcast 跳发送者/hop-drop/离线补投/防伪/double-hello/ gap-drain/drain-error/空-to/missing-key/**SqliteStore 离线**堵 InMemoryStore 测试盲点);现有测试 改双身份(同身份 pub/sub 被 from-skip 是预期)。full check exit 0:1763 pass / 0 fail。 Cross-review:5 轮(轮1 thorough + 4 lean),抓出并修复 6 个真实 issue——HIGH 缺失/非对象 from 绕过 防伪+防环失效、HIGH drain 在 auth catch 内致 store 错误误踢连接、MED gap 窗口离线丢、MED 双 hello 重绑泄漏、LOW string-to 子串匹配 DM 泄漏、LOW idempotencyKey/roomId 未校验致 SqliteStore 静默丢(§6.4 跨实现分叉)。连续两轮 0 收敛。 Backlog:topic==roomId 双源校验、to 元素类型校验、from.name/agentType 防伪、异步 Store 的 offline+live 原子性(§8.2/PR11)、BrokerClient 暴露 onError、广播离线混合成员测试。 --- feat(routing): three-tier Envelope routing + traceId/hop loop prevention + offline replay (PR6) Upgrade the broker from plain topic fan-out to identity-aware routing (§3.2): broadcast / @mention / DM (by subscriber identity), loop prevention (never echo to sender + hop<=0 drop), anti-spoof (runtime envelope validation + stamp the authenticated sender), and store_if_offline replay (enqueue for unreachable recipients, drain on (re)connect + subscribe). Converged after 5 adversarial rounds that caught + fixed 6 real issues (2 HIGH). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概要 / Summary
PR6:把 broker 从纯 topic 扇出升级为身份感知三档路由 + 防环 + 防伪 + 离线补投(§3.2),消费 Store。
改动 / Changes(集中在
src/broker.ts)shouldDeliverper-ws 过滤:broadcast(无to→全发) / @提及(全发+client 高亮) / DM(to:[id]→仅命名身份;presentto即 DM、[]→nobody、绝不退化广播)hop<=0dropfrom.agentId=认证身份store_if_offline对不可达 intended(DM=to / broadcast=getMembers)enqueuePending;hello + subscribe 后都drainPendingTo(覆盖「已连接未订阅」gap)测试计划 / Test plan
broker-routing.test12 用例:DM 隔离 / broadcast 跳发送者 / hop-drop / 离线补投 / 防伪 / double-hello / gap-drain / drain-error / 空-to/ missing-key / SqliteStore 离线(堵 InMemoryStore 测试盲点)bun run checkexit 0 → 1763 pass / 0 fail、typecheck 干净、bundle 同步Cross-review
5 轮(轮 1 thorough + 4 lean),抓出并修复 6 个真实 issue:
from绕过防伪 stamp → 防环失效 + 转发未认证信封(实证:发送者收到自己广播)drainPendingTo在 auth try/catch 内 → store 错误被当认证失败 → 永久踢掉已认证连接to退化为子串匹配 → DM 泄漏给子串身份idempotencyKey/roomId未校验 → SqliteStoreNOT NULL+OR IGNORE静默丢(InMemoryStore 却投递,§6.4 跨实现分叉)连续两轮 0 真实 issue → 收敛。
Backlog
topic==roomId双源校验、to元素类型、from.name/agentType防伪、异步 Store 的 offline+live 原子性(§8.2/PR11)、BrokerClient 暴露 onError。🤖 Generated with Claude Code