docs(25): 第 16 条复核——两项不成立,另有一项是真缺陷(原报告没写出来)
原描述把三件事混成一条,逐项复核:
**a. exclude 不要求"调查中"** —— 这是**业务规则**,不是技术缺陷。exclude 要求
"已确认 + 未闭环"(:63-66),resolve 额外要求"调查中"(:90);不对称是事实,但
"误报关闭是否必须先经调查"属于业务裁定,代码里那两道门是有意设置的,看不出实现偏差。
需业务方定,不由技术侧单方面加门禁。
**b. min(20, score_before)** —— **误报**。BEHAVIOR_SCORE_INITIAL = 20 是**满分**(:18),
扣分表 {"低":3, "中":5, "高":20}(:19)与之自洽(高危扣满归零),所以这个 min 是把越界
数据拉回合法上限的数据清洗;而且它**不是静默的** —— 审计里同时记了
behavior_score_before / deduction / after(:118-120)。原描述"静默改写"不成立。
**c. 真缺陷(原报告没写)**:ehavior_score 的初始值是 0 而不是满分 20,
**导致扣分机制整体失效**。实测:fin_customer_profile.behavior_score 定义为
int NOT NULL(无默认值),现有画像 customer_id=9001 的值是 **0**。
于是 :103 的计算恒为 min(20, 0) - deduction = -deduction → max(0, ...) = 0:
**扣分永远扣不动,行为分恒为 0**。且全仓只有 :109 一处给 behavior_score 赋值
(写入方只有风控结案),说明初始 0 来自插入画像时的显式赋值,没有任何地方初始化成 20。
影响:行为分是"预警结案 → 客户行为评分下降"这条链路的落点,现在这条链路**产出为零**。
修复点在**画像创建侧**(初始值应为满分),不在风控的扣分逻辑里。
This commit is contained in:
+30
-1
@@ -175,7 +175,36 @@ Asia/Shanghai 展示。北京 08:00 前生成时,统计窗口是"前一日 08:
|
||||
| 13 | 一条脏数据中断整批 | `risk_scan_service.py:468` `int(level.replace(prefix, ""))` 遇非 C1-C5 抛 `ValueError`,`refresh_alerts` 无逐条隔离,`:411` 整批 rollback | 一条脏数据 ⇒ 整批扫描失败 |
|
||||
| 14 | 年龄口径不一 | `risk_scan_service.py:462` 用 UTC 日期,`risk_judgement_service.py:381` 用服务器 `date.today()` | 生日边界差 1 天,65 岁阈值可能翻面 |
|
||||
| 15 | 幂等仅在应用层 | `risk_scan_service.py:332` `_exists` + JSON 列无唯一索引;`:37` 的 asyncio.Lock 仅进程内 | 多 Web worker 并发存在重复告警窗口 |
|
||||
| 16 | 状态跳变与静默截断 | `risk_action_service.py:65-66` 允许"待处理+已确认"直接关误报、跳过调查;`:103` `min(20, score_before)` 静默把 >20 压到 20 | 处置流程可被绕过;评分被静默改写 |
|
||||
| 16 | ~~状态跳变与静默截断~~ **复核后拆成三部分,见下方说明** | `risk_action_service.py:65-66`;`:103` | ~~处置流程可被绕过;评分被静默改写~~ |
|
||||
|
||||
**第 16 条的复核结论(2026-09-11)**:原描述把三件事混成了一条,其中两件不成立、一件是真缺陷。
|
||||
|
||||
**a. `exclude` 不要求"调查中" —— 这是业务规则,不是技术缺陷。**
|
||||
|
||||
`exclude`(`:63-66`)要求 `_require_acknowledged` + `_require_open`,而 `resolve`(`:90`)
|
||||
额外要求 `alert.status == "调查中"`。两者不对称是事实,但**误报关闭是否必须先经调查,是业务
|
||||
规则**:把明显误报(如系统重复触发)也强制走一遍调查,未必是想要的效果。代码里两道门是有意
|
||||
设置的,看不出实现偏差。**需要业务方裁定**,不由技术侧单方面加门禁。
|
||||
|
||||
**b. `min(20, score_before)` —— 误报。**
|
||||
|
||||
`BEHAVIOR_SCORE_INITIAL = 20` 是**满分**(`:18`),扣分表 `{"低":3, "中":5, "高":20}`(`:19`)
|
||||
与之自洽(高危扣满、归零)。所以 `min(20, ...)` 是**把越界数据拉回合法上限**,属于数据清洗。
|
||||
而且它**不是静默的**:审计里同时记了 `behavior_score_before` / `behavior_score_deduction` /
|
||||
`behavior_score_after`(`:118-120`)。原描述说"静默改写"不成立。
|
||||
|
||||
**c. 真缺陷(原报告没写):`behavior_score` 初始值是 0,不是满分 20,导致扣分机制整体失效。**
|
||||
|
||||
实测:`fin_customer_profile.behavior_score` 定义为 `int NOT NULL`(**无默认值**),
|
||||
现有画像 `customer_id=9001` 的值是 **0**。
|
||||
|
||||
于是 `:103` 的计算恒为:`min(20, 0) - deduction = -deduction` → `max(0, ...) = 0` ——
|
||||
**扣分永远扣不动,行为分恒为 0**。而且全仓只有 `risk_action_service.py:109` 一处给
|
||||
`behavior_score` 赋值(写入方只有风控结案),说明**初始值来自插入画像时的显式 0**,
|
||||
没有任何地方把它初始化成 20。
|
||||
|
||||
影响:行为分是"预警结案 → 客户行为评分下降"这条链路的落点,现在这条链路**产出为零**。
|
||||
修复点在**画像创建侧**(把初始值设为满分),不在风控的扣分逻辑里。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user