feat: refine operations UI and transport limits

This commit is contained in:
hectorzhao
2026-08-13 10:42:59 +08:00
parent fb02cbcf39
commit 67fee21616
34 changed files with 314 additions and 188 deletions
@@ -65,15 +65,15 @@
},
{
"name": "SignatureReportModal",
"canonicalSha256": "7439104e171e7d9eeb8449f497696b6d3736b881195c0b96a1a096079ba0789b"
"canonicalSha256": "4cfec954f564c998af70da441971bede16915f4bb5ac9c10e45da15101957de5"
},
{
"name": "ChannelReportStatusModal",
"canonicalSha256": "d32f8d7d3025ee286ed7898ed41a22404db3d684b80d23819965b3332e0e8310"
"canonicalSha256": "e0717a89302e477fd1e57f18e3f97b993ebe3c7c42ccbfcd2761110054f6abcb"
},
{
"name": "DrainageReportModal",
"canonicalSha256": "716a2d480a4b652ee951de0306854f1d8f6d72759d7b2fbffbfbb600abc8a789"
"canonicalSha256": "d2b41c26eb3992bb1ff3b50ee5ef6c06e7f84d89832e3ec7446b35178520431f"
},
{
"name": "DrainageReportStatusModal",
@@ -84,7 +84,7 @@
"canonicalSha256": "2f71bdc2f8044ca9b403affbb0cb3f31587e4c004a90e9e0836aa6143033b6da"
}
],
"tableJsxSha256": "203ec16e0ca67f0dafea08d659e84db02dd8346d06a52f41378625e39a43def7",
"tableJsxSha256": "5cae4926ab10a762b26d77d0a0633b85de68fa204b7d5732ba0942e7fc276234",
"apiCalls": [
"listEnterpriseSignaturesPage",
"listTenants",
@@ -2034,3 +2034,17 @@
5. 跳过只表示未调用 Gateway,第一版原因包括:状态已变化、已被客户确认、已被其他任务处理、本任务已成功处理、不属于任务快照、应用或投递能力已停用、投递数据不完整、缺少原 Submit 映射。
6. 任务必须支持列表、详情、暂停、继续和终止;终止只影响尚未发送的记录。任务项以 `taskId + deliveryId` 幂等,执行前原子认领并复核状态,API 重启后可继续,成功 ACK 的项目不得再次发送。
7. 所有创建、暂停、继续、终止和自动暂停均写操作日志;任务使用真实 PostgreSQL、Gateway 和客户 ACK,不得使用 mock、静态数据或 localStorage。
# 2026-08-13 HTTP 请求与 Gateway API 响应容量边界
1. Go Gateway 调用 NestJS API 时必须完整读取最多 `4 MiB` 的响应体;超过边界必须返回包含实际容量边界的明确传输错误,禁止静默截断后以 `unexpected end of JSON input` 等语法错误掩盖容量问题。该边界覆盖待投递回执恢复批次等内部响应,不改变单次恢复查询的业务分页口径。
2. NestJS 普通 JSON 与 URL-encoded 请求体统一限制为 `2 MiB`。客户号码文件导入预览和确认接口因现阶段仍在 JSON 中携带 CSV/TSV 正文,单独限制为 `25 MiB`;业务层继续限制原始导入正文不超过 `20 MiB`,为 JSON 字段、转义字符和其他参数保留协议开销。
3. 大容量解析器只能挂载到 `/api/client/send/imports/*`,不得把所有管理、客户和公网 HTTP API 全局放宽到 25 MiB。`rawBody` 必须在两类解析器中继续保留,确保公网 HTTP API 的验签与幂等正文哈希语义不变。
4. 客户导入接口经 `sms.lisglo.com` 私有 API 访问,该入口的 Nginx 请求体上限必须不低于 `30 MiB`,当前标准配置 `50 MiB` 满足要求。`api.lisglo.com` 只开放单条客户 HTTP API、Swagger 和健康检查,不承载文件导入,不得为导入需求扩大其暴露路由。
5. 容量边界必须由自动化测试覆盖:大于旧 `64 KiB` 且小于 `4 MiB` 的合法 Gateway 响应完整解析;超过 `4 MiB` 明确拒绝;同一份大于 `2 MiB` 的 JSON 仅在导入路由可被解析,普通路由返回 HTTP 413。
# 2026-08-13 运营端信息密度与运营商标签统一
1. 运营端充值记录回执必须展示该笔人工充值的操作人员姓名。姓名由充值单已保存的`operatorId`关联真实用户记录取得,优先展示姓名、姓名缺失时回退用户名;历史无操作人的系统记录展示“系统”,不得用前端静态映射伪造。
2. 运营看板删除“今日签名发送统计”和“今日签名发送统计 - 含引流”两个明细模块;“今日活跃签名”指标仍使用当天真实发送聚合。今日消费金额的主数字必须与今日发送总量使用相同字号、字重和深色层级。
3. 企业应用管理列表的状态、到达率、单价列在现有基础上缩窄约20%,提升大屏一次展示完整表格的概率;不得通过隐藏真实字段实现。
4. 移动、联通、电信数据展示统一使用全局`CarrierTag`低饱和标签,包括通道与通道组、监控、报备、签名、短信审核、任务号码、发送记录及客户端发送详情等页面。筛选/表单控件的选项文案、图表图例、导出文本和业务说明仍使用纯文本,避免破坏交互、可访问性和机器可读输出;可取得运营商集合的三网通道按三个运营商标签展示,只有历史通道级字段时使用中性的“三网”标签。
+2
View File
@@ -70,6 +70,8 @@ PROD_ADMIN_PASSWORD='change-me'
`API_ENABLE_SEND_WORKER=true` 是生产发送链路必填项。后续发布脚本会在构建和迁移前校验该开关以及正整数 `API_SEND_WORKER_CONCURRENCY`;缺失时直接终止发布,防止 API/Gateway 健康但 BullMQ 短信队列无人消费。
HTTP容量边界固定为:NestJS普通JSON/URL-encoded请求体`2 MiB`,仅`/api/client/send/imports/*`使用`25 MiB` JSON解析上限,原始CSV/TSV正文继续由业务层限制为`20 MiB`Gateway读取NestJS API响应最多`4 MiB`且超限必须明确报错。客户文件导入走`sms.lisglo.com`私有API,因此该虚拟主机的`client_max_body_size`必须不低于`30m`,标准bootstrap配置为`50m``api.lisglo.com`只承载单条公网HTTP API、Swagger和健康检查,不承载客户文件导入;不要为导入需求开放私有路由或把NestJS所有JSON接口统一放宽到25MiB。发布前使用`nginx -T`确认最终生效值,不能只检查仓库模板。
Gateway 的最终 TPS 防线依赖与 API 相同的 Redis。通道连接时会写入 `rate:gateway:channel:config:<channelId>` 权威上限,实际预约使用 `rate:gateway:channel:<channelId>`;这些 key 不应在正常发布时清理。多 Gateway 实例必须指向同一 Redis,才能共享单通道额度。超速的 `gateway.submit.commands` 消息会保持在 consumer group pending 中等待,不应通过手工 `XACK` 或删除 Stream 处理积压;先检查通道配置、Redis key、consumer group 和 Gateway 日志。
服务重启顺序必须是 Gateway 在前、API 在后。API 启动后等待 `GATEWAY_STARTUP_RECONNECT_DELAY_MS`(默认 1 秒),从 PostgreSQL 读取全部 active 通道并重新下发真实连接命令,同时恢复 Gateway 内存连接池和 Redis 权威 TPS key;禁止沿用数据库中重启前的 connected 状态冒充当前连接。
+18
View File
@@ -4596,3 +4596,21 @@ npm run verify:phase8
| TC-DOWNSTREAM-REQUEUE-TASK-007 | 任务控制 | 待执行/执行中任务可暂停、继续、终止;终止不撤回已写出消息。 |
| TC-DOWNSTREAM-REQUEUE-TASK-008 | 审计 | 创建、暂停、继续、终止和自动暂停记录操作人、筛选快照、原因和结果。 |
| TC-DOWNSTREAM-PAGE-SIZE-001 | 分页数量 | 可选 10/25/50;切换回第一页,后端返回对应条数,总数和筛选条件保持一致。 |
# 2026-08-13 HTTP 与 Gateway 报文容量专项用例
| 用例编号 | 优先级 | 验证内容 | 预期结果 |
| --- | --- | --- | --- |
| TC-TRANSPORT-SIZE-001 | P0 | 模拟 NestJS 返回约128KiB的合法待投递回执JSON,由Gateway通用API传输方法读取并反序列化 | 响应完整解析,字段长度与服务端输出一致,不出现64KiB截断或JSON语法错误 |
| TC-TRANSPORT-SIZE-002 | P0 | 模拟NestJS返回超过4MiB的响应 | Gateway停止读取并返回`api response exceeds 4194304-byte limit`容量错误,不返回`unexpected end of JSON input`,不把不完整数据当作成功结果 |
| TC-HTTP-BODY-001 | P0 | 分别向普通JSON接口和`/api/client/send/imports/preview`提交约3MiB合法JSON | 普通接口在Controller前返回413;导入接口成功解析且保留rawBody,证明25MiB解析器只对导入路由生效 |
| TC-HTTP-BODY-002 | P1 | 分别测试普通JSON 2MiB边界、导入JSON 25MiB边界及业务层原始正文20MiB边界 | 边界内请求正常进入业务校验;超过解析器边界返回413;超过20MiB原始导入正文返回明确业务错误且不创建发送任务 |
| TC-NGINX-BODY-001 | P1 | 检查预生产有效Nginx配置及域名路由 | `sms.lisglo.com`请求体上限不低于30MiB并承载私有导入接口;`api.lisglo.com`不暴露私有导入路由且其现有上限不影响单条公网HTTP API |
# 2026-08-13 运营端信息密度与运营商标签统一专项用例
| 编号 | 场景 | 步骤 | 预期结果 |
| --- | --- | --- | --- |
| TC-BILLING-RECEIPT-OPERATOR-001 | 人工充值回执展示操作人员姓名 | 使用有`operatorId`的真实人工充值记录查询充值列表并打开回执 | API按用户表返回`operatorName`,回执显示姓名而非用户ID;无操作人的历史记录显示“系统”,关联用户确已不存在时显示“未知操作人员” |
| TC-DASHBOARD-SIGNATURE-REMOVE-001 | 删除看板签名统计模块并统一金额样式 | 打开运营看板,检查指标卡与后续模块 | 两个“今日签名发送统计”模块均不存在;今日消费金额与今日发送总量主数字字号、字重和颜色一致;今日活跃签名仍来自真实接口 |
| TC-ENTERPRISE-APP-WIDTH-001 | 企业应用关键列缩窄 | 在桌面大屏打开企业应用管理并读取表头列宽 | 状态、到达率、单价列宽均约为原宽度80%,字段与操作均未隐藏,横向滚动需求减少 |
| TC-UI-CARRIER-TAG-002 | 全局运营商数据展示复用通用标签 | 抽查通道/通道组、监控、报备、企业签名、短信审核、批次号码、发送记录和客户端发送详情 | 移动、联通、电信均使用全局低饱和胶囊及统一色值;有运营商集合的三网通道显示三个标签,历史通道级字段显示中性“三网”;筛选选项、图表图例与导出文本保持纯文本 |
+16
View File
@@ -3541,3 +3541,19 @@ git diff --check
- 最小修复为将原始企业、应用字段加入`GROUP BY`,保持“正文签名 × 实际企业应用”业务口径、搜索、计数和分页不变;同步新增`TC-SIGNATURE-RETIREMENT-029`,防止测试桩只验证返回映射而遗漏真实PostgreSQL语法约束。
- 签名清退专项9/9、API TypeScript正式构建和`git diff --check`通过。热修复提交`4c70978da4e3bd22ea159313c95b36ca18d150d6`已推送,并采用API最小热发布:备份位于`/opt/cmpp-platform-backups/releases/20260812-175436-before-hotfix-4c70978d`,只替换本次API源码/编译产物并重启`cmpp-api`,未重启Gateway、Nginx或短信通道。
- 发布后运行标识已核对为`4c70978d`,API和Gateway健康通过。使用生产真实PostgreSQL执行与接口相同的完整聚合SQL成功返回1组、266条短信,未再出现`42803`;热发布后的API日志没有新增`ExceptionsHandler`或Prisma聚合异常。现有浏览器没有可接管的登录页,因此未伪造账号会话;页面可由用户直接刷新验收。
# 2026-08-13 Gateway响应截断与NestJS请求体容量修复(本地未提交、未发布)
- 只读复核确认Gateway通用API传输方法使用`io.LimitReader(resp.Body, 64*1024)`静默截断响应;待投递回执恢复查询单批100条时,生产真实JSON已可超过该边界并形成`unexpected end of JSON input`。本轮将完整响应上限调整为4MiB,并额外读取1字节识别超限:超过边界返回明确容量错误,不再把传输截断伪装成JSON语法错误。
- NestJS关闭框架自动注册的默认100KiB body parser,显式注册普通JSON/URL-encoded 2MiB解析器;仅`/api/client/send/imports/*`先注册25MiB JSON解析器。两类JSON解析器继续保存`rawBody`,公网HTTP API验签和幂等正文哈希语义不变;导入业务层原始正文20MiB限制保持不变。
- 域名链路重新核对:客户导入使用`sms.lisglo.com`私有API,其标准Nginx上限50MiB已覆盖25MiB解析需求;`api.lisglo.com`只开放单条HTTP API、客户Swagger和健康检查,不承载文件导入,因此本轮不错误扩大API专用域名或开放私有路由。
- 新增专项自动化:Gateway可完整解析约128KiB合法响应,超过4MiB返回`api response exceeds 4194304-byte limit`且不出现截断JSON错误;同一份约3MiB JSON在导入路由返回200、保留完整rawBody,普通路由返回413。API容量专项2/2、API全量37套/460项、API TypeScript正式构建、Gateway inbound专项、Gateway全量`go test ./... -count=1``go vet ./...`、4份Gateway队列契约和`git diff --check`均通过。
- 19份既有结构门禁中10份通过、9份失败;失败均来自当前`HEAD`在本轮开始前已经存在的契约漂移(下游重投/异常处置API、通道排序、签名弹窗、签名质量查询、报备导出、运营商集合、定时调度、长文本样式和签名查询),与本轮新增/修改文件无交集。本轮不为通过门禁而顺手刷新或改写其他会话业务契约,保留为既有基线问题单独治理。
- 本轮没有发送、补发或重投短信,没有修改通道账号、密码、启停状态、企业余额、客户连接或生产数据;代码保持未提交、未推送、未部署。受保护的`api/tsconfig.build.tsbuildinfo``tsconfig.tsbuildinfo``outputs/`和空文件`=`不删除、不提交、不归因。
# 2026-08-13 充值回执操作人员、看板精简与运营商标签统一(待提交、未发布)
- 充值记录列表接口使用充值单既有`operatorId`批量查询真实用户,返回`displayName`(缺失时回退`username`)作为`operatorName`;充值回执新增“操作人员”,历史无操作人的系统记录展示“系统”。未新增字段或migration,避免复制姓名造成历史数据与用户资料不一致。
- 运营看板删除“今日签名发送统计”和“今日签名发送统计 - 含引流”两个模块及其分页状态;今日活跃签名继续使用真实发送质量接口聚合。指标文案调整为“今日消费金额”,主数字直接复用与今日发送总量相同的`metric-card strong`样式。
- 企业应用管理的状态、到达率、单价列宽均从130px缩至104px,字段和操作未隐藏。全局审计运营商数据展示后,监控、通道/通道组、应用路由、签名和报备、清退、短信审核、批次号码、发送记录及客户端发送详情统一复用`CarrierTag`;筛选选项、图表图例、导出和说明文字保留纯文本,三网通道展开为三个标签。
- API全量37套/460项、充值和HTTP容量专项14/14、前后端TypeScript、Vite 8.1.5生产构建、Gateway全量测试与`go vet`、4份Gateway队列契约、企业应用R11、短信记录R11、企业签名R4结构契约和`git diff --check`均通过;Vite仅保留既有约2.07MiB单chunk提示。企业签名R4哈希只按本次经验证的运营商标签JSX同步更新,未放宽模块边界。浏览器连接本地页面时既有登录会话已失效,未输入账号密码或验证码,因此页面级视觉验收未完成。
- 本轮与此前未提交的HTTP/Gateway容量修复一并进入待提交范围,未发送、补发或重投短信,未修改通道配置、余额、客户连接或生产数据;受保护缓存、`outputs/`和空文件`=`不删除、不提交、不归因。