fix(trace): 白名单放行 session —— 归属标识可读,正文边界不动
主人 2026-10-26 裁定:session 是**业务标识**,不是正文。它是排障时把一条 stderr 日志对回某个会话的唯一线索;而 /admin/flow/graph 本来就按会话返回、连 sessionId 都给了,图里多一个 session 不构成新的暴露。因此把 session 加进共享白名单 (safePropKeys,走 redactValue 的普通清洗),不再被写侧折成 Digest。 「不放宽白名单」仍是原则:本次只放行这一个键,正文的边界一个字没动 —— - trace 侧新增 TestJSONRecorder_KeepsSessionReadableDropsBody,**一条用例同时钉 两件相反的事**:JSONL 里 `"session":"web#lane-2"` 原文可读;同一 span 里的 result / text 哨兵正文仍然搜不到,且只在 omitted 里留下体积与指纹。 - loop 侧真循环用例补一句断言:落盘里 `"session":"sess"` 可读,而工具结果哨兵 同时仍不可见。 - 变异验证:把 session 从白名单摘掉,上述两处都会变红(session 落到 omitted)。 回归:go build ./... + go vet ./... + go test -count=1 ./... 全绿; trace/loop/orchestration 另跑 -race 全绿。
This commit is contained in:
1 parent
003d12a712
commit
6d0df6a825
3 files changed
+52
-2
No files matched your search
@@ -35,6 +35,44 @@ func writeRecords(t *testing.T, recs ...SpanRecord) ([]SpanRecord, string) {
|
||||
return decodeLines(t, buf.Bytes()), buf.String()
|
||||
}
|
||||
|
||||
// TestJSONRecorder_KeepsSessionReadableDropsBody 是「日志里 session 可读、正文仍
|
||||
// 不可见」**同一条断言**(主人 2026-10-26 裁定放行 session):
|
||||
//
|
||||
// - session 是业务标识、不是正文,进白名单后必须**原文可读**(排障要把一条
|
||||
// stderr 日志对回某个会话;变成 Digest 就失去用途);
|
||||
// - 同一 span 里的正文(result / text)仍必须落不到盘上 —— 这一条防的是
|
||||
// 「顺手放宽了别的东西」:白名单加一个键,正文的边界不能跟着动。
|
||||
func TestJSONRecorder_KeepsSessionReadableDropsBody(t *testing.T) {
|
||||
t.Parallel()
|
||||
const session = "web#lane-2"
|
||||
rec := spanRec("sess1", "", "tool.fs.read", SpanKindTool, SpanStatusOK, map[string]any{
|
||||
"session": session,
|
||||
"result": sentinelToolBody,
|
||||
"text": sentinelToolBody,
|
||||
})
|
||||
|
||||
recs, raw := writeRecords(t, rec)
|
||||
if !strings.Contains(raw, `"session":"`+session+`"`) {
|
||||
t.Fatalf("JSONL 里 session 不可读(它是排障对回会话的唯一线索):%s", raw)
|
||||
}
|
||||
if strings.Contains(raw, sentinelToolBody) {
|
||||
t.Fatalf("放行 session 的同时正文也落盘了:%s", raw)
|
||||
}
|
||||
|
||||
got := byID(recs, "sess1")
|
||||
if got.Props["session"] != session {
|
||||
t.Fatalf("session prop = %v, want 原文 %q", got.Props["session"], session)
|
||||
}
|
||||
for _, key := range []string{"result", "text"} {
|
||||
if _, ok := got.Props[key]; ok {
|
||||
t.Fatalf("表外 prop %q 落盘了:%+v", key, got.Props)
|
||||
}
|
||||
if d := omittedEntry(t, got, key); d.SHA256 == "" || d.Bytes == 0 {
|
||||
t.Fatalf("omitted 里没有 %q 的体积/指纹:%+v", key, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestJSONRecorder_DropsRawContentAndKeepsDigest 是写侧投影的主钉:
|
||||
// - 表外的 `result` / `text`(正文形态)绝不落盘;
|
||||
// - 白名单键仍落盘(图上与日志里要能看见 tool / error 之类的元数据);
|
||||
|
||||
Reference in new issue
Block a user