merge: integrate latest qyqy_develop + push docs/41
This commit is contained in:
@@ -539,12 +539,14 @@ tests/unit/api/test_risk_controller.py
|
||||
已实现:
|
||||
|
||||
- 站内通知记录创建。
|
||||
- 邮件通知记录创建,本阶段不外发 SMTP。
|
||||
- 邮件通知记录创建;迁移阶段当时尚未接入 SMTP。
|
||||
- 通知主键和通知编号显式生成。
|
||||
- 通知内容自动包含“预警编号:xxx”。
|
||||
- 高风险批量通知记录。
|
||||
- 通知分页复用 `RiskQueryService` 和 `RiskRepository`。
|
||||
|
||||
> 2026-09-12 更新:本节“本阶段不外发 SMTP”只描述 R6.1 当时状态。当前手动扫描和定时扫描命中高风险后已恢复真实邮件发送,通知状态会回写 `已发送` 或 `发送失败`。当前高风险预警邮件只支持一个收件人。
|
||||
|
||||
验证结果:当前全部风控专项测试共 `58 passed`。
|
||||
|
||||
下一步:R6.2 将高风险通知创建接入扫描事务,并验证通知失败不破坏预警主事务。等待确认后执行。
|
||||
@@ -556,7 +558,8 @@ tests/unit/api/test_risk_controller.py
|
||||
已实现:
|
||||
|
||||
- 扫描生成高风险预警后自动创建站内通知记录。
|
||||
- 可选邮件通知记录,默认不发送 SMTP。
|
||||
- 高风险邮件通知记录和真实 SMTP 外发,发送失败不回滚预警。
|
||||
- 高风险预警邮件当前只支持一个收件人,多个邮箱值只取第一个。
|
||||
- 通知创建使用嵌套保存点隔离。
|
||||
- 通知创建失败只记录日志,不回滚预警扫描主事务。
|
||||
- 扫描结果增加 `notification_count`。
|
||||
|
||||
+44
-18
@@ -72,24 +72,38 @@ D:\conda\envs\jr_py313\python.exe tools\portal.py --base-url http://127.0.0.1:80
|
||||
|
||||
## 3. 员工 · 风控工作台(`risk_t`)
|
||||
|
||||
> 本节按 `docs/风控业务演示文档/17-风控模块-前端合并提示词与验收约束.md` 重写过,功能清单与交互约束都对齐了那份文档。
|
||||
|
||||
| # | 操作 | 预期结果 |
|
||||
|---|---|---|
|
||||
| 3-1 | 进入即自动加载"总览" | 数字卡片;数据范围 `all`(能看全部客户的预警) ✅实测 |
|
||||
| 3-2 | 点「刷新总览」 | 同上,HTTP 200 ✅实测 |
|
||||
| 3-3 | 进入即自动加载"预警列表" | **表格出现**:预警号 / 客户 / 等级 / 规则 / 状态 / 操作。本机实测 2 条:`ALDEMO0002`(高,RW-015/RW-003)、`ALDEMO0001`(中,RW-007/RW-002/RW-012),均"待处理" ✅实测<br>⚠️ **门户刻意不传 `limit`**:该接口 `limit` 上限是 **5**,传 20 会得到 `422 query.limit: Input should be less than or equal to 5`,**整张表格渲染不出来**(行内按钮也随之消失) |
|
||||
| 3-4 | 点「触发一次扫描」 | **HTTP 200,`body.code=0`**(这条以前会因缺幂等头报 422,已修) ✅实测 |
|
||||
| 3-5 | 点「生成日报」 | HTTP 200,返回日报内容 ⚠️按契约 |
|
||||
| 3-6 | 对某条预警点「确认」 | 二次确认后返回业务结果。✅实测:`POST .../acknowledgements` → **409「只有待处理的预警才能确认解决」** —— 该动作**有状态前置条件**,不是任意状态都能点,属正常业务约束(页面会原样显示原因) |
|
||||
| 3-7 | 点「升级」/「解决」 | 同上,各自有状态约束;状态不符时返回 409 ⚠️按契约 |
|
||||
| 3-8 | 点一个**不存在**的预警号 | 404 资源不存在 —— 正常 fail closed ⚠️按契约 |
|
||||
| 3-9 | 用**客户**账号访问风控接口 | **403 缺少操作权限**(`risk_t` 能看,`cust_t` 不能) ✅实测(客户访问 `/admin/roles` 为 403) |
|
||||
| 3-1 | 进入即自动加载"风险概览" | 五张指标卡:**预警总量 / 待处理 / 已超时 / 高风险 / 重点预警** ✅实测(total=2 pending=1 overdue=2 高风险=2 重点=2) |
|
||||
| 3-2 | 看"预警队列" | **每页 5 条**、按风险等级优先、行高固定且超长省略 ✅实测<br>本机 2 条:`ALDEMO0002`(高,RW-015/RW-003)、`ALDEMO0001`(高,RW-007/RW-002/RW-012)<br>⚠️ 该接口 `limit` 上限就是 **5**,传 20 会 422 且**整张表渲染不出来** |
|
||||
| 3-3 | 用筛选栏逐项筛 | 8 个条件:关键词、客户号、风险等级、规则码、产品代码、产品名、起止时间 ✅实测<br>`rule_code=RW-015 → ALDEMO0002`、`customer_no=T-CUST → 2 条`、`keyword=ALDEMO0002 → 1 条`<br>⚠️ **风险等级必须填「高/中/低」**:预警对象用「高」,而概览 `levels` 用「高风险」,填「高风险」会 422 |
|
||||
| 3-4 | 点「下一页 / 上一页」 | 走游标分页(`meta.next_cursor` + `has_more`),页脚显示"第 N 页 · 每页 5 条" ✅实测(本机 2 条 → 已到末页) |
|
||||
| 3-5 | 点某行「详情」 | **弹窗**显示:预警编号、类型、等级与优先级分、处置状态、回执状态、证据归档、规则、到期时间、结案原因、证据摘要、证据快照、客户(行为分/投资者类型/风险标签)✅实测(alert 23 字段、customer 13 字段) |
|
||||
| 3-6 | 弹窗里点「确认接收」 | 二次确认后提交。✅实测:`POST .../acknowledgements`(无 body)→ **409「只有待处理的预警才能确认解决」**,说明该动作有状态前置 |
|
||||
| 3-7 | 弹窗里点「进入调查」 | 二次确认后 `POST .../investigations`(无 body)⚠️按契约 |
|
||||
| 3-8 | 弹窗里点「关闭误报」 | **必须填写理由**(1-500 字),空值会被前端与后端双重拒绝 → `POST .../exclusions {reason}` ✅实测(body 字段已核对) |
|
||||
| 3-9 | 弹窗里点「升级」 | **必须先「确认接收」**,否则 409「请先确认接收预警」;填 `reason` → `POST .../escalations` ✅实测 |
|
||||
| 3-10 | 弹窗里点「完成结案」 | 填 `resolution`(**字段名不是 reason**)→ `POST .../resolutions` ✅实测 |
|
||||
| 3-11 | 点「手动扫描」 | 二次确认后 `POST /alerts/scan` → **HTTP 200, code=0** ✅实测 |
|
||||
| 3-12 | 点「生成日报」 | 弹窗内**流式生成**(SSE:`start` / `progress` / `replace`),生成后可**编辑内容**再填收件人发送 ✅实测(事件类型已核对) |
|
||||
| 3-13 | 点「八类证据」 | 八个页签:**客户 / 产品 / 交易 / 资金 / 持仓 / 登录 / 预警 / 通知**,各带关键词、行为分等级、发送状态、起止时间筛选 ✅实测(8/8 全部 HTTP 200)<br>⚠️ 正确路径是 **`holdings`**,写成 `positions` 会被 422 拒绝 |
|
||||
| 3-14 | 点「通知记录」 | 表格:预警编号 / 类型 / 发送状态 / 时间 ✅实测(HTTP 200) |
|
||||
| 3-15 | 用**客户**账号访问风控接口 | **403 缺少操作权限** ✅实测 |
|
||||
|
||||
> ⚠️ **注意**:`risk_t` 有 `audit:read`,所以它访问 `/api/v1/admin/roles` 是 **200 而不是 403** ——
|
||||
> 这是种子设计如此,不是越权漏洞。
|
||||
>
|
||||
> ⚠️ 行内三条按钮对应 `acknowledgements` / `escalations` / `resolutions` 三个端点,都是**写操作**:
|
||||
> 会在库里留数据与审计,且**受状态机约束**。列表拿不到数据时这三个按钮不会出现 ——
|
||||
> 先确认 3-3 是否正常。
|
||||
> ⚠️ 五个处置动作都是**写操作**,会在库里留数据与审计,且**受状态机约束**(**先确认 → 再调查/误报/升级/结案**)。
|
||||
> 各自动作的请求体不同:确认与进入调查无 body、误报与升级要 `reason`、结案要 `resolution`。
|
||||
> 列表拿不到数据时行内按钮不会出现 —— 先确认 3-2 是否正常。
|
||||
>
|
||||
> ⚠️ **排序局限**:接口没有排序参数,门户只在**当前页内**按风险等级+优先级分排序;跨页整体排序需要服务端支持。
|
||||
>
|
||||
> ⚠️ 本轮顺带修掉一个平台 bug:`rule_code` 筛选此前**恒返回 0 条**(`risk_repository.py` 用
|
||||
> `.contains([code])`,SQLAlchemy 把它编译成 `LIKE`,而列是 JSON 数组,等于匹配字符串
|
||||
> `'["RW-015"]'`)。已改为 `func.json_contains(col, json.dumps(code))`,扫描去重处的同一写法也一并修了。
|
||||
|
||||
---
|
||||
|
||||
@@ -98,14 +112,26 @@ D:\conda\envs\jr_py313\python.exe tools\portal.py --base-url http://127.0.0.1:80
|
||||
| # | 操作 | 预期结果 |
|
||||
|---|---|---|
|
||||
| 4-1 | 进入即加载"邮箱状态" | 数字卡片,HTTP 200 ✅实测 |
|
||||
| 4-2 | 点「拉取邮件列表」 | 表格(邮件 ID / 主题 / 状态 / 操作);**邮箱未配置时**返回空列表或错误说明,不是白屏 ✅实测(HTTP 200) |
|
||||
| 4-2 | 点「拉取邮件列表」 | 表格(邮件 ID / 主题 / 状态 / 操作)。**邮箱未配置时条数为 0**、不白屏 ✅实测(HTTP 200,0 条) |
|
||||
| 4-3 | 点某封邮件的「识别字段」 | 返回识别结果 JSON ⚠️按契约(需库里有邮件数据) |
|
||||
| 4-4 | 点「删除」邮件 | 二次确认后写操作;审计留痕 ⚠️按契约 |
|
||||
| 4-5 | 点「触发邮箱恢复」 | 二次确认后 HTTP 200 ⚠️按契约 |
|
||||
| 4-4 | 点「删除」邮件 | 二次确认后写操作。门户自动带 `operator_id`(= 当前登录 user_id)✅实测(字段齐了才会进业务层) |
|
||||
| 4-5 | 点「触发邮箱恢复」 | ✅实测:`HTTP 200 + body.code=404「邮箱尚未初始化」` —— 请求体已合法,是本机没配邮箱,属正常 |
|
||||
| 4-6 | 在"单据处理"填一个**真实存在**的 task_id,点「识别字段」「规则结果」 | 返回该单据的字段与规则判定 ⚠️按契约 |
|
||||
| 4-7 | 填一个**不存在**的 task_id | 404 资源不存在,页面上原样显示 —— 正常 ⚠️按契约 |
|
||||
| 4-8 | 点「确认单据」/「重试识别」/「创建通知」 | 二次确认后写操作;审计留痕 ⚠️按契约 |
|
||||
| 4-9 | 点「重算结算统计」 | 二次确认后 HTTP 200 ⚠️按契约 |
|
||||
| 4-7 | 填一个**不存在**的 task_id | 422/404,页面上原样显示 —— 正常 ⚠️实测(假 task_id 得到 422) |
|
||||
| 4-8 | 点「确认单据」/「重试识别」/「创建通知」 | 见下方"三个写操作的必填字段",各自会弹窗要必填值 ⚠️按契约 |
|
||||
| 4-9 | 点「重算结算统计」 | ✅实测:要填 `fund_code` + `application_date`(门户已弹窗),**HTTP 200 `code=0` ok** |
|
||||
|
||||
> **场外写操作的三条硬约束**(实测得出,门户已按此实现):
|
||||
>
|
||||
> | 接口 | 必填字段 |
|
||||
> |---|---|
|
||||
> | `mailbox-status/recoveries`、`mails/{id}/deletions`、`documents/{id}/recognition-retries` | `operator_id` |
|
||||
> | `documents/{id}/confirmations` | `decision`(**中文枚举**:确认无误 / 确认异常 / 未处理)+ `operator_id` |
|
||||
> | `documents/{id}/notifications` | `notification_type`(risk / settlement / mail_return / normal_return / exception_return…)+ `operator_id` |
|
||||
> | `settlement-statistics/recalculate` | `fund_code` + `application_date`(**没有** operator_id) |
|
||||
>
|
||||
> `operator_id` 是**防伪校验**:平台会核对它是否等于当前登录用户(传别人的会被拒)。
|
||||
> 实测不传它必得 **422**,所以门户一律自动带本次登录的 user_id,不让你手填。
|
||||
|
||||
> **运营为什么只有 2 项权限却能用**:场外线的服务层用的是**角色门槛**
|
||||
> `{"operator","risk_operator","admin","super_admin"}`(`offsite_fund_service.py:2600`),
|
||||
|
||||
@@ -79,6 +79,16 @@
|
||||
同一用户、同一路径、同一键的重复请求直接回放首次响应;同一键换了请求正文返回
|
||||
`409 IDEMPOTENCY_CONFLICT`。证据上传靠"同一预警只能归档一次"的冲突保护去重。
|
||||
|
||||
## 扫描通知与高风险邮件
|
||||
|
||||
- `POST /alerts/scan` 同时用于手动扫描,定时扫描复用同一 `RiskScanService`。
|
||||
- 高风险预警会创建站内通知和邮件通知。
|
||||
- 邮件发送成功时通知状态为 `已发送`;发送失败时为 `发送失败` 并返回失败原因。
|
||||
- 邮件发送失败不会改变扫描接口的成功状态,也不会回滚预警和站内通知。
|
||||
- `notification_count` 统计站内通知和邮件通知记录总数。
|
||||
- `notification_failure` 只表示通知记录创建失败,不表示 SMTP 邮件发送失败。
|
||||
- `RISK_ALERT_MAIL_RECIPIENTS` 当前只支持一个收件人,多个邮箱只取第一个。
|
||||
|
||||
## 日报和邮件
|
||||
|
||||
| 方法 | 路径 | 功能 | 权限 |
|
||||
|
||||
@@ -48,7 +48,33 @@
|
||||
- 数据库保留 `read_at`、`acknowledged_at` 基线字段,但当前未实现写入逻辑。
|
||||
- 通知接口和前端不返回或展示阅读时间、确认时间。
|
||||
|
||||
## 邮件开关
|
||||
### 高风险预警邮件
|
||||
|
||||
- 手动扫描和定时扫描共用同一套高风险预警邮件发送逻辑。
|
||||
- 高风险预警生成后,后端创建站内通知和邮件通知,并尝试调用真实 SMTP。
|
||||
- 邮件发送成功时,通知状态更新为 `已发送` 并写入发送时间。
|
||||
- 邮件发送失败时,通知状态更新为 `发送失败` 并写入安全失败原因。
|
||||
- 邮件发送失败不回滚预警,也不回滚站内通知。
|
||||
- 当前 `RISK_ALERT_MAIL_RECIPIENTS` 只支持一个收件人。即使配置多个邮箱,也只有第一个邮箱生效。
|
||||
- 高风险预警邮件收件人由后端配置,前端不提供收件人输入框。
|
||||
|
||||
高风险预警邮件配置:
|
||||
|
||||
- `RISK_ALERT_MAIL_ENABLED`
|
||||
- `RISK_ALERT_MAIL_DRY_RUN`
|
||||
- `RISK_ALERT_MAIL_RECIPIENTS`
|
||||
|
||||
高风险预警邮件复用以下 SMTP 配置:
|
||||
|
||||
- `RISK_SMTP_HOST`
|
||||
- `RISK_SMTP_PORT`
|
||||
- `RISK_SMTP_USERNAME`
|
||||
- `RISK_SMTP_PASSWORD`
|
||||
- `RISK_SMTP_SENDER`
|
||||
- `RISK_SMTP_USE_SSL`
|
||||
- `RISK_SMTP_TIMEOUT_SECONDS`
|
||||
|
||||
## 日报邮件开关
|
||||
|
||||
发送日报邮件需要 `risk:report:mail` 权限。
|
||||
|
||||
@@ -72,6 +98,7 @@
|
||||
|
||||
## 收件人
|
||||
|
||||
- 本节多个收件人规则只适用于日报邮件;高风险预警邮件当前只支持一个收件人。
|
||||
- 支持多个收件人。
|
||||
- 收件人去重并校验格式。
|
||||
- 单次最多 10 个收件人。
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
- 定时扫描默认关闭,多个 Worker 同时运行时不重复执行。
|
||||
- 定时扫描成功和失败写入系统审计。
|
||||
- 扫描返回 `notification_failure` 时,页面必须区分成功与通知失败。
|
||||
- 手动扫描和定时扫描命中高风险后,高风险预警邮件按后端配置自动发送;当前只支持一个收件人。
|
||||
- 高风险邮件发送成功后通知状态为 `已发送`,失败时为 `发送失败`,且不影响预警落库。
|
||||
- 重复扫描不重复生成同一交易和规则的预警。
|
||||
- 多规则命中时正确合并。
|
||||
|
||||
@@ -69,6 +71,7 @@
|
||||
- `data_truncated=true` 时不得把计数当作全量。
|
||||
- 误报、处置结果和规则效果正确统计。
|
||||
- 邮件接口要求 `risk:report:mail`,开关关闭时不发送真实邮件。
|
||||
- 日报邮件支持多个收件人;高风险预警邮件只支持一个收件人,两类邮件互不替代。
|
||||
|
||||
## Agent 验收
|
||||
|
||||
@@ -88,7 +91,7 @@
|
||||
5. 展示行为分变化。
|
||||
6. 使用奶龙风控智能助手查询和研判。
|
||||
7. 生成并查看日报。
|
||||
8. 查看通知或邮件 dry-run 结果。
|
||||
8. 查看高风险预警邮件状态,并单独演示日报邮件 dry-run 或真实发送。
|
||||
|
||||
## 通过标准
|
||||
|
||||
|
||||
@@ -27,7 +27,14 @@
|
||||
- Redis 不可用时,缓存和限流可能降级,不影响结构化业务主流程。
|
||||
- Milvus 不可用时,语义记忆关闭,结构化查询继续运行。
|
||||
- 模型服务不可用时,使用模板或规则化降级。
|
||||
- SMTP 未开启时,邮件接口返回禁用或 dry-run。
|
||||
- 日报邮件在 SMTP 未开启或 dry-run 时不会发送真实邮件。
|
||||
- 高风险预警邮件在 SMTP 发送失败时只更新通知状态,不回滚预警。
|
||||
|
||||
## 邮件通知限制
|
||||
|
||||
- `RISK_ALERT_MAIL_RECIPIENTS` 当前只支持一个收件人,多个邮箱配置只取第一个。
|
||||
- 高风险预警邮件和日报邮件是两条独立链路,收件人配置和开关互不替代。
|
||||
- 正式使用不能要求业务人员手工启动 `python -m app.worker.risk_scan_scheduler`。
|
||||
|
||||
## 前端范围
|
||||
|
||||
@@ -52,6 +59,7 @@
|
||||
|
||||
- 主项目合并完成后对齐统一 RBAC 和客户数据范围。
|
||||
- 修复公共 `data_scope` 最高权限跨资源扩散问题。
|
||||
- 将风控定时扫描接入主项目统一 Worker 或统一部署编排,并补充一个收件人以外的多收件人能力评估。
|
||||
- 确认幂等回执与业务 Action 内部提交的事务边界。
|
||||
- 私有前端最后再适配 `data/meta` 列表信封和写接口 `Idempotency-Key`。
|
||||
- 根据合规要求确定会话保留期、脱敏和归档策略。
|
||||
|
||||
@@ -21,11 +21,35 @@
|
||||
|
||||
后续模型开始前端合并前,必须先阅读本目录全部文档,并扫描上述代码和路由。
|
||||
|
||||
## 前端合并前必须对齐的补充口径(2026-09-12)
|
||||
|
||||
本节优先于后文中的概括性描述。前端合并时以本节为准。
|
||||
|
||||
### 风险概览口径
|
||||
|
||||
- 风险概览接口的 `total` 表示当前未闭环预警,状态范围为 `待处理` 和 `调查中`。
|
||||
- `total` 不是当天新增预警,不受 `created_at` 当天范围限制。
|
||||
- 前端指标名称应使用“未闭环预警”,不得继续显示为“今日预警”。
|
||||
|
||||
### 高风险预警邮件
|
||||
|
||||
- 手动扫描和定时扫描命中高风险预警后,后端都会创建站内通知并尝试发送邮件。
|
||||
- 高风险预警邮件由后端配置决定收件人,前端不提供收件人输入框。
|
||||
- 高风险预警邮件当前只支持一个收件人,前端不能按“多收件人”设计配置界面。
|
||||
- 邮件状态取值包括 `待发送`、`已发送`、`发送失败`、`未启用`。
|
||||
- 前端通知记录列表必须展示发送状态和失败原因,不能把“已创建通知记录”显示为“邮件已发送”。
|
||||
- 邮件发送失败不回滚预警,也不等于整次扫描失败。扫描成功后仅刷新通知记录即可看到真实邮件状态。
|
||||
|
||||
### 两类邮件必须区分
|
||||
|
||||
- 高风险预警邮件:手动扫描或定时扫描自动触发,收件人来自风控邮件通知配置。
|
||||
- 日报邮件:用户在高风险日报弹窗中填写收件人后手动发送,与预警扫描邮件互不替代。
|
||||
|
||||
## 二、前端功能范围
|
||||
|
||||
| 页面或区域 | 必需功能 |
|
||||
|---|---|
|
||||
| 风险概览 | 总量、风险等级、待处理、超时、重点预警 |
|
||||
| 风险概览 | 当前未闭环总量、风险等级、待处理、超时、重点预警;不得把总量显示为“今日预警” |
|
||||
| 预警队列 | 风险等级排序、筛选、每页 5 条、分页、弹窗详情 |
|
||||
| 预警详情 | 预警编号、状态、规则、证据、回执、人工处置 |
|
||||
| 证据区域 | 客户、产品、交易、资金、持仓、登录、预警、通知八类证据 |
|
||||
@@ -34,7 +58,7 @@
|
||||
| 证据归档 | 图片和文档上传、归档状态、失败提示 |
|
||||
| 奶龙风控智能助手 | 对话、SSE 输出、工具调用展示、能力边界和免责声明 |
|
||||
| 日报 | 弹窗展示、流式生成、内容编辑、多邮箱发送 |
|
||||
| 通知 | 通知记录、预警编号、发送状态 |
|
||||
| 通知 | 通知记录、预警编号、站内或邮件渠道、发送状态、失败原因 |
|
||||
| 系统提示 | 政策解读、日报入口和预留模块 |
|
||||
|
||||
## 三、排版和交互约束
|
||||
@@ -112,7 +136,9 @@
|
||||
| 上传证据 | 证据上传成功 |
|
||||
| 手动扫描 | 预警扫描完成 |
|
||||
| 生成日报 | 日报生成完成 |
|
||||
| 邮件发送 | 日报发送成功 |
|
||||
| 日报邮件发送 | 日报邮件发送成功 |
|
||||
|
||||
手动扫描成功只表示预警扫描完成。高风险预警邮件发送失败不会让扫描接口返回失败,前端应刷新通知记录,并通过通知的发送状态和失败原因展示真实结果。
|
||||
|
||||
### 失败提示
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
| 项目 | 当前状态 |
|
||||
|---|---|
|
||||
| 统计日期 | 2026-09-11 |
|
||||
| 统计日期 | 2026-09-12 |
|
||||
| 当前分支 | `RM2_develop` |
|
||||
| 当前合并基线 | `origin/qyqy_develop` 主项目风控修复批次 |
|
||||
| 代码状态 | 已完成主项目风控修复合并,全量测试通过 |
|
||||
| 代码状态 | 已完成主项目风控修复合并,专项回归 54 项通过 |
|
||||
| 已推送分支 | `origin/RM2_develop` |
|
||||
| 已合并分支 | `origin/qyqy_develop` |
|
||||
| 私有前端 | `private_frontend/`,未提交、未推送 |
|
||||
@@ -63,11 +63,12 @@
|
||||
### 证据、通知和日报
|
||||
|
||||
- 图片和文档证据归档。
|
||||
- 高风险通知记录。
|
||||
- 高风险站内通知和邮件通知,邮件成功或失败状态可回查。
|
||||
- 九段式日报。
|
||||
- 历史未闭环完整统计。
|
||||
- 日报流式生成。
|
||||
- 多邮箱校验和 dry-run 邮件发送。
|
||||
- 日报多邮箱校验和 dry-run 邮件发送。
|
||||
- 高风险预警邮件真实 SMTP 外发,当前只支持一个收件人。
|
||||
|
||||
### 奶龙风控智能助手
|
||||
|
||||
@@ -124,14 +125,15 @@
|
||||
|
||||
### 定时规则扫描
|
||||
|
||||
状态:已完成。
|
||||
状态:功能已完成,主项目 Worker 接入待办。
|
||||
|
||||
- 新增独立 `RiskScanSchedulerWorker`,不在 Web 进程启动后台线程。
|
||||
- 扫描开关、周期、是否立即执行和重试次数由 `.env` 环境变量控制。
|
||||
- 扫描开关、间隔、轮询频率和重试次数由 `.env` 环境变量控制。
|
||||
- 使用 MySQL 咨询锁防止多个 Worker 重复执行。
|
||||
- 手动扫描和定时扫描共用同一个 `RiskScanService`。
|
||||
- 扫描成功和失败写入系统审计。
|
||||
- 默认关闭,配置开启后才执行。
|
||||
- 当前仍需独立启动 `python -m app.worker.risk_scan_scheduler`;主项目需要改为统一 Worker 注册或统一部署编排。
|
||||
|
||||
### 主项目正式前端
|
||||
|
||||
@@ -170,11 +172,12 @@
|
||||
## 下一阶段建议
|
||||
|
||||
1. 将 `RM2_develop` 与最新 `qyqy_develop` 保持同步。
|
||||
2. 将定时规则扫描的环境变量配置纳入主项目部署配置。
|
||||
3. 按 `17-前端合并提示词与验收约束.md` 合并正式前端。
|
||||
4. 使用主项目真实登录、账号、角色和客户归属完成联调。
|
||||
5. 执行桌面端、移动端、权限、降级和完整业务链路验收。
|
||||
6. 主项目稳定后再实施对话历史、Redis 缓存和长期留存。
|
||||
2. 将定时规则扫描和高风险预警邮件配置纳入主项目部署配置。
|
||||
3. 将定时规则扫描接入主项目统一 Worker 或部署编排,取消业务人员手工启动独立进程。
|
||||
4. 按 `17-风控模块-前端合并提示词与验收约束.md` 合并正式前端。
|
||||
5. 使用主项目真实登录、账号、角色和客户归属完成联调。
|
||||
6. 执行桌面端、移动端、权限、降级和完整业务链路验收。
|
||||
7. 主项目稳定后再实施对话历史、Redis 缓存和长期留存。
|
||||
|
||||
## 完成判定
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
|---|---:|---|
|
||||
| `RISK_SCAN_SCHEDULE_ENABLED` | `false` | 是否开启定时扫描 |
|
||||
| `RISK_SCAN_INTERVAL_MINUTES` | `5` | 扫描间隔,单位分钟 |
|
||||
| `RISK_SCAN_RUN_IMMEDIATELY` | `false` | Worker 启动后是否立即执行 |
|
||||
| `RISK_SCAN_RUN_IMMEDIATELY` | `false` | 仅保留兼容字段,当前不控制启动后的首次执行 |
|
||||
| `RISK_SCAN_RETRY_LIMIT` | `2` | 单轮失败后的重试次数 |
|
||||
| `RISK_SCAN_POLL_SECONDS` | `30` | Worker 轮询配置和到期时间的间隔 |
|
||||
| `RISK_SCAN_POLL_SECONDS` | `30` | Worker 检查扫描是否到期的频率,不是实际扫描间隔 |
|
||||
|
||||
### 证据归档
|
||||
|
||||
@@ -31,6 +31,14 @@
|
||||
| `RISK_EVIDENCE_DIR` | `storage/risk_evidence` | 证据文件归档根目录 |
|
||||
| `RISK_EVIDENCE_MAX_FILE_SIZE_MB` | `10` | 单个证据文件最大大小,单位 MB |
|
||||
|
||||
### 高风险预警邮件
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
|---|---:|---|
|
||||
| `RISK_ALERT_MAIL_ENABLED` | `false` | 是否允许手动扫描和定时扫描发送高风险预警邮件 |
|
||||
| `RISK_ALERT_MAIL_DRY_RUN` | `true` | 为真时只记录 dry-run 结果,不连接 SMTP |
|
||||
| `RISK_ALERT_MAIL_RECIPIENTS` | 空 | 高风险预警邮件收件人;当前只支持一个,多个值只取第一个 |
|
||||
|
||||
### 日报邮件
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
@@ -87,7 +95,9 @@
|
||||
|
||||
- 联调初期保持 `RISK_SCAN_SCHEDULE_ENABLED=false`。
|
||||
- 确认扫描规则和演示数据后,再按需改为 `true`。
|
||||
- 邮件先保持 `RISK_DAILY_REPORT_MAIL_DRY_RUN=true`。
|
||||
- 高风险预警邮件先保持 `RISK_ALERT_MAIL_DRY_RUN=true`,确认预警落库和通知记录无误后再关闭 dry-run。
|
||||
- 当前高风险预警邮件只支持一个收件人,多邮箱配置只会有第一个生效。
|
||||
- 日报邮件先保持 `RISK_DAILY_REPORT_MAIL_DRY_RUN=true`。
|
||||
- 正式发送前配置 SMTP,并将 `RISK_DAILY_REPORT_MAIL_ENABLED=true`。
|
||||
- 证据目录应挂载到持久化存储,不能只保存在临时容器目录。
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
公共底座、公共事务能力、公共数据范围、公共鉴权基座和公共 SSE 协商等问题不纳入本文,
|
||||
由主项目统一修复和发布。
|
||||
|
||||
## 本轮已完成
|
||||
## 已处理事项
|
||||
|
||||
### 1. 证据查询时间口径统一
|
||||
|
||||
@@ -53,6 +53,23 @@ Agent 不能把截断结果表述成覆盖全部数据,也不能据此给出
|
||||
`tools/grant_risk_permissions.py` 的文档字符串已改为实际文件名,
|
||||
避免执行人员按错误路径操作。
|
||||
|
||||
## 主项目仍需完成
|
||||
|
||||
### 6. 高风险预警邮件通知接入
|
||||
|
||||
- 主项目部署配置需要接入 `RISK_ALERT_MAIL_ENABLED`、`RISK_ALERT_MAIL_DRY_RUN` 和 `RISK_ALERT_MAIL_RECIPIENTS`。
|
||||
- 手动扫描和定时扫描必须继续共用同一套高风险邮件发送逻辑。
|
||||
- 高风险预警邮件当前只支持一个收件人,多个邮箱配置只有第一个生效。
|
||||
- 邮件发送成功写 `已发送`,失败写 `发送失败`;失败不得回滚预警和站内通知。
|
||||
- 日报邮件仍由用户在日报弹窗中填写多个收件人,和预警邮件配置相互独立。
|
||||
|
||||
### 7. 定时扫描接入主 Worker
|
||||
|
||||
- 当前 `python -m app.worker` 不包含风控定时扫描,独立调度进程只适合本地联调。
|
||||
- 主项目需要提供通用后台任务注册入口,或在部署编排中统一拉起风控调度进程。
|
||||
- 正式使用不能要求业务人员额外手工执行 `python -m app.worker.risk_scan_scheduler`。
|
||||
- 无论采用哪种方式,都必须保留扫描互斥锁和幂等去重。
|
||||
|
||||
## 联调前需要执行的动作
|
||||
|
||||
以下内容属于环境准备或数据初始化,不是代码缺陷:
|
||||
@@ -68,7 +85,7 @@ Agent 不能把截断结果表述成覆盖全部数据,也不能据此给出
|
||||
3. 执行 `python tools/publish_risk_agent_config.py`,确认奶龙风控智能助手的工具白名单和意图配置已发布。
|
||||
4. 按主项目发布的迁移流程执行 Alembic 升级,确认 `trigger_rule_codes` 多值索引已生效。
|
||||
5. 演示前准备足够的客户、交易、资金、持仓、登录和预警数据。
|
||||
6. 使用前确认日报邮件开关、SMTP 配置和收件人范围符合演示要求。
|
||||
6. 使用前确认高风险预警邮件开关、日报邮件开关、SMTP 配置和收件人范围符合演示要求。
|
||||
|
||||
## 当前保留限制
|
||||
|
||||
|
||||
Reference in New Issue
Block a user