feat: 增强规则资产管理与审计页面运行时调试

后端新增规则资产版本管理和规则文件 CRUD 接口,优化风险
规则生成模板执行和员工数据模型字段,知识库 RAG 增强本
地回退和文档提取能力,清理旧风险规则文件统一由生成引擎
管理,前端审计页面增加运行时调试面板和规则资产编辑交互,
补充单元测试覆盖。
This commit is contained in:
caoxiaozhu
2026-05-24 21:44:17 +08:00
parent 575f093c74
commit 50b1c3f9a9
113 changed files with 13896 additions and 5044 deletions

View File

@@ -23,7 +23,16 @@ from app.schemas.agent_asset import (
AgentAssetRead,
AgentAssetReviewCreate,
AgentAssetReviewRead,
AgentAssetRiskRuleEnabledUpdate,
AgentAssetRiskRuleGenerateRequest,
AgentAssetRiskRuleLatestTestSummary,
AgentAssetRiskRuleReportRequest,
AgentAssetRiskRuleReturnRequest,
AgentAssetRiskRuleSampleTestRequest,
AgentAssetRiskRuleScenarioTestRequest,
AgentAssetRiskRuleSimulationRead,
AgentAssetRiskRuleSimulationRequest,
AgentAssetRiskRuleTestRunRead,
AgentAssetRuleJsonRead,
AgentAssetRuleJsonWrite,
AgentAssetSpreadsheetChangeRecordRead,
@@ -131,6 +140,116 @@ def get_agent_asset_rule_json(
_handle_asset_error(exc)
@router.get(
"/{asset_id}/risk-rule-tests/latest",
response_model=AgentAssetRiskRuleLatestTestSummary,
summary="读取风险规则最近测试摘要",
description="返回当前风险规则工作版本最近一次样例测试、场景试运行和测试报告。",
)
def get_agent_asset_risk_rule_latest_test(
asset_id: str,
_: CurrentUser,
db: DbSession,
) -> AgentAssetRiskRuleLatestTestSummary:
try:
return AgentAssetService(db).get_latest_risk_rule_test_summary(asset_id)
except Exception as exc:
_handle_asset_error(exc)
@router.post(
"/{asset_id}/risk-rule-tests/simulate",
response_model=AgentAssetRiskRuleSimulationRead,
summary="执行风险规则对话仿真",
description="基于临时对话输入和附件元信息执行风险识别,不创建业务单据,不写入测试记录。",
)
def simulate_agent_asset_risk_rule_test(
asset_id: str,
payload: AgentAssetRiskRuleSimulationRequest,
_: RuleEditorUser,
db: DbSession,
) -> AgentAssetRiskRuleSimulationRead:
try:
return AgentAssetService(db).simulate_risk_rule_message(asset_id, payload)
except Exception as exc:
_handle_asset_error(exc)
@router.post(
"/{asset_id}/risk-rule-tests/sample",
response_model=AgentAssetRiskRuleTestRunRead,
summary="执行风险规则快速样例测试",
description="使用人工样例或系统默认样例执行当前 JSON 风险规则,不依赖大模型判断结果。",
)
def run_agent_asset_risk_rule_sample_test(
asset_id: str,
payload: AgentAssetRiskRuleSampleTestRequest,
current_user: RuleEditorUser,
db: DbSession,
x_actor: ActorHeader = None,
x_request_id: RequestIdHeader = None,
) -> AgentAssetRiskRuleTestRunRead:
try:
return AgentAssetService(db).run_risk_rule_sample_test(
asset_id,
payload,
actor=(x_actor or current_user.name or "system").strip() or "system",
request_id=x_request_id,
)
except Exception as exc:
_handle_asset_error(exc)
@router.post(
"/{asset_id}/risk-rule-tests/scenario",
response_model=AgentAssetRiskRuleTestRunRead,
summary="执行风险规则真实场景试运行",
description="按测试意图读取真实业务样本并沙盒执行风险规则,不写回业务单据。",
)
def run_agent_asset_risk_rule_scenario_test(
asset_id: str,
payload: AgentAssetRiskRuleScenarioTestRequest,
current_user: RuleEditorUser,
db: DbSession,
x_actor: ActorHeader = None,
x_request_id: RequestIdHeader = None,
) -> AgentAssetRiskRuleTestRunRead:
try:
return AgentAssetService(db).run_risk_rule_scenario_test(
asset_id,
payload,
actor=(x_actor or current_user.name or "system").strip() or "system",
request_id=x_request_id,
)
except Exception as exc:
_handle_asset_error(exc)
@router.post(
"/{asset_id}/risk-rule-tests/report",
response_model=AgentAssetRiskRuleTestRunRead,
summary="确认风险规则测试报告",
description="在样例测试和真实场景试运行通过后,保存当前版本测试通过记录。",
)
def confirm_agent_asset_risk_rule_test_report(
asset_id: str,
payload: AgentAssetRiskRuleReportRequest,
current_user: RuleEditorUser,
db: DbSession,
x_actor: ActorHeader = None,
x_request_id: RequestIdHeader = None,
) -> AgentAssetRiskRuleTestRunRead:
try:
return AgentAssetService(db).confirm_risk_rule_test_report(
asset_id,
payload,
actor=(x_actor or current_user.name or "system").strip() or "system",
request_id=x_request_id,
)
except Exception as exc:
_handle_asset_error(exc)
@router.put(
"/{asset_id}/rule-json",
response_model=AgentAssetRuleJsonRead,
@@ -586,6 +705,112 @@ def activate_agent_asset(
_handle_asset_error(exc)
@router.post(
"/{asset_id}/risk-rule-enabled",
response_model=AgentAssetRead,
summary="设置风险规则启用状态",
description=(
"高级管理人员可独立启用或停用 JSON 风险规则;停用后即使已上线也不会进入真实业务扫描。"
),
)
def set_agent_asset_risk_rule_enabled(
asset_id: str,
payload: AgentAssetRiskRuleEnabledUpdate,
current_user: RuleReviewerUser,
db: DbSession,
x_actor: ActorHeader = None,
x_request_id: RequestIdHeader = None,
) -> AgentAssetRead:
try:
asset = AgentAssetService(db).set_risk_rule_enabled(
asset_id,
enabled=payload.enabled,
actor=(x_actor or current_user.name or "system").strip() or "system",
request_id=x_request_id,
)
detail = AgentAssetService(db).get_asset(asset.id)
if detail is None:
raise LookupError("Asset not found")
return detail
except Exception as exc:
_handle_asset_error(exc)
@router.post(
"/{asset_id}/return",
response_model=AgentAssetRiskRuleLatestTestSummary,
summary="回退待审核风险规则",
description="高级管理人员将待审核风险规则回退到草稿,并记录回退原因。",
)
def return_agent_asset_risk_rule(
asset_id: str,
payload: AgentAssetRiskRuleReturnRequest,
current_user: RuleReviewerUser,
db: DbSession,
x_actor: ActorHeader = None,
x_request_id: RequestIdHeader = None,
) -> AgentAssetRiskRuleLatestTestSummary:
try:
return AgentAssetService(db).return_risk_rule(
asset_id,
note=payload.note,
actor=(x_actor or current_user.name or "system").strip() or "system",
request_id=x_request_id,
)
except Exception as exc:
_handle_asset_error(exc)
@router.post(
"/{asset_id}/publish",
response_model=AgentAssetRead,
summary="审核并发布风险规则",
description="高级管理人员确认测试通过后,将待审核风险规则一次性审核通过并发布上线。",
)
def publish_agent_asset_risk_rule(
asset_id: str,
current_user: RuleReviewerUser,
db: DbSession,
x_actor: ActorHeader = None,
x_request_id: RequestIdHeader = None,
) -> AgentAssetRead:
try:
asset = AgentAssetService(db).publish_risk_rule(
asset_id,
actor=(x_actor or current_user.name or "system").strip() or "system",
request_id=x_request_id,
)
detail = AgentAssetService(db).get_asset(asset.id)
if detail is None:
raise LookupError("Asset not found")
return detail
except Exception as exc:
_handle_asset_error(exc)
@router.delete(
"/{asset_id}",
status_code=status.HTTP_204_NO_CONTENT,
summary="删除未发布风险规则",
description="仅允许删除从未发布过的 JSON 风险规则,并同步删除规则 JSON 文件。",
)
def delete_agent_asset(
asset_id: str,
current_user: RuleEditorUser,
db: DbSession,
x_actor: ActorHeader = None,
x_request_id: RequestIdHeader = None,
) -> None:
try:
AgentAssetService(db).delete_unpublished_asset(
asset_id,
actor=(x_actor or current_user.name or "system").strip() or "system",
request_id=x_request_id,
)
except Exception as exc:
_handle_asset_error(exc)
@router.post(
"/{asset_id}/versions/{version}/restore",
response_model=AgentAssetRead,