feat: strengthen risk controls and review workflows

This commit is contained in:
hectorzhao
2026-07-26 13:08:12 +08:00
parent b461532075
commit 2ce682c3fc
34 changed files with 2167 additions and 390 deletions
+36 -7
View File
@@ -1677,6 +1677,13 @@
1. 运营端“系统日志”必须将人员操作审计与协议通讯日志分成两个独立页签。通讯日志至少支持协议、交互方向、事件类型、结果、关键字和时间范围过滤,并展示平台消息号、上游消息号或HTTP请求号、脱敏对象、结果码、耗时和安全详情。
2. CMPP应覆盖客户登录/Submit、供应商SubmitResp、状态报告Deliver、上行Deliver及平台下游投递;HTTP应覆盖客户发送请求和平台回执/上行Webhook。数据库中一条记录必须对应一个真实业务报文,不得把同一报文的“入口收到”和“处理成功”拆成两条记录;处理结果、结果码和耗时写在该报文同一条记录中,失败、重试等后续真实交互另行记录。
3. Gateway收到状态报告或上行后,必须对解包/解码失败及转发NestJS失败输出结构化安全日志;NestJS入口把业务处理结果合并回同一报文记录,以便区分“上游未发”“Gateway未收到”“Gateway转发失败”和“API落库失败”。一条正常短短信的供应商侧完整成功闭环应依次展示四个真实报文:平台→通道 `CMPP_SUBMIT`、通道→平台 `CMPP_SUBMIT_RESP`、通道→平台 `CMPP_DELIVER`、平台→通道 `CMPP_DELIVER_RESP`;箭头只表达报文实际传输方向。
4. 通讯日志不得保存短信正文、密码、密钥、Token、签名鉴权值或完整HTTP请求体;手机号只保存脱敏值。CMPP心跳不得逐包写入数据库,连接健康仍使用连接状态和聚合指标。
5. 通讯日志写入不能阻塞短信主链路,默认批量异步写入,缓冲区应有上限和溢出告警;热数据默认保留30天,保留期允许通过环境变量配置。
6. 通讯日志方向固定使用“企业应用 → 平台、平台 → 供应商通道、供应商通道 → 平台、平台 → 企业应用”。供应商长短信每个真实 `SUBMIT``SUBMIT_RESP` 分片各记一条,企业应用每个真实 `SUBMIT_RESP` 也必须记录;内部 `submit-result` 聚合回调不是协议报文,不得重复生成通讯日志。
7. 供应商长短信回执必须先写入对应 `SmsMessageSegmentAudit`。仅当同一提交尝试的全部分片均为 `delivered` 时,主记录才转 `delivered` 并向企业应用投递一次最终回执;任一分片明确失败可进入最终失败/补发状态,分片尚未齐全时主记录保持 `submitted`,不得由首片成功提前聚合。
8. 长短信任一分片返回非成功终态时,系统必须通过该分片审计关联的提交记录识别当前发送尝试,不得仅以主记录保存的首片上游消息号判断;确认属于当前尝试后,整条短信立即进入失败/补发或退款终态,无需等待其余分片回执。
9. 回执和上行投递方式不得由运营人员选择。企业应用开通CMPP接口即按CMPP投递,开通HTTP接口且对应Webhook地址非空即按HTTP投递,两者同时满足时双投;任一地址为空时只跳过该类HTTP事件。运营端企业应用HTTP参数页必须始终可编辑回执和上行Webhook地址,不因HTTP接口开关关闭而隐藏。
10. Gateway向企业应用发送真实 `CMPP_DELIVER` 以及收到企业应用真实 `CMPP_DELIVER_RESP` 时,都必须各写一条通讯交互日志,分别使用“平台→企业应用”和“企业应用→平台”方向;下游投递记录继续承担排队、重试和ACK业务状态,不得以通讯日志替代。
## 2026-07-26 依赖安全治理补充
@@ -1685,10 +1692,32 @@
- PostCSS 必须固定到 `8.5.18` 或更高修复版本。平台不得接受用户 CSS 后交由构建链处理;如未来新增此能力,必须显式禁用不可信 previous source map 自动加载并重新开展威胁建模。
- ExcelJS 的旧版 `minimatch` 调用接口与安全修复版 `brace-expansion` 5.x 不兼容时,允许使用受测试的本地 CommonJS 兼容适配层;适配层只能转发到官方有长度上限的实现,必须同时验证旧版 minimatch 花括号匹配、Excel 读写和干净 `npm ci`
- Prisma CLI 只用于生成、迁移和构建,不属于 API 请求运行路径。其无上游修复版本的中危工具链公告需记录接受条件并持续跟踪,不得为审计数字清零而把 Prisma 7 数据访问栈盲目降级到 6.x。
4. 通讯日志不得保存短信正文、密码、密钥、Token、签名鉴权值或完整HTTP请求体;手机号只保存脱敏值。CMPP心跳不得逐包写入数据库,连接健康仍使用连接状态和聚合指标。
5. 通讯日志写入不能阻塞短信主链路,默认批量异步写入,缓冲区应有上限和溢出告警;热数据默认保留30天,保留期允许通过环境变量配置。
6. 通讯日志方向固定使用“企业应用 → 平台、平台 → 供应商通道、供应商通道 → 平台、平台 → 企业应用”。供应商长短信每个真实 `SUBMIT``SUBMIT_RESP` 分片各记一条,企业应用每个真实 `SUBMIT_RESP` 也必须记录;内部 `submit-result` 聚合回调不是协议报文,不得重复生成通讯日志。
7. 供应商长短信回执必须先写入对应 `SmsMessageSegmentAudit`。仅当同一提交尝试的全部分片均为 `delivered` 时,主记录才转 `delivered` 并向企业应用投递一次最终回执;任一分片明确失败可进入最终失败/补发状态,分片尚未齐全时主记录保持 `submitted`,不得由首片成功提前聚合
8. 长短信任一分片返回非成功终态时,系统必须通过该分片审计关联的提交记录识别当前发送尝试,不得仅以主记录保存的首片上游消息号判断;确认属于当前尝试后,整条短信立即进入失败/补发或退款终态,无需等待其余分片回执
9. 回执和上行投递方式不得由运营人员选择。企业应用开通CMPP接口即按CMPP投递,开通HTTP接口且对应Webhook地址非空即按HTTP投递,两者同时满足时双投;任一地址为空时只跳过该类HTTP事件。运营端企业应用HTTP参数页必须始终可编辑回执和上行Webhook地址,不因HTTP接口开关关闭而隐藏
10. Gateway向企业应用发送真实 `CMPP_DELIVER` 以及收到企业应用真实 `CMPP_DELIVER_RESP` 时,都必须各写一条通讯交互日志,分别使用“平台→企业应用”和“企业应用→平台”方向;下游投递记录继续承担排队、重试和ACK业务状态,不得以通讯日志替代
## 2026-07-26 用户登录标识复用、组合查询与管理员保护提示
1. 用户逻辑删除后,原用户记录、用户主键及历史审计关联必须继续保留;用户名、邮箱和手机号仅在未删除用户范围内唯一。新建用户可以复用逻辑删除记录曾使用的登录标识,但必须生成新的用户主键,不得继承旧用户的角色、企业归属、密码、会话或权限
2. 用户登录和按用户名查找必须显式排除逻辑删除记录。活动用户之间的登录标识并发冲突继续由PostgreSQL唯一索引保证,并返回HTTP 409、冲突字段及明确中文提示
3. 运营端用户管理将用户姓名、登录账号、所属企业、用户角色和状态拆分为独立条件;客户端将用户姓名、登录账号和状态拆分。点击查询或重置时调用真实后端组合查询,条件之间使用AND,登录账号内部对用户名、邮箱和手机号使用OR;不得加载全量数据后仅在浏览器过滤
4. 删除、禁用或降权最后一个平台管理员/企业管理员时,后端实时拦截继续作为权威判断。前端必须在当前确认弹窗内以`role=alert`显示失败原因和处理建议,保持弹窗打开,禁止只向浏览器控制台输出未处理Promise;请求期间确认按钮必须禁用
## 2026-07-26 企业应用停用与回执清算补充要求
- 删除企业前必须检查其企业应用;只要存在`active``disabling`应用就阻止删除,并提示先完成应用停用。
- 点击停用应用时,系统必须统计尚未收到供应商回执的短信、待发送回执、等待`CMPP_DELIVER_RESP`的回执、仍可重试的失败投递及待投递上行。
- 无待清算数据时,应用直接转为`disabled`并断开该账号的全部下游CMPP连接;存在待清算数据时,运营可选择“等待回执后停用”或“强制停用并断开连接”。
- “等待回执后停用”将应用转为`disabling`:立即拒绝新短信Submit,但保留或允许下游账号重新连接以接收历史回执;待清算数据归零后自动停用。
- `disabling`状态必须展示进入原因、各类待清算数量、当前连接数及自动停用时间;运营点击启用可清除停用计时并恢复为`active`
- “停用中”最长保留72小时,从`disablingAt`起算。到期仍未清算时自动转为`disabled`,剩余下游投递标记`abandoned`并停止重试,然后断开全部下游连接。
- 应用停用后才到达的供应商回执仍更新短信主记录并保存原始证据,但下游投递记录直接标记`abandoned`,不得继续推送或形成重试告警。
- Gateway读取已形成的待投递回执不能依赖企业或应用当前是否启用,避免“已生成回执但账户停用导致永远无法读取”的投递死锁。
## 2026-07-26 风控规则、逐号码拦截与短信人工审核补充要求
1. 风控规则只保留全局默认和企业应用级覆盖两层;应用级同编码规则优先于全局规则。企业级覆盖不再存在,企业应用表单和数据模型中的`maxPhonesPerTask`删除,单任务号码上限完全由`MAX_PHONES_PER_TASK`规则控制。本条取代2026-07-23“应用每任务最大号码数”旧要求,测试环境既有应用值无需迁移。
2. 可配置规则仅包括单任务最大号码数、非工作时间大批量营销发送和10分钟客户端任务创建频控。重复号码比例、非法号码比例、黑名单命中比例、模板变量异常不再作为可配置风控规则;历史规则与命中记录保留审计但不再生效或展示。
3. 10分钟任务频控只按同一企业应用、`SmsBatchTask.sourceType=client`统计真实客户端任务;CMPP、公开HTTP、运营通道测试和风控预检不得计入。配置上限N时,第N+1个客户端任务进入规则指定动作。
4. 非工作时间规则支持`HH:mm`开始、结束时间并允许跨日,时区固定使用`Asia/Shanghai`;全局和企业应用级覆盖均可分别配置。
5. 手机号码基础合法性只判断“1开头、总计11位、全部为数字”,不得依赖可能滞后的手机号段表。非法号码为确定性拦截,不进入人工审核;客户端/HTTP短信记录标记`submit_failed + submitStatus=rejected + INVALID_PHONE`,CMPP已受理的多号码提交对非法目的号码生成平台失败回执,其他合法号码继续处理。
6. 黑名单按单号码确定性拦截,不再按命中比例拒绝整批。命中平台或企业应用黑名单的客户端/HTTP记录标记提交失败、金额为0且不提交通道;CMPP已受理记录生成`REJECTD`失败回执。混合批次中的非黑名单号码继续发送。
7. 模板变量异常指本次发送缺少模板必填变量或传入模板未定义变量。该校验保留为不可配置的确定性拒绝,返回明确的缺失/多传变量原因,不进入人工审核;模板创建时的人工审核不能替代每次发送的变量完整性校验。
8. 短信审核页面只展示待人工审核和人工审核记录;自动放行和自动拒绝不得混入“人工通过/人工驳回”。号码数量可点击查看真实号码明细,字段仅为手机号码、号码归属地、运营商和短信记录状态,并提供服务端搜索与分页。
9. 创建待审核批次时,每条待审`SmsMessageRecord.reviewTaskId`必须同步保存。人工通过或驳回应同时兼容短信直连审核任务和`SmsBatchTask.riskTaskId`关联路径,保证审核任务、批次、短信状态及入队/拒绝动作一致;本次不修复或补发升级前历史异常数据。