观测面 Actor 边界(INV-OBS-08/09/10)
wesgine 观测子系统中的 Actor 边界设计,确保每位用户只看到自己的 Run 记录和工具调用。
核心问题
观测面是 Actor 边界的第三个面。难在分类错误——"观测"听起来是元数据,于是没人把它当数据边界看。
但 wes_tool_calls.input/output 是:
- 文件内容
- 命令输出
- 检索命中
work_dir 是目录结构。这些不是元数据,是数据。
空 actor 是合法值
诊断特征:空 actor 是合法值(跨 actor 管理视图)。
所以漏传参数:
- 不是编译错误
- 不是运行时错误
- 不返回空集
- 返回一次可用的越权读取
症状与"功能正常"同形。
INV-OBS-08:三层单点收敛
SQL 谓词
internal/observe/actor.go 的 actorClause 单点:
func actorClause(actor string) (string, []any) {
if actor == "" {
return "", nil // admin 全 Cell 视图
}
return "AND json_extract(tags, '$.actor') = ?", []any{actor}
}
对于无自己 tags 列的表(wes_tool_calls / wes_turn_traces),使用 runOwnedByActor 的 EXISTS 子查询借父 Run 的归属。
请求边界
一律 actorFromRequestOrContext(req):
?actor=只对 admin token 生效- 非 admin 一律取 token 里的 actor
关键约束
- 过滤在
LIMIT之内(不是页外过滤) GetRunDetail对别人的 Run 与不存在返回同一句(不给存在性预言机)tags是 TEXT 列用JsonExtractLenient(坏行对 actor 隐藏、对管理视图可见)
INV-OBS-09:证据链不过滤
/observe/evidence 与 /audit/* 反向裁决:
- 抬作用域到
cell:admin - 按 Cell 全量不过滤
理由:证据链是逐 Run hash chain,切片后缺环无法校验。"只给我看我自己的审计记录"不是审计。
声明必须排在 defaultCellRequiredScope 的 /observe 泛前缀之前(Go switch 按序匹配)。
INV-OBS-10:事件环也要守
事件先进 per-Run 内存环再进 wes_run_traces,只守 SQL 那一侧等于把最新最全的一份留在门外。
重放流吐原始 engine.Event,Data 带工具输入输出与模型输出。
RunVisible 单点
func RunVisible(owner, actor string) bool {
if actor == "" { return true } // admin
return owner == actor
}
闸门 60-actor-single-judgement.sh 的 run_owner_cmp 规则禁止别处手写 owner == actor。
无主 Run
没有 owner 意味着 actor 在某处没被传下去。
"我不知道这是谁的"的安全读法是隐藏,不是"大家的"。
不属于你与不存在同返空流。
聚合查询注意事项
无 GROUP BY 的聚合在零行上仍返回一行,MAX of nothing 是 NULL。
加了 actor 过滤之后"零匹配行"从边角变成新用户的第一次访问。
-- ✅ 必须 COALESCE
SELECT COALESCE(MAX(created_at), '') FROM wes_run_traces WHERE ...
-- ❌ 首访 500
SELECT MAX(created_at) FROM wes_run_traces WHERE ...
Token 用量查询
GET /cells/{id}/observe/token-usage
?group_by=model&tags=actor:alice&from=2026-01-01&to=2026-12-31
支持 GroupBy(model / agent / session / day / tag:actor)+ Tags / Model / Session / From / To 多维过滤。
各产品场景
| 产品 | 观测面影响 |
|---|---|
| wescode | actor 恒为 "local",无边界问题 |
| wesclaw 桌面 | N=1,无边界问题 |
| wescraft 团队 | 多 actor,观测面生效 |
| 企业版 | 部门多员工,Run/工具调用按员工隔离 |