fix(read)!: 读信只认会话 —— 删掉「同工作区」那道闸门

用户订正:「是应该发到对应 session 的信,因为 agent 多 session 架构,不同 session 的
记忆是隔离的。你之前那个修法简直荒谬」

我把两条轴混在一起了:**工作区**决定 cwd/沙箱/线索可见面,**会话**决定记忆与收件箱。
原先 AgentMayReadSession 判「参与过 + 同工作区」,两头都错:

  · 太松:同工作区内、我参与过的**别的会话**也放行 —— 会话之间记忆隔离,读别的会话
    就是绕过隔离(用户上午的要求本就是"不同 session 不同收件箱");
  · 太严:我在 A 工作区的上下文里读不到**自己刚发起**、落在 B 工作区那条会话。
    zcode 撞上这条,403 文案还写着 cross-workspace ⇒ 它推断出"那五位 agent 不存在"。

新判据两句:① target 必须就是 scope(我当前那条会话);② 我参与过 target(防伪造
session_id)。scope==nil 保持迁移期放行(五家桥实测都带 session_id)。

403 文案换成「这封信不在你当前所在的那条会话里:每个会话各有各的收件箱(会话之间的
记忆是隔离的)。你当前在会话 <id>。要读它,就在它那条会话里读 —— 每封来信都会把 worker
唤醒到它自己那条会话上」。报"我在哪"安全,目标会话在哪不报。

判据:workspace_scope_test 的该用例改名并重写为五条形态(自己那条会话放行 / 同工作区
另一条会话拒 / 别的工作区会话拒 / 伪造 session_id 拒 / 未声明 scope 迁移期放行)。
生产实测:① 200 ② 403 not-your-session(新文案)③ 403(伪造)。
This commit is contained in:
2026-09-15 09:59:21 +08:00
parent a684d479bb
commit 6b86836343
3 changed files with 69 additions and 51 deletions

View File

@ -92,13 +92,20 @@ func canReadSession(w http.ResponseWriter, r *http.Request, agentName string, sc
return true
}
switch reason {
case "cross-workspace":
case "not-your-session":
// ★ 2026-09-15 用户订正:读信这条路只认会话 ——
// 「是应该发到对应 session 的信,因为 agent 多 session 架构,不同 session 的
// 记忆是隔离的」。所以**不再拿工作区当理由**(旧文案就是 cross-workspace,
// 它让 zcode 推断出"那五位 agent 不存在",把错误结论写进了给人看的信里)。
// 报出"我当前在哪条会话"是安全的(那是调用方自己的);**不报**目标会话在哪。
self := ""
if scope != nil {
self = repo.SessionWorkspaceOf(r.Context(), *scope)
self = (*scope).String()
}
Error(w, http.StatusForbidden,
"无权访问该会话:调用方当前所在的工作区是 "+self+",目标会话不在同一个工作区")
"这封信不在你当前所在的那条会话里:每个会话各有各的收件箱(会话之间的记忆是隔离的)。"+
"你当前在会话 "+self+"。要读它,就在它那条会话里读 —— 每封来信都会把 worker 唤醒到"+
"它自己那条会话上,那时你看到的就是那条会话的收件箱。")
default:
Error(w, http.StatusForbidden, "无权访问该会话")
}