Files
danyang-match/docs/Phase-17-V11-Recovery-Completion-Report-2026-09-17.md
T

7.5 KiB
Raw Blame History

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-test mvn -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)未自动进入,等待用户确认后启动。 是否继续?