# feat(wx-security): Phase 2C 出行人三层兜底

**PR**: [#1666](https://git.1814.love:8443/wx/HL/pulls/1666) **Issue**: [#1663](https://git.1814.love:8443/wx/HL/issues/1663) **合并**: 2026-05-05

按官方契约 §8 出行人姓名实名信息特殊处理：机审误伤代价高（真实姓「操/苟」、少数民族罕字、港澳台/外籍拼音），**前端不做硬拦截**，后端三层兜底。

## 三层兜底

### 第 1 层 入库静默机审（不阻塞业务）
- traveler.create/update + order_traveler.add/update **业务先成功**
- afterCommit + @Async 触发异步 msgSecCheck（scene=1 资料）
- 命中 risky/review/pass=false → **MANUAL_REVIEW**（不直接 REJECTED 避免误伤，运营 Phase 2D 人工裁决）
- 微信 5xx/异常降级 PENDING（不删数据不拒收）
- 命中违规落 traveler_audit_log 审计日志（正常用户不入，避免噪音）
- 同款适用 emergencyContact + user.realName（复用 Phase 1 nickname_audit_status 列）

### 第 2 层 选用时校验（下单仅挡 REJECTED）
- `TravelerService.requireApprovedForBooking` helper
- REJECTED → BusinessException 「此出行人信息异常,请联系客服核实」
- PENDING / MANUAL_REVIEW / APPROVED 全放行（误伤场景不影响出行）
- 注：admin 端下单（OrderCreateService.saveTravelers）受 spec 设计限制只走 Layer 3 验证（无源 traveler 联动），跨服务 Feign 留 Phase 2D

### 第 3 层 本地正则（同步硬拦,防垃圾）
`TravelerNameValidator` 4 条规则：
- 长度 2-30（codePoint 字符数）
- 字符集白名单 `^[中文a-zA-Z·\-\s]+$`
- 黑名单（初始空，Phase 2D admin 维护）
- 重复字符 `.*(.)\1{4,}.*` 防 aaaaa/test

误伤豁免（已单测覆盖）：「操军」/ 「司马相如」/ 「张-李」/ 「a·b」 通过；「aaaaa」/ SQL 片段拒。

## 新表 + 配置

- `traveler_audit_log`（V20260505_004 增量 SQL + schema.sql 同步）
- `TravelerAuditAsyncConfig` 独立线程池（core=4/max=8/queue=200/CallerRunsPolicy）
- @Async qualifier 严格对齐 `@Bean("travelerAuditExecutor")`

## 4 个新错误码（CommonErrorCode）

- TRAVELER_NAME_LENGTH_INVALID 「姓名长度异常(2-30字符)」
- TRAVELER_NAME_CHAR_INVALID 「姓名含非法字符」
- TRAVELER_NAME_BLACKLISTED 「姓名含敏感词」
- TRAVELER_NAME_REPEATED_CHAR 「姓名格式不正确」
- TRAVELER_REJECTED 「此出行人信息异常,请联系客服核实」

## 前端契约要点（mmg）

- 前端不再做硬拦截 — 4 个错误码配套 toast 文案即可
- 出行人列表展示状态条：审核中 (PENDING/MANUAL_REVIEW) / 已通过 (APPROVED) / 已拒 (REJECTED 仅运营手动设置)
- 下单时若 traveler.audit_status=REJECTED 后端返业务码 100705，前端 toast 后引导联系客服

## 测试

- mvn compile 全工程 BUILD SUCCESS
- 235 单测全绿（TravelerNameValidator 44 + TravelerAuditService 22 + TravelerAuditAsyncConfig 1 + TravelerService 84 + OrderTravelerService 34 + 回归 50）
- CR 通过（5 P1 留 Phase 2D cleanup：Service Mapper 拆分 / @Async+@Transactional 分离 / 字段注入改构造器 / 审计日志吞异常改 ERROR / 文档 TODO 标注）

## 不在本期范围

- order.contactName 同款审（无独立 SaveReqVO 入口）
- order_traveler.audit_status 跨服务字段（spec 设计跳过；admin 下单 Layer 3 已挡垃圾名字）
- 运营人工 REJECTED 裁决 + 黑名单维护（Phase 2D #1664 admin 后台）
