feat: 增强下游重投与签名质量检测
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": "R10",
|
||||
"generatedAt": "2026-08-03",
|
||||
"source": "api/src/send-chain/send-chain.service.ts at R9 local baseline",
|
||||
"source": "api/src/send-chain/send-chain.service.ts at R9 local baseline; facade extended by 5 downstream requeue task methods on 2026-08-12",
|
||||
"facade": "api/src/send-chain/send-completion.service.ts",
|
||||
"methods": [
|
||||
{
|
||||
|
||||
@@ -1917,6 +1917,7 @@
|
||||
- 已按整条级成功形成`delivered`终态后,如果同一提交尝试又收到明确失败回执,平台保留原始回执和分片审计,但不得自动把已送达终态改成失败、重复退款或向客户推送互相矛盾的失败结果;系统按稳定异常键写入`SmsReceiptAnomaly`,重复矛盾回执累加发生次数。
|
||||
- 运营菜单“Gateway提交异常”更名为“网关异常”,原路由保持兼容。页面使用“提交异常”和“回执异常”两个Tab,均查询真实后端和PostgreSQL;每个Tab必须在标题区说明其数据来源、业务含义、不能代表的结论及人工处理注意事项,避免运营人员间隔较久后误判。
|
||||
- “提交异常”展示Gateway消费提交命令连续失败且没有明确供应商提交结果的死信,可在严格确认未被供应商接收后重新入队;“回执异常”展示供应商回执与平台既有终态冲突的结构化异常判定。回执异常详情必须指明真实回执保存在回执记录、原始CMPP报文在通讯交互日志,不得用异常摘要替代原始证据。
|
||||
- “提交异常”的待处理记录允许运营人员标记为“已处理”。操作只将异常状态原子更新为`resolved`并记录处理人、处理时间和操作日志,不删除异常证据、不重新入队、也不发送短信;已进入重新入队流程的记录不得并发标记。
|
||||
|
||||
## 运营端休眠唤醒与会话锁定恢复(2026-08-09)
|
||||
|
||||
@@ -2015,7 +2016,7 @@
|
||||
- 页面模块顺序固定为“签名通道发送质量”在最上方,其后依次为企业、通道热力图。两张热力图按维度行各自独立分页,每页10行;翻动其中一张不得改变另一张页码,30日日期列继续在各自表格内横向滚动。
|
||||
- 两张热力图的日期列从左到右按日期由大到小展示,即从`T-1`依次到`T-30`。行首主信息只展示签名名称;通道热力图保留识别维度所必需的通道名称和运营商标签,企业名称与企业应用名称不在行内常驻,鼠标悬停签名时再展示。每张热力图内部提供独立搜索框,可按企业名称、企业应用名称或签名名称筛选,并在筛选后回到第一页,不影响另一张热力图。
|
||||
- 热力图有真实检测快照的发送量格子悬停文案必须明确区分“提交条数”和“发送成功条数”,同时可补充上游接受条数、成功率和阈值;不得把上游接受或`SubmitResp status=0`写成发送成功。报备前仍显示“不适用”,没有检测快照仍显示当日无快照。
|
||||
- 页面最下方增加“未报备签名”模块,按所选北京时间自然日统计已提交到平台且有签名的真实`SmsMessageRecord`。当短信号码运营商没有匹配到该签名当前可用的运营商级报备成功事实,且也没有仍处于通过状态的历史通道级兼容报备事实时,计入未报备短信;运营商级事实可位于任一未删除通道,历史兼容事实仅用于避免把旧系统真实通过误报为未报备。结果按“签名 × 实际企业应用”聚合业务短信条数,展示签名、企业、企业应用,支持按三者搜索和每页10行独立分页;无签名的异常消息不在该模块伪造成签名。
|
||||
- 页面最下方增加“未报备签名”模块,按所选北京时间自然日统计真实`SmsMessageRecord`中“短信正文以规范`【签名】`开头,但该企业应用的有效签名库中没有同名记录”的业务短信。判定不再依赖通道或运营商报备任务:已有系统签名、仅缺少通道/运营商报备成功事实的短信不进入本模块;无法从正文开头提取规范签名的异常消息也不得伪造成签名。结果按“正文签名 × 实际企业应用”聚合号码级业务短信条数,展示签名、企业、企业应用,支持按三者搜索和每页10行独立分页。
|
||||
- 数据统计菜单改名为“签名质量检测”,并删除企业应用发送排行、通道占比、当天发送量和当天成功率模块。本项删除已确认,不作为后续可选项保留。
|
||||
|
||||
## 通道组按通道筛选(2026-08-09)
|
||||
@@ -2023,3 +2024,12 @@
|
||||
- 运营端“短信通道组管理”在通道组名称条件之外增加“通道”筛选。选定一个通道后,只展示成员配置中真实包含该`channelId`的未删除通道组;与通道组名称同时输入时按两个条件取交集。
|
||||
- 通道选项必须来自真实通道API,不使用静态列表、Mock或localStorage。页面首次加载时通道组与通道两个独立请求并行执行;选项同时展示通道名称和编码,已删除通道明确标记“已删除”。未加入任何通道组的真实通道仍可选择,选中后结果为零而不得隐藏该选项。
|
||||
- 通道选择控件必须为通用下拉可搜索控件,支持按通道名称或编码搜索;“全部通道”表示不按通道限制,点击“重置”必须同时清空通道组名称和通道条件并回到第一页。
|
||||
# 下游投递后台重投任务(2026-08-12)
|
||||
|
||||
1. 运营端“下游投递记录”必须同时保留单条重投、当前页勾选批量重投,并新增“按筛选条件重投”;分页支持每页 `10/25/50` 条,切换后回到第一页并重新查询真实后端。
|
||||
2. 后台任务使用当前企业、应用、投递类型、状态、创建日期和关键词的后端筛选快照,分页不属于任务范围;任务创建时固定 `snapshotAt`,之后产生的记录不得被卷入。
|
||||
3. 第一版只允许 `pending/failed/unconfirmed/rejected`,不支持批量重投客户端已确认的 `delivered`,`awaiting_ack` 不得并发重投。创建前必须真实预检命中、可重投、跳过和状态分布,原因必填。
|
||||
4. 任务按应用分批执行,默认每秒 10 条;单条失败不阻断整批,连续失败达到 10 条或 ACK 超时/拒绝达到安全阈值时自动暂停。客户离线、等待 ACK 属于等待状态,不得误记为跳过。
|
||||
5. 跳过只表示未调用 Gateway,第一版原因包括:状态已变化、已被客户确认、已被其他任务处理、本任务已成功处理、不属于任务快照、应用或投递能力已停用、投递数据不完整、缺少原 Submit 映射。
|
||||
6. 任务必须支持列表、详情、暂停、继续和终止;终止只影响尚未发送的记录。任务项以 `taskId + deliveryId` 幂等,执行前原子认领并复核状态,API 重启后可继续,成功 ACK 的项目不得再次发送。
|
||||
7. 所有创建、暂停、继续、终止和自动暂停均写操作日志;任务使用真实 PostgreSQL、Gateway 和客户 ACK,不得使用 mock、静态数据或 localStorage。
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
|
||||
热力图日期列按`T-1`至`T-30`由新到旧排列;行首只常驻签名以及通道维度必要的通道/运营商标识,企业和企业应用通过签名悬停提示查看。企业、通道模块分别在前端对后端返回的真实维度按企业、企业应用、签名过滤并独立分页。每行增加30日上游受理业务短信合计并按合计降序排列。格子悬停明确展示提交条数和最终发送成功条数,不混淆上游接受。报备后的完整观察窗口只控制清退预警资格,观察期仍按日生成`observing`快照并展示真实发送量,不创建预警周期、站内消息或Webhook。
|
||||
|
||||
页面底部增加独立的未报备签名查询。后端按所选北京时间自然日,以`SmsMessageRecord`为业务短信事实,按短信运营商检查该签名是否存在任一未删除通道上的当前运营商级`approved`任务;仍处于`approved`的历史通道级兼容任务视为已有真实旧报备,避免迁移期误报。其余按签名和消息实际企业应用聚合,后端完成关键字过滤、总数和分页,前端不使用静态数据或全量拉取伪分页。
|
||||
页面底部增加独立的未报备签名查询。后端按所选北京时间自然日,以`SmsMessageRecord`为业务短信事实,从正文开头提取规范`【签名】`;仅当消息没有关联签名且当前企业应用的有效签名库不存在同名记录时计入。该模块用于发现类似`【湘银物业】`的系统外签名,不再检查通道或运营商报备任务。结果按正文签名和消息实际企业应用聚合,后端完成关键字过滤、总数和分页,前端不使用静态数据或全量拉取伪分页。
|
||||
|
||||
### 第16步:完整验证与分阶段预生产发布
|
||||
|
||||
|
||||
@@ -3627,6 +3627,7 @@ npm run verify:phase8
|
||||
| --- | --- | --- |
|
||||
| TC-GW-SUBMIT-EXCEPTION-001 | 制造一条超过 Gateway 最大处理次数的真实 `SubmitCommand`,打开运营端“网关异常”的“提交异常”Tab,按状态、应用、通道和关键字筛选并查看详情。 | 记录写入 PostgreSQL,页面汇总、分页和详情来自 NestJS API;手机号脱敏,命令中的密码、密钥和原始 payload 不返回浏览器,页面不使用“死信”作为业务名称。 |
|
||||
| TC-GW-SUBMIT-EXCEPTION-002 | 对短信仍处于 pending/failed、通道 active 且 connected 的异常记录,输入 5~500 字原因,勾选“已确认上游未受理”并重新入队。 | 近期认证通过后服务端原子抢占记录、真实写入 Redis Stream;记录变为 requeued,人工次数、操作人、原因、Stream ID 和时间完整留痕,收到 SubmitResult 后变为 resolved。 |
|
||||
| TC-GW-SUBMIT-EXCEPTION-004 | 对一条`pending`提交异常点击“已处理”,在确认弹窗中取消后再次确认。 | 取消不调用接口;确认后仅将记录原子更新为`resolved/manually_resolved`,保留原异常和命令证据并写操作日志,不写Redis Stream、不触发短信提交;非`pending`记录不展示按钮且后端拒绝并发变更。 |
|
||||
| TC-GW-SUBMIT-EXCEPTION-003 | 不勾选确认、原因过短、重复点击同一记录,或分别把短信置为 accepted/submitted/delivered/unknown、把通道置为停用/断开、人工重试达到 3 次后尝试重新入队。 | API 拒绝危险或重复操作,不产生额外 Stream 命令;页面显示可读原因,操作日志不伪造成功。 |
|
||||
| TC-GW-RATE-001 | 给通道 A 配置 10 TPS,连续投递 20 条;通道 B 同时配置 20 TPS 并投递,另让提交命令携带高于通道配置的数值。 | Gateway A 实际提交节奏不超过 10 TPS,B 独立按自身额度执行;消息值不能放大 A 的权威上限,同一通道跨通道组共享额度。 |
|
||||
| TC-GW-RATE-002 | 超过通道 TPS 后观察 Redis Stream consumer group,并在存在等待消息时重启 Gateway。 | 超流速消息保留在 Stream pending,不直接失败;重启后通过 PEL/XAUTOCLAIM 恢复并继续按通道 TPS 排队提交,不丢失、不重复 ACK。 |
|
||||
@@ -4556,8 +4557,9 @@ npm run verify:phase8
|
||||
| TC-SIGNATURE-RETIREMENT-019 | 检查两张热力图日期、行首和悬停信息 | 日期从左到右为`T-1`至`T-30`;行首不常驻企业和企业应用,悬停签名可看到企业、企业应用;通道维度仍能识别通道和运营商 |
|
||||
| TC-SIGNATURE-RETIREMENT-020 | 分别在企业、通道热力图搜索企业、企业应用、签名并清空 | 每张热力图只过滤自身真实维度并回到第一页;三类关键字均可命中,清空恢复,另一张热力图的关键字和页码不变 |
|
||||
| TC-SIGNATURE-RETIREMENT-021 | 悬停报备前、无快照、零量和非零量格子 | 报备前显示不适用;无快照说明当日无检测;真实快照明确显示提交条数、上游接受条数、发送成功条数和成功率,发送成功等于真实最终送达而非受理成功 |
|
||||
| TC-SIGNATURE-RETIREMENT-022 | 所选日期构造有签名短信:运营商级已通过、历史通道级已通过、无通过任务、仅其他运营商通过、无签名 | 前两类不进入未报备模块;无通过任务和仅其他运营商通过按签名×实际应用计入;无签名记录不伪造成签名行;总条数与真实`SmsMessageRecord`一致 |
|
||||
| TC-SIGNATURE-RETIREMENT-022 | 所选日期构造正文以规范`【签名】`开头的短信:当前企业应用签名库存在同名记录、签名库不存在、仅其他企业应用存在同名记录、正文没有规范开头签名 | 只有当前企业应用签名库不存在的规范正文签名进入未报备模块;已有同名系统签名不受通道或运营商报备状态影响,其他应用同名签名不能替代当前应用记录,无规范签名正文不伪造成签名行 |
|
||||
| TC-SIGNATURE-RETIREMENT-023 | 在未报备签名模块按企业、企业应用、签名搜索并翻页 | 后端搜索、总数、每页10行和分页结果一致;列表展示签名、企业、实际企业应用和未报备短信条数,修改主统计日期后按新的北京时间自然日重新查询 |
|
||||
| TC-SIGNATURE-RETIREMENT-028 | 同一企业应用在所选北京时间自然日提交正文以`【湘银物业】`开头的短信,消息未关联`signatureId`且有效签名库无同名记录;另准备已有签名但缺少通道报备、其他应用同名签名、正文无规范开头签名三组对照数据 | 仅正文签名在当前企业应用签名库不存在的消息进入“未报备签名”,并按正文签名和实际企业应用聚合;已有系统签名但缺通道/运营商报备、其他应用的记录和无规范签名正文不得误判 |
|
||||
| TC-SIGNATURE-RETIREMENT-024 | 首次打开预警页面,随后选择历史日期区间 | 页签和区块标题均为“预警消息”;默认开始、结束均为今日且只返回今日消息,历史区间返回对应历史消息,每页10条并显示真实总数 |
|
||||
| TC-SIGNATURE-RETIREMENT-025 | 分别或组合选择企业、企业应用、签名关键字、通道及日期区间并翻页 | 后端同时应用全部条件,列表、总数和页码一致;条件变化查询后回到第1页,企业应用选项受企业筛选约束 |
|
||||
| TC-SIGNATURE-RETIREMENT-026 | 点击消息“抑制”,分别选择临时截止日期和永久抑制并填写原因 | 只出现平台自研弹窗;临时模式要求未来截止日期,永久模式不显示日期,两种模式原因必填,保存调用真实抑制接口且刷新当前筛选页 |
|
||||
@@ -4580,3 +4582,16 @@ npm run verify:phase8
|
||||
| TC-CHANNEL-GROUP-FILTER-003 | 选择某通道 | 只展示`items.channelId`包含该通道的通道组,不展示仅运营商相同但未配置该通道的组;总数和分页与筛选结果一致 |
|
||||
| TC-CHANNEL-GROUP-FILTER-004 | 同时输入通道组名称并选择通道 | 按名称包含与成员通道两个条件取交集,条件变更后回到第一页 |
|
||||
| TC-CHANNEL-GROUP-FILTER-005 | 点击“重置” | 通道组名称和通道条件同时清空,恢复全部未删除通道组并回到第一页 |
|
||||
# 下游投递后台重投任务专项用例(2026-08-12)
|
||||
|
||||
| 编号 | 场景 | 预期 |
|
||||
|---|---|---|
|
||||
| TC-DOWNSTREAM-REQUEUE-TASK-001 | 当前筛选条件预检 | 后端按企业、应用、类型、状态、日期、关键词和 `snapshotAt` 返回真实命中、可重投、跳过及状态分布;分页不影响数量。 |
|
||||
| TC-DOWNSTREAM-REQUEUE-TASK-002 | 创建任务 | 原因少于 5 字拒绝;仅物化 `pending/failed/unconfirmed/rejected`;`delivered/awaiting_ack` 不进入执行。 |
|
||||
| TC-DOWNSTREAM-REQUEUE-TASK-003 | 快照边界 | 创建任务后新增或筛选条件外记录不进入任务。 |
|
||||
| TC-DOWNSTREAM-REQUEUE-TASK-004 | 并发与幂等 | `taskId+deliveryId` 唯一;重复扫描、API 重启及并发任务不会重复调用 Gateway。 |
|
||||
| TC-DOWNSTREAM-REQUEUE-TASK-005 | ACK 闭环 | Gateway 写出后项目进入等待 ACK;`Result=0` 成功,拒绝/超时计失败并按阈值自动暂停。 |
|
||||
| TC-DOWNSTREAM-REQUEUE-TASK-006 | 状态变化跳过 | 执行前状态变化、已确认或被其他操作认领时不调用 Gateway,记录明确跳过原因。 |
|
||||
| TC-DOWNSTREAM-REQUEUE-TASK-007 | 任务控制 | 待执行/执行中任务可暂停、继续、终止;终止不撤回已写出消息。 |
|
||||
| TC-DOWNSTREAM-REQUEUE-TASK-008 | 审计 | 创建、暂停、继续、终止和自动暂停记录操作人、筛选快照、原因和结果。 |
|
||||
| TC-DOWNSTREAM-PAGE-SIZE-001 | 分页数量 | 可选 10/25/50;切换回第一页,后端返回对应条数,总数和筛选条件保持一致。 |
|
||||
|
||||
@@ -3448,6 +3448,13 @@ git diff --check
|
||||
- 真实PostgreSQL聚合返回“完全未报备”6条、“仅移动已报备但提交电信”4条;浏览器按企业B搜索后只显示后者4条。企业热力图按企业B搜索只保留3个相关维度,通道热力图仍保留全部7个维度;签名悬停属性显示真实企业和应用,格子悬停属性显示五项明确口径,日期首列为08-09、末列为07-11,控制台error/warn为0。
|
||||
- 清退专项7/7、API全量35个suite/446项通过,API与前端TypeScript、API正式构建、Vite 8.1.5生产构建通过(2538 modules,仅既有大chunk提示)。API全量用例本身12.573秒完成,但既有异步句柄使Jest不自行退出,本次使用`--forceExit`收尾并保留该提示;两次外层超时遗留的本轮Jest进程已按精确命令行确认后停止,未影响API、前端、PostgreSQL或Redis。
|
||||
|
||||
## 2026-08-12 未报备签名判定修正(未提交、未发布)
|
||||
|
||||
- 生产只读核查确认【彩生活物业】2026-08-12北京时间自然日有4个号码级`SmsMessageRecord`,4条均为2个计费分片;2026-08-11另有2个号码级消息。因此页面当日显示4条正确,用户所见6条为相邻两日累计,不修改签名质量统计代码,也不增加额外列表说明。
|
||||
- “未报备签名”按确认口径改为系统签名库缺失:从`signatureId IS NULL`消息正文开头提取规范`【签名】`,仅在同企业应用不存在未删除同名`SmsSignature`时计入;不再用通道、运营商或报备任务通过状态判定。结果仍按正文签名和实际企业应用聚合、搜索和分页。
|
||||
- 使用生产数据只读回放新聚合SQL,【湘银物业】在2026-08-12正确返回266条,企业为“王斯评与聆界中转企业”、应用为“王斯评平台To百信互动物业”;全过程未写生产数据库、未发送或重投短信。
|
||||
- 签名清退专项9/9、API与前端TypeScript、API正式构建、Vite 8.1.5生产构建及`git diff --check`通过;Vite仅保留既有约2.08MB单chunk提示。代码按要求未提交、未推送、未部署。
|
||||
|
||||
## 2026-08-10 预警消息检索分页、抑制弹窗与备注列宽(未提交、未发布)
|
||||
|
||||
- “今日预警”已调整为“预警消息”,后端按预警日期、企业、企业应用、签名和通道执行真实PostgreSQL筛选及分页;页面默认选中北京时间今日,仅查询今日,支持历史日期区间并固定每页10条。本地回放最近5个检测日后,今日共11条:浏览器验收第1页10条、第2页1条;选择近7天并按“跨通道”签名查询返回15条、2页,可见`2026/8/9 08:00:00`历史消息及真实企业应用名称。
|
||||
@@ -3500,3 +3507,15 @@ git diff --check
|
||||
- 新增统一`MoneyText`只读金额组件,运营端和客户端现有余额、授信、单价、消费、返还、充值、收入、成本、利润及短信计费等金额,小数点和小数部分使用统一次级文字色;输入框、CSV、复制文本和底层金额值不拆分、不改变。
|
||||
- 本地正式`SignatureRetirementService`在真实PostgreSQL执行2026-08-12检测,生成11条alert、2条healthy、6条observing快照;执行前后站内消息均55条、Webhook投递均0条,证明检测阶段不外发。浏览器真实API验收热力图首列为08-11、显示30日合计且合计491/134/65/0按降序,6个观察期格子可见;企业与应用字重为400;金额小数色为`rgb(107, 114, 128)`;客户端登录Canvas为2560×1440并正常绘制,页面控制台error/warn为0。
|
||||
- API全量35个suite/451项、签名清退与利润专项18/18项、前后端TypeScript、API正式构建、Vite 8.1.5生产构建、4份Gateway队列契约、Gateway `go test ./...`和`go vet ./...`通过;Vite仅保留既有约2.06MB单chunk提示,`git diff --check`仅有既有LF/CRLF提示。
|
||||
# 2026-08-12 下游投递后台重投任务与分页数量(已完成,待发布)
|
||||
|
||||
- 已确认第一版设计:按当前真实筛选条件和创建时快照建立后台任务,只允许 `pending/failed/unconfirmed/rejected`,不批量重投 `delivered`,等待连接/ACK 与真正跳过严格分开。
|
||||
- 已增加任务/任务项真实 PostgreSQL 模型、预检、创建、分批原子认领、ACK 闭环、暂停/继续/终止、操作审计,以及运营端任务列表和详情;下游投递列表同步增加每页 `10/25/50` 条选择。
|
||||
- 本地PostgreSQL已真实应用`20260812153000_add_downstream_requeue_tasks`,当前共86条migration;Prisma validate、专项4项、API全量36个suite/458项、API/前端TypeScript、API/Vite生产构建、4份Gateway队列契约、R10结构契约和`git diff --check`通过。R10稳定门面方法数同步为104。
|
||||
- 全量Jest的458项断言均通过;仓库仍有既有异步句柄导致不自行退出,使用`--forceExit`取得退出码0。新增后台任务扫描器已在相关启动定时器用例中显式关闭,复跑时不再产生缺少测试Prisma delegate的循环错误日志。
|
||||
|
||||
# 2026-08-12 网关提交异常人工标记已处理(已完成,待发布)
|
||||
|
||||
- “网关异常 / 提交异常”对`pending`记录增加“已处理”按钮和自研确认弹窗;确认后真实调用后端,将记录原子更新为`resolved`、写`resolvedAt`和`manually_resolved`,保留原始异常证据,不重新入队、不发送短信。
|
||||
- 后端记录操作人和`gateway.submit_dead_letter_resolved`审计日志;非`pending`状态拒绝并发标记,重复读取已处理记录保持幂等。
|
||||
- 功能纳入API全量36个suite/458项验证;前端TypeScript、API正式TypeScript构建、Vite生产构建和`git diff --check`通过,Vite仅有既有大chunk提示。
|
||||
|
||||
Reference in New Issue
Block a user