Harden auth/vault path sanitization and clean WeKnora docs

This commit is contained in:
Agent Board
2026-07-28 17:04:27 +08:00
parent 2deaf59f7b
commit 26ff1a9c9a
190 changed files with 13454 additions and 4987 deletions
+70 -9
View File
@@ -53,6 +53,21 @@ async fn events_with_stream_delta(
let state_for_stream = state.clone();
let context_for_stream = context.clone();
let query_for_stream = query.clone();
let subscription_workspace = query
.workspace_id
.as_deref()
.map(str::trim)
.filter(|value| !value.is_empty())
.map(str::to_string)
.or_else(|| {
context
.workspace
.workspace_id
.as_deref()
.map(str::trim)
.filter(|value| !value.is_empty())
.map(str::to_string)
});
let stream = stream::unfold(
Some(StreamPollState {
app_state: state_for_stream,
@@ -64,6 +79,7 @@ async fn events_with_stream_delta(
initial_emitted: false,
block_delta_rx,
stream_delta_rx,
subscription_workspace,
}),
move |state| async move {
let mut state = state?;
@@ -76,11 +92,17 @@ async fn events_with_stream_delta(
));
}
// Check block.delta broadcast first
// Check block.delta broadcast first(按订阅 workspace 过滤,防跨工作区泄露)
if let Some(ref mut rx) = state.block_delta_rx {
match rx.try_recv() {
Ok(payload) => {
return Some((Ok(stream_event("block.delta", &payload)), Some(state)));
if delta_matches_workspace(
&payload,
state.subscription_workspace.as_deref(),
) {
return Some((Ok(stream_event("block.delta", &payload)), Some(state)));
}
// 非本工作区:丢弃并继续同一 tick 的后续检查
}
Err(tokio::sync::broadcast::error::TryRecvError::Empty) => {}
Err(tokio::sync::broadcast::error::TryRecvError::Closed) => {
@@ -94,12 +116,17 @@ async fn events_with_stream_delta(
if let Some(ref mut rx) = state.stream_delta_rx {
match rx.try_recv() {
Ok(payload) => {
let hint = build_stream_push_delta_hint(
if delta_matches_workspace(
&payload,
&state.context.trace.request_id,
&state.context.trace.trace_id,
);
return Some((Ok(stream_event("delta", &hint)), Some(state)));
state.subscription_workspace.as_deref(),
) {
let hint = build_stream_push_delta_hint(
&payload,
&state.context.trace.request_id,
&state.context.trace.trace_id,
);
return Some((Ok(stream_event("delta", &hint)), Some(state)));
}
}
Err(tokio::sync::broadcast::error::TryRecvError::Empty) => {}
Err(tokio::sync::broadcast::error::TryRecvError::Closed) => {
@@ -184,11 +211,19 @@ async fn events_with_stream_delta(
state.polls += 1;
sleep(Duration::from_millis(poll_ms)).await;
// Check block.delta after poll sleep
// Check block.delta after poll sleep(同样按 workspace 过滤)
if let Some(ref mut rx) = state.block_delta_rx {
match rx.try_recv() {
Ok(payload) => {
return Some((Ok(stream_event("block.delta", &payload)), Some(state)));
if delta_matches_workspace(
&payload,
state.subscription_workspace.as_deref(),
) {
return Some((
Ok(stream_event("block.delta", &payload)),
Some(state),
));
}
}
Err(tokio::sync::broadcast::error::TryRecvError::Empty) => {}
Err(tokio::sync::broadcast::error::TryRecvError::Closed) => {
@@ -305,6 +340,31 @@ struct StreamPollState {
#[allow(dead_code)]
block_delta_rx: Option<tokio::sync::broadcast::Receiver<Value>>,
stream_delta_rx: Option<tokio::sync::broadcast::Receiver<Value>>,
/// 订阅工作区;broadcast 推送仅转发匹配项,避免跨工作区泄露。
subscription_workspace: Option<String>,
}
/// 仅转发与当前订阅 workspace 一致的 delta(与 ws.rs 同策略)。
fn delta_matches_workspace(delta: &Value, subscription_workspace: Option<&str>) -> bool {
let Some(expected) = subscription_workspace else {
// 无订阅 workspace 时不推送带 workspace 的全局 delta(保守)
return delta
.get("workspaceId")
.and_then(|v| v.as_str())
.map(str::trim)
.filter(|v| !v.is_empty())
.is_none();
};
match delta
.get("workspaceId")
.and_then(|v| v.as_str())
.map(str::trim)
.filter(|v| !v.is_empty())
{
Some(delta_ws) => delta_ws == expected,
// 无 workspace 标记的 delta 不转发(避免跨租户噪声)
None => false,
}
}
fn live_poll_query(query: &StreamSnapshotQuery) -> StreamSnapshotQuery {
@@ -368,6 +428,7 @@ mod tests {
dev_user_id: "dev-user".into(),
dev_user_name: "开发用户".into(),
dev_user_email: "dev@mnote.local".into(),
environment: "dev".into(),
}))
}