From d40c4605b22a453648cf8598db189135143fcfe3 Mon Sep 17 00:00:00 2001 From: iven Date: Thu, 2 Apr 2026 19:16:32 +0800 Subject: [PATCH] =?UTF-8?q?fix(knowledge):=20verification=20audit=20?= =?UTF-8?q?=E2=80=94=203=20medium=20issues?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - create_item: wrap item + version INSERT in transaction for atomicity - update_item handler: validate content length (100KB) before DB hit - KnowledgeChunk: document missing embedding field, safe per explicit SELECT usage --- crates/zclaw-saas/src/knowledge/handlers.rs | 6 ++++++ crates/zclaw-saas/src/knowledge/service.rs | 8 ++++++-- crates/zclaw-saas/src/knowledge/types.rs | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/zclaw-saas/src/knowledge/handlers.rs b/crates/zclaw-saas/src/knowledge/handlers.rs index 3e52d8c..38c7ddd 100644 --- a/crates/zclaw-saas/src/knowledge/handlers.rs +++ b/crates/zclaw-saas/src/knowledge/handlers.rs @@ -273,6 +273,12 @@ pub async fn update_item( ) -> SaasResult> { check_permission(&ctx, "knowledge:write")?; + if let Some(ref content) = req.content { + if content.len() > 100_000 { + return Err(SaasError::InvalidInput("内容不能超过 100KB".into())); + } + } + let updated = service::update_item(&state.db, &id, &ctx.account_id, &req).await?; // 触发 re-embedding diff --git a/crates/zclaw-saas/src/knowledge/service.rs b/crates/zclaw-saas/src/knowledge/service.rs index ee40017..6108a06 100644 --- a/crates/zclaw-saas/src/knowledge/service.rs +++ b/crates/zclaw-saas/src/knowledge/service.rs @@ -296,6 +296,9 @@ pub async fn create_item( )); } + // 使用事务保证 item + version 原子性 + let mut tx = pool.begin().await?; + let item = sqlx::query_as::<_, KnowledgeItem>( "INSERT INTO knowledge_items \ (id, category_id, title, content, keywords, related_questions, priority, tags, created_by) \ @@ -311,7 +314,7 @@ pub async fn create_item( .bind(priority) .bind(tags) .bind(account_id) - .fetch_one(pool) + .fetch_one(&mut *tx) .await?; // 创建初始版本快照 @@ -328,9 +331,10 @@ pub async fn create_item( .bind(keywords) .bind(related_questions) .bind(account_id) - .execute(pool) + .execute(&mut *tx) .await?; + tx.commit().await?; Ok(item) } diff --git a/crates/zclaw-saas/src/knowledge/types.rs b/crates/zclaw-saas/src/knowledge/types.rs index 09cd2e4..b787aad 100644 --- a/crates/zclaw-saas/src/knowledge/types.rs +++ b/crates/zclaw-saas/src/knowledge/types.rs @@ -121,6 +121,8 @@ pub struct ItemResponse { } // === 知识分块 === +// 注意:DB 表含 embedding vector(1536) 列,但当前所有查询均显式指定列, +// 故 struct 暂不映射该字段。若未来使用 SELECT * 需添加 embedding: Option。 #[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)] pub struct KnowledgeChunk {