14 KiB
CMPP 平台代码质量复评报告 V3
- 报告日期:2026-08-28
- 复评时间:2026-08-28 15:36~16:08(Asia/Shanghai)
- 复评基线:
3834d67a308acf89d0e6cb2e6009c89c93b2c139 - 主要业务整改提交:
ad27acad7e02b787185c972c710c73c867429c36 - 锁文件修正提交:
226527f1cef122e4dbd163da782485e8c0254dc5 - 对比基线:V2 基线
3af145abe5eb8cae567bb18e29116b4940889258 - Git 状态:本地
main比origin/main超前 3 个提交;当前提交尚未推送 - 工作区保护:保留既有
docs/code-quality-reassessment-20260828-v2.md修改、未跟踪=和pnpm-lock.yaml - 明确未执行:提交、推送、部署、服务重启、数据库业务写入、短信发送、压力测试、预生产或生产操作
1. 执行摘要
本轮综合判定为:代码质量有条件通过,持续治理尚未闭环;不建议仅凭本报告进入预生产发布。
与 V2 相比,本轮取得了明确进步:
- 客户端凭据、Webhook、日志导出、文件上传、用户维护等写接口补充 class DTO、严格运行时校验和负向测试。
- 浏览器客户端请求不再发送或回退租户 ID,服务端可信租户边界进一步收紧。
- 登录保护从账号维度扩展为账号、来源 IP、账号+IP 和验证码请求频率,并使用 Redis 原子计数和摘要键。
- 建立 Vitest/Testing Library/jsdom/MSW 前端测试基座,4 个测试文件、34 项测试通过。
- API 增至 51 个测试套件、563 项测试并全部通过。
- 根依赖审计保持 0;API 审计从 V2 的 7 项降至 5 项,剩余项均位于 Prisma CLI 开发/迁移链。
- npm 10.9.4、两份正式
package-lock.json、ESLint flat config 和 Prettier 配置已建立。 - 测试环境已部署
226527f...;本次独立读取到的远端前端资源与本地构建资源一致,外部 API health 最终连续 5 次返回 200。
但本次独立复测发现两项不能忽略的问题:
- 增量 lint/format 门禁存在假绿。 默认比较
HEAD时,提交后的整改文件不会进入检查;显式设置基线后,Windows 包装器又无错误信息地退出 1。绕过包装器直接检查 37 个整改代码文件,发现 6 个 ESLint error、2 个 warning,以及 2 个文件未通过 Prettier。 - 客户端删除接口仍缺严格 DTO。
ClientDeletionGovernanceController使用 TypeScript typeDeleteTargetDto,没有strictValidationPipe,额外字段、格式和长度仍不会按本轮统一规则拒绝。
综合参考分:86/100,较 V2 的 82/100 提升 4 分。P0 为 0,但仍有 2 项 P1 和若干 P2/验收边界。
2. 质量评级
| 维度 | V2 | V3 | 结论 |
|---|---|---|---|
| 业务正确性与并发设计 | B+ | B+ | API/Gateway 全量回归通过;未重跑真实 CMPP 全链。 |
| 安全性 | B+ | A- | 客户端租户边界、DTO 和登录保护明显增强;删除接口仍有校验缺口。 |
| 自动化测试 | B- | B+ | 前端 34 项、API 563 项通过;API “全源”指标仍未成为标准脚本默认口径。 |
| 前端性能 | B+ | B+ | 路由分包保持,入口 107.28 KiB gzip,图表异步包 181.65 KiB gzip。 |
| 可维护性 | C+ | C+ | 引入 ESLint/Prettier,但门禁未真实通过;两个 SendChain Service 未拆分。 |
| 数据库工程 | B+ | B+ | Prisma schema 和 95 项迁移发布记录正常;本轮未独立执行真实数据查询计划。 |
| 依赖与仓库卫生 | B- | B | 根审计 0,API 风险降至 Prisma CLI 5 项;正式包管理器已固定,旧未跟踪 pnpm 锁仍在。 |
| 运行与发布就绪 | B- | B | 测试环境公开入口及资源匹配;内部服务/队列状态仅有发布记录,本次 SSH 未独立复核。 |
3. V2 遗留项复核
| V2 项目 | V3 状态 | 复评结论 |
|---|---|---|
| 客户端写接口严格校验不完整 | 大部分关闭,仍有缺口 | 凭据、Webhook、导出、文件、用户等已补齐;客户端删除接口遗漏。 |
| 前端自动化测试为 0 | 已关闭 | 4 个文件、34 项通过;覆盖登录、请求错误、租户头、路由异常和用户列表关键状态。 |
| API 依赖公告 2 moderate/5 high | 部分关闭 | 当前为 2 moderate/3 high,共 5 项;均聚合在 Prisma CLI 链并有风险矩阵。 |
| 无真实 ESLint/Prettier | 实现未验收通过 | 配置与脚本已增加,但增量包装器有缺陷,整改代码本身仍有 lint/format 失败。 |
| SendChain 超大服务 | 未处理,按方案延期 | 文件仍约 86,253 和 53,421 字节;需要独立行为锁定与重构任务。 |
| 双锁文件口径 | 部分关闭 | packageManager 固定 npm 10.9.4,正式仅跟踪两份 npm lock;旧未跟踪 pnpm lock 仍受保护保留。 |
| 测试环境与登录后验收 | 部分关闭 | 测试环境已部署并健康;登录后深层页面和真实 CMPP 全链仍未复验。 |
4. 本轮独立验证结果
4.1 构建与自动化测试
| 检查项 | 结果 |
|---|---|
| 前端 TypeScript | 通过 |
| Vite production build | 通过 |
| Bundle budget | 通过;入口 107.28 KiB gzip,Chart 181.65 KiB gzip |
| 前端 Vitest | 4/4 文件、34/34 项通过 |
| 前端纳入覆盖范围的核心模块 | statements 88.34%、branches 84.71%、functions 84.00%、lines 88.02% |
| API TypeScript build | 通过 |
| Prisma validate | 通过;仓库 95 项 migration |
| API Jest | 51/51 套、563/563 项通过 |
| API 默认 coverage 脚本口径 | 70.44% / 53.77% / 71.76% / 73.61% |
| API 显式全源口径 | 60.46% / 51.54% / 60.75% / 63.04% |
| API 增量覆盖配置 | 86.92% / 77.03% / 95.91% / 90.07% |
Gateway go test ./... -count=1 |
通过 |
Gateway go vet ./... |
通过 |
| Gateway 队列契约 | 5/5 通过 |
| 结构质量/依赖缓解/安全部署门禁 | 通过 |
npm ci --dry-run --include=dev |
根项目与 API 均通过 |
覆盖率顺序均为 statements / branches / functions / lines。
首次并发执行前端测试时,4 个 Vitest worker 因本机同时运行多个高负载任务而启动超时,未执行测试;资源释放后以单 worker 串行重跑全部通过。首次从仓库根目录直接启动 API Jest 时误扫描受保护的 outputs/ 历史快照;改为在 api/ 目录按项目配置运行后全部通过。两次错误执行均未计为产品失败。
4.2 覆盖率口径校正
api/jest.config.cjs 仍未配置 collectCoverageFrom,因此标准 test:coverage 的 70.44% 只统计测试实际加载的源码,不能称为严格“全源覆盖率”。本报告显式加入 src/**/*.ts 后的全源结果为 60.46% / 51.54% / 60.75% / 63.04%,较 V2 的 59.84% / 51.29% / 60.15% / 62.60% 小幅提升,并继续满足 59% / 50% / 60% / 62% 门槛。
增量配置确实对指定新增模块建立了 80% / 70% / 80% / 80% 门槛,但运行时仍执行全部 51 套测试;覆盖率只收集列出的 7 个文件。该机制有效,但文档应准确称为“指定整改模块覆盖率”,不应与全源口径混用。
4.3 依赖审计
使用项目固定的 npm 10.9.4 直接审计正式锁文件:
- 根项目:0 项公告。
- API:5 项公告,2 moderate、3 high。
- 5 项均为
prisma -> @prisma/config/@prisma/dev -> deepmerge-ts/valibot聚合路径,不进入 NestJS HTTP 请求运行时。 - 自动修复建议是 Prisma 7.9.0 降级到 6.12.0,属于破坏性主版本变更,本轮不执行
audit fix --force的决定合理。 api/package-lock.json已实际解析 UUID 11.1.1、find-my-way 9.7.0;Swagger、js-yaml、fast-uri、brace-expansion 的既有公告已关闭。
判定:供应链风险已从“未治理”转为“有记录的开发工具链风险接受”,但仍需监控 Prisma 上游修复。
4.4 测试环境只读探测
curl --noproxy '*'绕过系统代理后,第一组/api/health3 次均为 HTTP 200。- 同组客户端登录页、运营登录页和验证码接口均返回 200;运营登录页有一次总耗时约 9 秒。
- 随后一次 health 请求发生 10 秒连接超时;立即复测 5 次均返回 200,总耗时约 17~19 ms。
- 远端登录 HTML 引用
index-BvZGIM6l.js和index-DyAqoJbu.css,与本地 V3 构建产物一致。 - SSH 当前仍认证失败,无法独立读取
.deployed-commit、systemd、Redis Stream、migration 和服务器日志。 - 发布记录显示测试环境部署标记为
226527f...,95 项迁移一致、11 项服务 active、三条 Streampending=0/lag=0、发布窗口 error 日志为 0;这些内部状态本次未独立复核。
判定:外部入口总体健康,单次超时暂记为网络瞬态,不设 P0;预生产前仍需用可用只读凭据复核内部状态。
边界说明:外部 smoke 曾请求一次验证码 GET 接口,该接口会在 Redis 写入一个 5 分钟 TTL 的一次性验证码记录;未提交登录、未创建用户或业务数据,未触发短信、余额、应用、通道或 MinIO 业务写入。
5. 当前问题清单
CQ-QG-001 / P1:增量 lint/format 门禁假绿且整改代码未通过
证据
tools/quality/run-changed-code-quality.mjs:7-14默认基线为HEAD,正常提交后执行npm run lint时不会检查已提交整改代码。- 本次默认运行输出
No changed code files require lint/format,不能证明ad27aca中的代码通过。 - 设置
QUALITY_BASE_REF=3af145a...后,Windows 包装器无错误信息退出 1;脚本没有输出spawnSync的 error。 - 绕过包装器直接对 37 个整改文件执行 ESLint,发现 6 个 error、2 个 warning:
api/src/auth/auth.controller.ts:2 个未使用变量。api/src/open-api/open-api.service.ts:1 个未使用 import。src/api/client/client.api.ts:2 个未使用 import。src/apps/client/ClientUsersPage.test.tsx:1 个未使用变量。src/apps/LoginPage.tsx:Fast Refresh 导出警告、useEffect缺少refreshCaptcha依赖警告。
- Prettier 检查发现
api/src/auth/auth.service.spec.ts、api/src/open-api/open-api.service.spec.ts未格式化。
影响
整改记录中的“ESLint/Prettier 门禁通过”不是当前可重复证据。CI 如果没有显式传入基线会漏检提交;Windows 本地即使传入基线也会无诊断失败。
关闭要求
- 门禁显式接收并验证 base/head,CI 使用 merge-base;本地提供全量或最近提交模式。
- Windows 调用方式可执行,并在 spawn 失败时输出
result.error。 - 修复 6 个 error、2 个 warning 和 2 个格式文件后,直接 ESLint/Prettier 与包装脚本均通过。
- 为“无变更”“有错误”“Windows 启动失败”和“CI 基线”增加脚本测试。
CQ-API-001 / P1:客户端删除接口仍未纳入严格运行时校验
api/src/deletion-governance/deletion-governance.controller.ts:34-38 的客户端删除接口使用 DeleteTargetDto,但没有 @UsePipes(strictValidationPipe);api/src/deletion-governance/deletion-governance.service.ts:10-18 的 DTO 仍为 TypeScript type,没有 class-validator 规则。请求中的额外字段、超长 reason、错误布尔类型、非法时间和幂等键格式不会按统一客户端策略拒绝。
关闭要求:建立 client deletion class DTO、严格管道和负向测试,并把结构门禁扩展为检查所有 @Controller('client...') 的 body 写接口,而不是仅靠人工清单。
CQ-COV-001 / P2:API 标准覆盖率脚本仍不是全源口径
标准 test:coverage 未配置 collectCoverageFrom,容易把 70.44% 误写为全源覆盖率;严格全源只有 60.46%。应在正式配置中固化全源 include/exclude,并保留增量覆盖作为第二道门禁。
CQ-MAINT-001 / P2:SendChain 超大服务仍未拆分
send-inbound-entry.service.ts 约 84.2 KiB,send-gateway-submit.service.ts 约 52.2 KiB。本轮明确延期是合理的风险控制,但不能记为质量治理完成。后续需先补行为锁定和性能基线,再分职责重构。
CQ-REPO-001 / P2:本地提交尚未推送且旧 pnpm 锁仍存在
本地比 origin/main 超前 3 个提交,远端凭据拒绝已在进度文档记录;测试环境部署了代码提交 226527f...,但远端 Git 仍停留在 V2 基线。灾备、协作和可追溯性因此不完整。另有未跟踪旧 pnpm-lock.yaml,虽未纳入正式流程,仍可能误导人工命令。
CQ-ACC-001 / P2:登录后浏览器和真实全链仍未复验
测试环境只验证了公开页面、验证码和 health;没有输入密码或代解验证码,没有验证登录后 loading/empty/error/refresh、权限和关键写操作,也没有重跑 PostgreSQL/Redis/MinIO/Gateway/CMPP 模拟器全链。自动化测试不能替代这些最终验收证据。
6. 发布建议
当前建议:允许继续整改和测试环境验证,暂停预生产发布。
最小充分关闭顺序:
- 修复增量 lint/format 包装器并清零当前 lint/format 失败。
- 补齐客户端删除 DTO、严格校验和负向测试。
- 把 API 严格全源覆盖率固化为标准门禁,修正文档口径。
- 使用可用只读凭据复核测试环境部署标记、11 项服务、95 项迁移、Redis Stream 和 error 日志。
- 在真实登录态下完成客户端/运营端关键页面和请求状态验收。
- 取得授权后解决远端 Git 凭据并推送;推送不是本次复评授权范围。
- SendChain 拆分继续作为独立高风险任务,不与上述门禁修复混合。
7. 最终判定
- 原始安全 P0:0 项未关闭。
- 当前 P0:0 项。
- 当前 P1:2 项——质量门禁假绿、客户端删除校验遗漏。
- 当前 P2/验收边界:API 覆盖率口径、SendChain 重构、Git/锁文件治理、登录后与真实全链验收。
- 自动化:前端 34 项、API 563 项、Gateway 全包测试均通过。
- 构建与包体:通过。
- 依赖:根项目 0;API 5 项 Prisma CLI 风险已记录接受。
- 测试环境公开入口:通过,存在一次短暂超时后连续 5 次快速恢复。
- 代码质量:86/100,有条件通过。
- 持续治理闭环:未通过。
- 预生产发布建议:暂停。
本报告只对应固定提交和本次可重复证据,不把整改记录、单元测试或公开 health 冒充真实后端全链与登录后功能验收。