fix(addressing)!: 寻址不按工作区筛 + 联系人地址不再从垃圾 from_workspace 拼

用户:「任意 agent 的寻址是任意的,而不是按工作区区分,去落实吧」。

① 拆掉两处"按工作区收窄"(那是我把**寻址**当成了**权限**):
   · AgentListContacts 不再走 ListContactsInWorkspace ⇒ 列表 = 我参与过的会话(事实,不是授权);
   · AgentSuggestAddress 的会话候选不再走 SuggestSessionCandidatesInWorkspace。
   两个 InWorkspace 变体(连同钉旧口径的用例)一并删除,避免死代码。
   生产实测:pi 的联系人从"只剩同工作区"变成 5 条,横跨 TrueAgent/agentmail/其它工作区。
   agentScope 仍调用(校验 session_id 格式 + 未声明时告警),只是它的工作区不再当过滤器。

② 联系人地址的 path 取自**会话**,不再取第一封邮件的 from_workspace:
   `COALESCE(NULLIF(s.workspace,''), NULLIF(m.to_workspace,''), '')`。
   那条老路把地址拼成 `zcode@zcode.<别名>` —— 正是用户预言的"感染":一个可被复制出去的
   错误地址。from_workspace 与"对方在哪"无关,只用 to_*。

③ **清除感染源(数据)**:658 行 from_workspace = from_name(pi 406 / dsh 137 / zcode 89 /
   homeagent 17 / opencode 9)已清空。带去重前备份(/root/gotmp/agentmail-pre-fromws-purge-*.db)
   与回滚脚本,回滚**在副本库上真跑过**(恢复 658 行)才敢落地。
This commit is contained in:
2026-09-15 10:07:18 +08:00
parent 81ec77ae1f
commit a5fc86bc1a
4 changed files with 22 additions and 215 deletions

View File

@ -1124,17 +1124,6 @@ func ListContactsFor(ctx context.Context, forUser string, archived bool) ([]Cont
return listContacts(ctx, forUser, nil, archived)
}
// ListContactsInWorkspace 只在**同一个工作区**里列会话 —— Agent 侧读联系人的默认口径。
//
// 为什么 Agent 侧要收窄:一个 Agent 同时服务所有工作区(见 AgentMayReadSession 的注释),
// 不收窄的话,在 TrueAgent 里干活的 worker 调 list_contacts 会拿到 agentmail 工作区的
// 会话标题、别名与未读计数 —— 而它连看都不该看到(用户 2026-09-14 报的那类越界)。
//
// 人类侧刻意**不走**这条:人的可见性由 `UserCanAccessSession` 与 owner 决定,
// 与工作区不是一回事(一个人类可能同时管好几个项目的会话)。
func ListContactsInWorkspace(ctx context.Context, agentName, workspace string, archived bool) ([]Contact, error) {
return listContacts(ctx, agentName, &workspace, archived)
}
func listContacts(ctx context.Context, forUser string, onlyWorkspace *string, archived bool) ([]Contact, error) {
op := "<>"
@ -1198,7 +1187,13 @@ func listContacts(ctx context.Context, forUser string, onlyWorkspace *string, ar
rows, err := db.DB.QueryContext(ctx, `
SELECT s.session_id,
COALESCE(NULLIF(m.to_name, 'human'), m.from_name) AS agent_name,
COALESCE(NULLIF(m.to_workspace, ''), m.from_workspace) AS path,
-- ★ 2026-09-15:path 取自**会话**,不再取第一封邮件的 from_workspace ——
-- 那一列历史上存的是 **agent 名**(写入侧 bug,已修),于是联系人地址被拼成
-- zcode@zcode.<别名>,而它正是可被复制出去的"错误地址"(用户 09-15:
-- 「错误的老数据直接清除,否则有概率发生感染」—— 这就是那条感染通道)。
-- 顺序:会话的工作区(权威)→ 该会话首封邮件的 to_workspace(寻址时写的那个)
-- → 空。**只用 to_***:from_workspace 与"对方在哪"无关。
COALESCE(NULLIF(s.workspace, ''), NULLIF(m.to_workspace, ''), '') AS path,
COALESCE(s.session_alias, '') AS alias,
s.status,
(SELECT COUNT(*) FROM mails x WHERE x.session_id = s.session_id),