docs(gateway): gateway 第 2 批 5 个文件注释改中文(只改注释,代码零字节改动)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

主人 2026-10-03 拍板「注释一律中文」。本批 = WS 上行门与握手回放那批文件:
ws_hub.go / ws_history.go / ws_route.go / ws_role_gate_test.go / voice_signal_test.go
含中文的整行注释 6 → 148;无行尾注释。

校验(判据 = "只改注释、零代码字节改动"):
- git diff -U0 | 排除 +++/--- / 注释行 / 空行 / 行尾注释 → 为空
  (含"把纯空行变动也视为违规"的更严变体,同样为空)
- 独立实现:两侧剥掉注释后逐行比对代码文本 → 5/5 全等
- gofmt -l 干净(改动前同样干净,不存在"顺手格式化")
- go test ./... 全绿;go build/vet 绿;linux/amd64 + darwin/arm64 交叉编译绿
安全约束强度逐句保留:ws_route.go 的「默认拒(非黑名单)/ 删掉它等于放开一切」、
ws_history.go 的「门在 replayHistory 第一条语句 / 扩角色须先登记 design/11 §7.2 /
回放不含 thinking」、ws_role_gate_test.go 的测试名与断言字面量一字符未改。
This commit is contained in:
AskaEth committed 2026-10-03 22:10:33 +08:00
1 parent fe1ff33115
commit 355f81d04a
5 files changed
+149 -181

No files matched your search

+17 -20
View File
@@ -4,31 +4,28 @@ import (
"context"
)
// wsReplayLimit is the number of most-recent messages replayed to a connecting
// client. It is intentionally small so a reconnect is cheap; the frontend pulls
// the full active-session history via REST (design/16 §4.1) and the replay is
// only there to give a brand-new connection immediate context.
// wsReplayLimit 是回放给新接入客户端的最近消息条数。刻意取小值,使重连代价
// 低廉;完整活跃会话历史由前端走 REST 拉取(design/16 §4.1),回放只是让
// 一条全新连接立刻拿到上下文。
const wsReplayLimit = 50
// replayHistory sends the most recent messages for sessionID to a single,
// freshly-registered connection as a ws "history" event.
// replayHistory 把 sessionID 最近的若干条消息作为 ws "history" 事件发给
// 单条刚注册的连接。
//
// The replay carries the main session's message bodies, so it is owner/admin only
// (design/11 §7.2 A, decided by the owner on 2026-10-03). ownerAdminClaims is the
// same predicate the proactive push uses, so 「who may be handed the owner's
// conversation unasked」 is answered in one place instead of per caller. A viewer
// connection completes the handshake with no replay at all: its read-only window
// is the REST monitoring surface (design/11 §7.1 「语义澄清」), not a push.
// 回放携带主会话的消息正文,因此仅限 owner/admin(design/11 §7.2 A,主人于
// 2026-10-03 决策)。ownerAdminClaims 与主动推送用的是同一判据,所以
// 「谁可以在未被要求的情况下拿到主人的对话」只在一处回答,而不散落到各调用点。
// viewer 连接完成握手时完全不做回放:它的只读窗口是 REST 监控面
// (design/11 §7.1「语义澄清」),不是推送。
//
// The gate lives here rather than at the register/replay call site in
// ws_hub_conn.go on purpose: this is the only function that emits the replay, so
// no future caller can reach it without the check. A role the owner later wants
// to serve the replay to has to be registered in design/11 §7.2 first, exactly
// like an inbound frame (see ws_route.go).
// 门放在这里而不是 ws_hub_conn.go 里的 register/回放调用点,是刻意的:
// 这是唯一发出回放的函数,此后任何调用者都无法绕开该检查。日后主人想让某个
// 角色也收到回放,必须先把它登记到 design/11 §7.2,与上行帧的做法完全一致
// (见 ws_route.go)。
//
// It is best-effort: a nil store or a read error skips the replay silently.
// Thinking is NOT included (design/16 §6), so the frame never leaks
// chain-of-thought even to owner/admin.
// 回放是尽力而为:store 为 nil 或读取出错都静默跳过。
// 回放不含 thinking(design/16 §6),因此该帧即使对 owner/admin
// 也不会泄漏思维链。
func (h *hub) replayHistory(c *wsConn, sessionID string) {
if !ownerAdminClaims(c.claims) {
return