Commit Graph
9 Commits
Author SHA1 Message Date
GaoYiYuan_0626 66ec7eba08 feat: C6 FR-10 代理人行为链 RISK-008
代理人异常行为链识别(RISK-008)落地:
- 新增 agent_behavior_service:三条件证据聚合(A 诱导调仓/B AUTH_403_SCOPE 越权试探/C AUTH_403_NOT_OWNER|NOT_ASSIGNED 越权查询),按代理人维度独立出 pattern 单,payload.actor_id 指向代理人,审计仅 INSERT event_type=agent_behavior_detected。
- risk_repository 新增 list_audit_events / find_agent_behavior_alert / merge_agent_behavior_payload(同日同代理人一张单,证据并集)。
- trade_gateway.submit_trade 补 actor_id 透传(代理人发起交易归属发起人,缺省 SYSTEM);simulate 路由传入 auth.actor_id。
- chat_tools 新增 query_agent_behavior 只读 Tool(agent_id 过滤 + 客户脱敏),tool_service 补意图词与摘要。
- scripts/cron/agent_behavior_scan.py 定时扫描脚本。
- 修复 append_alert_event 序列化缺 default=str(C6 evidence 含 datetime 字段)。
- 单测 12 例(_count_induce 边界 / 三条件 / 出单去重 / payload 归属 / Tool 过滤脱敏)。
全量 pytest 482 passed 0 failed(470 基线 + 12 C6)。
2026-09-07 19:53:39 +08:00
GaoYiYuan_0626 90d0660b44 feat: C5 FR-9 预警处置时效升级(RISK-007,P0)
- 仓储:新增 list_pending_alerts_all / update_alert_escalation(统一读改写 payload,
  升级标记独占写入,status/handler_* 列不碰;_parse_alert 补 created_at/handled_at
  字符串→datetime 解析,兼容 sqlite 原生 DDL)
- escalation_service.scan_and_escalate:扫描判级(普通 4h/24h、AML 1h/4h 短通道)、
  幂等闸门(仅升不降)、先持久化再推送、按 (customer_id,level) 降噪合并一次推送、
  通知链累积(L1 含 risk_manager / L2 含 compliance)、逐单+任务级审计
- scripts/cron/escalation_scan.py:15min 定时扫描壳(sys.path 引导 + new_trace + JSON 摘要)
- 对话线 query_overdue_alerts Tool + 注册表 + 意图词(置于 alert_query 之前)+ summarize 分支
- C5 前置:seed STAFF-31001/31002(risk_manager) + deps 矩阵放行 + chat.py 显式 deny +
  risk.py 台账全量只读分支;JWT 手册 §5.3/§5.4/§6.1 增补 risk_manager
- 测试:conftest 回拨 fixture + test_escalation_service(9) + risk_api/manager(5) +
  chat deny(1) + chat_tools overdue(2);全量 470 绿(453+17)
2026-09-07 19:28:04 +08:00
GaoYiYuan_0626 fe4801bc0a feat: C4 FR-8 持仓集中度预警(RISK-006)
依据《实现方案-风控追加需求v1.1-C4C6.md》§2;不改表结构(alert_type/status
复用 payload 承载,audit_log.event_type 为 VARCHAR 可直接扩)。

1. settings.py + .env.example:一次性加齐风控追加 v1.1 共 11 项配置(C4~C6 共用)。
2. core_ro.concentration_profile(customer_id, limit=500):一次 SQL 取明细
   (LIMIT limit+1 探测截断)+ Python 端按 min_risk_code in (R4,R5) 聚合;
   收口挂账 #1(PRD 字面为 list_holdings,改聚合封装,docstring 注明偏离)。
3. rules.py:RULE_SCORES/RULE_ALERT_TYPES 加 RISK-006=60/pattern;RuleHit 加
   alert_subtype;RiskThresholds 加 concentration_threshold 且 from_settings
   必须补读(评审 P1-2:漏读会让 conftest monkeypatch 失效打穿现有断言);
   新增纯函数 rule_concentration——空仓不触发、截断视同达标(保守告警)、
   阈值边界 79.9% 不触发 / 80% 触发、R4+R5 为 0 不触发。
4. engine.process_trade_event:run_rules 之后、record_trade_alerts 之前并入
   集中度命中(不动 run_rules 签名);命中后 L3 打 high_risk_concentration
   标签 + 写 risk_concentration 审计(金额只落合计与前 5 条摘要)。
5. risk_repository:find_pending_event_alert 改候选 LIMIT 50 + Python 过滤掉
   payload.alert_subtype 含 agent_behavior 的单(评审 P0-1:代理人维度行为链单
   不得充当客户维度事件单的聚合锚点);append_alert_event 加 extra_subtypes
   合并进 payload.alert_subtype(不传时行为与原先一致,向后兼容)。
6. alert_service:subtypes 集合维护(空集不注入 payload,评审 P2-3);
   追加时 alert_type 按「老单规则 ∪ 本批规则」重算(评审 P1-3,修掉既有
   large_amount 单被本批仅 RISK-006(60) 翻转为 pattern 的缺陷);
   _publish_alert 加 notify_role/extra 可选参数(C5/C6 复用)。
7. 对话线:chat_tools.customer_context 加 profile(concentration_ratio/
   r45_value/total_value/holdings_truncated),tool_service.summarize 加
   「高风险持仓占比 X%(仅供参考)」;不新增意图词。
8. 02-redis-keys.md 增补 alert_subtype / escalation_level 附加推送字段。

测试:conftest 加 autouse _disable_concentration_rule(阈值推 1.01 做回归隔离,
现有用例断言零改动);test_risk_rules 加 RISK-006 纯函数 6 例;新建
tests/test_concentration_c4.py 11 例(与 RISK-001 同单聚合、score max=70、
L3 tag、risk_concentration 审计、仅集中度也出单、subtype 合并、P0-1 回归、
alert_type 不翻转、对话线 ratio)。全量 453 绿(436 + 17)。
2026-09-07 19:05:02 +08:00
GaoYiYuan_0626 38da477be4 AL-06: 对话 Tool 与 API 响应对齐 main 基准——chat_tools.suitability_check 返回体扩展 match_result/mismatch_type/requires_disclosure/needs_branch_confirm/block_response_code/rule_refs(替代 rule_id/reasons/effective_level 展示),check_source='r02_chat',not_found 转结构化 found=False(NotFoundError except 死代码清除);tool_service.summarize suitability 分支按新枚举重写文案(网点当面确认 FM-01/签署风险揭示书/测评过期 FM-03/专业豁免,附 rule_refs 依据);risk_api 断言改 block_response_code。全量 373 passed 0 failed(1 skip=test_suitability 占位待 AL-07)。遗留:chat 链路 risk_suitability_log.actor_id 暂落 SYSTEM(run_tool 统一透传需动 core_tools/kb_tools 冻结 func 契约,发起者留痕已由 agent_tool_call 覆盖) 2026-09-07 17:39:04 +08:00
GaoYiYuan_0626 1c51149912 feat: T21-5 知识库 Tool 接入对话——kb_tools(search_knowledge)挂统一注册表第三层; ToolSpec 新增 skip_access_check(公开知识无归属语义, advisor 无绑定客户可查, 意图层限定 customer/advisor); 意图关键词 customer/advisor 组尾挂 kb 词(Core 词优先, risk 不开放); tool_node 按 spec 白名单注入 query; summarize 溯源口径; 单测 13 例, 425 绿 2026-09-07 12:05:36 +08:00
GaoYiYuan_0626 930ea9db56 feat: 阶段C 风控对话线(C1 四只读 Tool + C2 risk 分支意图 + C3 A-6 验收与边界)
- C1: app/service/risk/chat_tools.py 新增 alert_query/customer_context/suitability_check/aml_lookup 四只读 Tool,挂 RISK_TOOL_REGISTRY(与 core_tools.ToolSpec 同构)
- C1: tool_service.run_tool 改查 core+risk 统一注册表并恒传 risk_repo;_normalize_params 读 spec 白名单;core_tools 三函数加 risk_repo=None;summarize 补四工具分支
- C2: match_intent 按 agent 分组扩 risk 关键词;agent_service.tool_node 守卫放宽(requires_customer=False 的 Tool 允许无绑定客户运行,支撑 A-6 全局待审)
- C3: A-6 验收(risk_officer 问待审预警→alert_query 全量→回复含待审数)+ 诱导处置边界(无处置 Tool、系统提示禁自动处置、诱导只触发只读且预警状态不变)
- 测试 tests/test_risk_chat_tools.py(21 例);全量 pytest 342 绿(原 321 + 21)
2026-09-07 10:26:54 +08:00
GaoYiYuan_0626 1216d26083 fix: T-04 复审闭环——P2-1 test_chat 夹具补 _risk_repo 打桩(防越权双写写脏演示 MySQL)/P3 归属码改为显式集合+前缀兜底/truncated 判定多取 1 条防恰好 500 误报, 321 绿 2026-09-07 09:51:38 +08:00
GaoYiYuan_0626 40a9ee21a6 fix: T-04 评审闭环——P1-1 留痕降级提 error 带定位字段/P1-2 对话越权接鉴权双写(utils/authz.py 下沉公共出口,deps 复用,service 不反向依赖 api)/P2 入参白名单+days 钳制[1,365]/list_holdings SQL LIMIT+truncated/时间窗集中 _now_naive; 补测 24 例(days 边界/非法入参/inactive 归属/双写断言/降级日志/上下文截断), 321 绿 2026-09-07 09:42:37 +08:00
GaoYiYuan_0626 301c78edc3 feat: T-04 Core RO Tool 节点——chat Tool 接入+归属校验+agent_tool_call 落库
- app/tool/core_tools.py: 三只读 Tool(query_customer_profile/holdings/recent_trades, Core RO 仅 SELECT) + TOOL_REGISTRY 白名单(requires_customer); JSON 安全化(Decimal 两位/时间 isoformat)
- app/service/tool_service.py: match_intent 关键词意图(仅 customer/advisor; risk/analyst 空转归 C1/C2) + assert_tool_access 归属断言(customer 本人/advisor assigned/risk_officer 全量/其余拒, 口径对齐 deps.assert_customer_access) + run_tool 编排(白名单→校验→执行→agent_tool_call 落库, 落库失败降级 warning)
- agent_service: 图 START→tool→llm→guard; Tool 结果注入 LLM 上下文(SystemMessage); 降级回复带 Tool 摘要; chat() 可选 session 上下文(缺省空转, T-07 兼容)
- session_repository: insert_tool_call(message_id 一期 NULL, session_id+trace_id 可还原)
- 归属拒绝口径: Tool 层不抛 403 改 blocked 留痕(AUTH_403_* 同码), 对话内呈现——API 层 deny 铁律不变
- tests: test_chat_tools 20 例(三态+落库字段+降级+图注入) + test_chat 4 例(全链路/JWT 外 debug 通道), _ddl 补 agent_tool_call/core_holding, 297 绿
- 真库冒烟: uvicorn+真 MySQL/Redis chat 触发持仓查询 success 落痕 47ms, 现场已清理
2026-09-07 08:43:36 +08:00