7.5 KiB
Phase 17 — 举报与风控 KEEP-VERIFY/EXTEND 复验完成报告
日期:2026-09-17 范围:举报与风控(risk / report / referral 模块 + 后台风险页) 纪律:KEEP-VERIFY/EXTEND。历史 ✅ 不可信;测试覆盖 ≠ 运行时路径覆盖;逐条核对运行时路径与生产约束;发现真实缺陷即修;补测试保真度;守卫必须解析真实 DDL;离线容器真实编译+执行;每阶段出报告后停止等确认。
一、结论
两项 Gate 全部达成,复验关闭。
| 项 | 结果 |
|---|---|
| 风险来源可追踪 | ✅ counseling / service_station / offline_activity 三来源均接入统一 RiskEvent,且已确认运行时真实调用(非定义未调用) |
| 正文最小可见 | ✅ 后台风险画像只带必要来源上下文,不暴露无关咨询正文(INV-006 同族约束延续) |
| 低权限人员不能扩大读取范围 | ✅ 禁止公开黑名单;敏感访问全部审计(AGENTS.md #8 敏感数据默认拒绝 + 查看需审计) |
本轮修复真实缺陷 6 处(含 1 处必崩级测试盲区、1 处隐藏编译缺陷),新增集成测试 7 例。
- 全量回归:488 tests / 0 failures / 0 errors / 3 skipped / BUILD SUCCESS(约 4 分)
- 基线 481 → 488,净 +7(Phase 17 集成测试 7 方法)
- 负向验证:临时注释
getReportDetail敏感访问审计 →operatorRiskEndpointsRecordSensitiveAccessAudit精准变红,已还原
二、本轮最关键发现(必记)
F1:风控/举报真实 DB 路径「零覆盖」盲区(必崩级)
EntityMigrationParityTest 的白名单 TEST_SCHEMA_OPTIONAL_TABLES 中列有 reports / risk_actions / risk_events 三张表,但 H2 测试库 schema-h2.sql 中根本没有这三张表的定义 → 整条 ReportService / RiskReferralService 真实 DB 路径零测试覆盖;而 ReportServiceTest 全是 assertTrue(true) 假绿。这与 STATUS.md 反复警示的"测试库缺表 → 零覆盖 → 必崩"模式完全一致,是本轮 KEEP-VERIFY 的最高风险点。
修复:在 schema-h2.sql 补齐三表(对齐 V012 生产 DDL,去外键、保留 CHECK);将三表从 TEST_SCHEMA_OPTIONAL_TABLES 移除,加入 REQUIRED_IN_TEST_SCHEMA(带 Phase 17 注释);新建真实 DB 集成测试。
F2:隐藏编译缺陷(javax → jakarta)
为补审计在 ReportService / RiskReferralService / AuditLogService 中引入 HttpServletRequest 取 ip/userAgent 时,误用 javax.servlet.http(Spring Boot 3.x 已迁移到 Jakarta EE jakarta.servlet.http)→ test-compile 直接失败。修复为 jakarta.servlet。印证 Phase 15 铁律:每次复验结束前必须真实编译+执行,不能以文档声明替代实证。
F3:补表时的列缺失
schema-h2.sql 的 risk_events 表起初漏了 updated_at 列(实体 RiskEvent extends BaseEntity 含 updatedAt,MyBatis-Plus 注入该列)→ 全量回归 6 个 BadSqlGrammar 错误。修复补齐 updated_at(与 reports / risk_actions 一致)。
三、真实缺陷清单(对应 Gate)
| 编号 | 类别 | 缺陷 | 修复 | Gate |
|---|---|---|---|---|
| D1 | 测试保真度/必崩级盲区 | reports/risk_events/risk_actions 在 H2 缺失 → 风控/举报真实 DB 路径零覆盖;ReportServiceTest 假绿 |
补三表 + 移出白名单 + 入必需集合 + 真实集成测试 ReportAndRiskPhase17IntegrationTest(7 例) |
风险来源可追踪 |
| D2 | 审计缺失 | manualFlagRisk(人工风险标记)不写审计 |
注入 AuditLogMapper,写 MANUAL_FLAG_RISK |
低权限不扩大读取 |
| D3 | 敏感访问无审计 | 查看他人风险画像/举报详情/风险事件列表不记录审计(AGENTS.md #8) | 新增 AuditLogService.recordSensitiveAccess;getReportDetail/getUserRiskProfile/RiskController.getRiskEvents 三端点接线 |
低权限不扩大读取 |
| D4 | 审计完整性 | ReportService.saveAuditLog 未填 ip/userAgent |
增强补全(与 AuthorizationAuditListener 同模式取 RequestContextHolder) |
低权限不扩大读取 |
| D5 | 数据一致性 | RiskEventMapper.findByUserId 未过滤 deleted_at,与 sumScoreByUserId(已过滤)不一致 |
补 deleted_at IS NULL |
风险来源可追踪 |
| D6 | 编译/列缺失 | 见 F2、F3 | jakarta 修正 + risk_events 补 updated_at |
— |
来源接入代码层(
detectCounselingRisk/detectAppointmentRisk/detectActivityRisk)在运行时已被CounselingService/ActivityService/ServiceAppointmentService真实调用,常量齐全,不是"假绿",本轮核心在修复覆盖盲区与审计缺口,而非重写来源逻辑。
四、负向验证(守卫有牙)
- 临时注释
ReportOperatorController.getReportDetail中的auditLogService.recordSensitiveAccess(...)→ 定向运行ReportAndRiskPhase17IntegrationTest→ BUILD FAILURE(operatorRiskEndpointsRecordSensitiveAccessAudit断言before+3 == after失败,实际只 +2)。已还原,代码回到 488 全绿状态。
五、证据(实测,非声明)
- 全量回归:
488 tests / 0 failures / 0 errors / 3 skipped / BUILD SUCCESS(离线容器danyang-match-backend-testmvn -B -o test,约 4 分)。 - 定向编译验证:
mvn -B -o test-compile通过(jakarta 修正后)。 - 新增测试:
backend/src/test/java/com/danyang/match/platform/risk/ReportAndRiskPhase17IntegrationTest.java(7 例:submitReport 写 reports+abuse_report 风险事件、三来源接入统一 RiskEvent、处置封禁写 risk_actions(ban)、manualFlagRisk 审计、敏感访问审计、findByUserId 软删过滤、最小可见)。
六、改动文件清单
主代码(src/main)
backend/src/test/resources/schema-h2.sql— 补齐reports/risk_events/risk_actions三表(对齐 V012,去外键、保留 CHECK;risk_events含updated_at)。backend/src/main/java/com/danyang/match/platform/risk/mapper/RiskEventMapper.java—findByUserId补deleted_at IS NULL。backend/src/main/java/com/danyang/match/platform/risk/service/ReportService.java—saveAuditLog补全ip/userAgent(jakarta 修正)。backend/src/main/java/com/danyang/match/platform/risk/service/RiskReferralService.java— 注入AuditLogMapper,manualFlagRisk写审计(jakarta 修正)。backend/src/main/java/com/danyang/match/platform/audit/service/AuditLogService.java— 新增recordSensitiveAccess(jakarta 修正)。backend/src/main/java/com/danyang/match/platform/risk/controller/ReportOperatorController.java—getReportDetail/getUserRiskProfile接线敏感访问审计。backend/src/main/java/com/danyang/match/platform/risk/controller/RiskController.java—getRiskEvents接线敏感访问审计。
测试(src/test)
backend/src/test/java/com/danyang/match/platform/risk/ReportAndRiskPhase17IntegrationTest.java— 新增 7 例。backend/src/test/java/com/danyang/match/platform/deployment/EntityMigrationParityTest.java— 三表移出白名单、入REQUIRED_IN_TEST_SCHEMA(Phase 17 注释)。
文档
docs/STATUS.md、docs/JIRA_BACKLOG.md、docs/善缘丹阳 V1.1 客户需求基线增量开发与修复计划.md的 Phase 17 段。docs/Phase-17-V11-Recovery-Completion-Report-2026-09-17.md(本报告)。- 技能
danyang-platform-verification同步更新。
七、下一步
Phase 18(申诉 — KEEP-VERIFY)未自动进入,等待用户确认后启动。 是否继续?