fix(security): P0 安全修复 — 审计日志 PII 脱敏 + AI Token 计量 + backup.sh 拼写 + CI audit

1. 审计日志 PII 脱敏: audit_service.rs 中 old_value/new_value 自动 mask
   patient/consultation/follow_up 等资源类型的 PII 字段(id_number/phone/name 等)
2. AI Token 计量: chat_handler.rs 从 Provider response 和 AgentOrchestrator 提取
   实际 input_tokens/output_tokens,替代硬编码 0
3. AI display_hints: 从 AgentOrchestrator 传递 display_hints 给前端 ChatResponse
4. backup.sh: PGDATABSE 拼写错误修复为 PGDATABASE
5. CI: npm audit 移除 || true,高危漏洞阻止合并
6. 新增六维度深度分析报告 docs/discussions/2026-05-28
This commit is contained in:
iven
2026-05-29 07:56:29 +08:00
parent ddf5c196e4
commit 03ead44385
5 changed files with 376 additions and 9 deletions

View File

@@ -240,6 +240,14 @@ where
let provider_name = provider_arc.name().to_string();
let supports_fc = provider_name != "ollama"; // Ollama generate_with_tools 未实现
// 收集 token 和 display_hints
#[allow(unused_assignments)]
let mut input_tokens: u32 = 0;
#[allow(unused_assignments)]
let mut output_tokens: u32 = 0;
let mut duration_ms: u64 = 0;
let mut collected_hints: Option<Vec<crate::agent::tool::DisplayHint>> = None;
let result = if supports_fc {
// FC provider执行完整 Agent ReAct 循环
let orchestrator = AgentOrchestrator::new(provider_arc, std::sync::Arc::new(registry));
@@ -256,6 +264,11 @@ where
tracing::error!(error = %e, "AI Agent run failed");
erp_core::error::AppError::Internal("AI 服务暂时不可用,请稍后再试".into())
})?;
input_tokens = agent_result.total_input_tokens;
output_tokens = agent_result.total_output_tokens;
if !agent_result.display_hints.is_empty() {
collected_hints = Some(agent_result.display_hints);
}
agent_result.reply
} else {
// 非 FC provider降级为普通对话
@@ -279,6 +292,9 @@ where
tracing::error!(error = %e, "AI generate failed");
erp_core::error::AppError::Internal("AI 服务暂时不可用,请稍后再试".into())
})?;
input_tokens = resp.input_tokens;
output_tokens = resp.output_tokens;
duration_ms = resp.duration_ms;
resp.content
};
@@ -297,7 +313,7 @@ where
"AI chat response sent"
);
// 记录用量的 token 消耗(简化模式下无法精确计量,记 0
// 记录用量的 token 消耗
if let Err(e) = ai_state
.usage
.log_usage(
@@ -305,9 +321,9 @@ where
&provider_name,
&run_params.model,
"chat",
0,
0,
0,
input_tokens,
output_tokens,
duration_ms,
0,
false,
)
@@ -362,7 +378,7 @@ where
reply,
message_id,
iterations: if supports_fc { 1 } else { 0 },
display_hints: None,
display_hints: collected_hints,
})))
}