统一 DirectProject 流式增量脱敏
对 reasoning 与 agentMessage 增量复用历史正文脱敏和截断规则 补充密钥与绝对路径不泄露的 Rust 回归测试
This commit is contained in:
@@ -1124,6 +1124,16 @@ fn direct_codex_reasoning_delta_event(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// DirectProject 的流式正文在进入 Thread Manager 前就完成脱敏;前端不得接触原始增量。
|
||||||
|
fn direct_codex_thread_delta_event(
|
||||||
|
root: &std::path::Path,
|
||||||
|
item_id: String,
|
||||||
|
kind: DirectThreadDeltaKind,
|
||||||
|
delta: &str,
|
||||||
|
) -> DirectThreadEvent {
|
||||||
|
DirectThreadEvent::item_delta(item_id, kind, direct_thread_delta_text(root, delta))
|
||||||
|
}
|
||||||
|
|
||||||
/// 通知 → 回合事件的唯一分类函数:运行态读取器与单测共用这一份。
|
/// 通知 → 回合事件的唯一分类函数:运行态读取器与单测共用这一份。
|
||||||
///
|
///
|
||||||
/// 读取器只负责"必须有 turnId 才处理"的前置条件与节流(活动 / 正文),分类不在这里之外
|
/// 读取器只负责"必须有 turnId 才处理"的前置条件与节流(活动 / 正文),分类不在这里之外
|
||||||
@@ -3105,10 +3115,11 @@ impl CodexAppServerConnection {
|
|||||||
&direct_thread_id,
|
&direct_thread_id,
|
||||||
// 事件自足:增量自带 item 身份与正文类别(正文 / 思考),
|
// 事件自足:增量自带 item 身份与正文类别(正文 / 思考),
|
||||||
// 前端 reducer 不允许靠猜 itemId 的来源决定 kind。
|
// 前端 reducer 不允许靠猜 itemId 的来源决定 kind。
|
||||||
DirectThreadEvent::item_delta(
|
direct_codex_thread_delta_event(
|
||||||
|
history_root,
|
||||||
item_id.clone(),
|
item_id.clone(),
|
||||||
DirectThreadDeltaKind::Message,
|
DirectThreadDeltaKind::Message,
|
||||||
delta.clone(),
|
&delta,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -3144,10 +3155,11 @@ impl CodexAppServerConnection {
|
|||||||
if self.inner.workspace_mode == CodexAppServerWorkspaceMode::DirectProject {
|
if self.inner.workspace_mode == CodexAppServerWorkspaceMode::DirectProject {
|
||||||
append_direct_thread_event(
|
append_direct_thread_event(
|
||||||
&direct_thread_id,
|
&direct_thread_id,
|
||||||
DirectThreadEvent::item_delta(
|
direct_codex_thread_delta_event(
|
||||||
|
history_root,
|
||||||
item_id,
|
item_id,
|
||||||
DirectThreadDeltaKind::Reasoning,
|
DirectThreadDeltaKind::Reasoning,
|
||||||
delta,
|
&delta,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -4893,6 +4905,31 @@ mod tests {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn direct_thread_message_and_reasoning_deltas_are_sanitized_before_enqueue() {
|
||||||
|
let root = std::path::Path::new("/workspace/direct-project");
|
||||||
|
let raw = "key=sk-abcdefghijklmnop project=/workspace/direct-project/assets/a.png private=/root/secret.txt";
|
||||||
|
for kind in [
|
||||||
|
DirectThreadDeltaKind::Message,
|
||||||
|
DirectThreadDeltaKind::Reasoning,
|
||||||
|
] {
|
||||||
|
let event = direct_codex_thread_delta_event(root, "item-1".to_string(), kind, raw);
|
||||||
|
let wire = serde_json::to_string(&event).expect("serialize direct thread delta");
|
||||||
|
assert!(
|
||||||
|
!wire.contains("sk-abcdefghijklmnop"),
|
||||||
|
"不得泄漏密钥:{wire}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!wire.contains("/root/secret.txt"),
|
||||||
|
"不得泄漏绝对路径:{wire}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
wire.contains("assets/a.png"),
|
||||||
|
"项目内绝对路径应归一成相对路径:{wire}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 判据:读取器与单测共用同一个分类函数,这些分支的行为被钉在这里。
|
/// 判据:读取器与单测共用同一个分类函数,这些分支的行为被钉在这里。
|
||||||
///
|
///
|
||||||
/// 参数:method / params / 正文候选 / 安全活动类别 / turnId。
|
/// 参数:method / params / 正文候选 / 安全活动类别 / turnId。
|
||||||
|
|||||||
@@ -365,6 +365,14 @@ fn item_text(root: &Path, item: &Value) -> Option<String> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 流式正文与完成态条目使用同一套脱敏和字符预算,避免增量文本绕过历史投影的安全边界。
|
||||||
|
pub(crate) fn direct_thread_delta_text(root: &Path, value: &str) -> String {
|
||||||
|
bounded(
|
||||||
|
&sanitize_detail_text(root, value),
|
||||||
|
DIRECT_THREAD_TEXT_MAX_CHARS,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn item_at_ms(item: &Value, observed_at_ms: u64) -> u64 {
|
fn item_at_ms(item: &Value, observed_at_ms: u64) -> u64 {
|
||||||
let from_metadata = item
|
let from_metadata = item
|
||||||
.get("internal_chat_message_metadata_passthrough")
|
.get("internal_chat_message_metadata_passthrough")
|
||||||
|
|||||||
Reference in New Issue
Block a user