V1.0.1 配置与规则纠偏:照片上限配置化+强校验 / 活体开关闭环 / 推荐阈值快照+规则版本化 / governance 三表+漂移审计

根治三类工程治理问题(技术默认值≠产品规则、配置存在但未闭环、文档代码漂移):
- PROFILE-001:profile.photo.maxCount(默认6未确认)+ ProfilePolicy + 服务器端 FOR UPDATE
  并发强校验(PHOTO_LIMIT_EXCEEDED,拒绝先于 S3 不留孤儿)+ 前端 mergeAppConfig 嵌套键修复
- CFG-001/IDENTITY-001:IdentityPolicy + GET /verification/liveness-status 真实判定点
  (默认关不阻断,开则 enhancedVerified 变化,消除假开关)+ 删死 seed livenessVerification.enabled
- MATCH-001:阈值60定为技术默认(消解 PENDING 矛盾)+ V050 recommendation_records.threshold_snapshot
  规则版本化 + 删死重复配置类 MatchConfig
- DOC-001:新增 docs/governance/(config-register/open-questions/decision-register/
  hardcoded-rule-audit/config-drift-audit)
- TEST-001:新增守卫 PhotoLimitGuardTest(8)/IdentityLivenessGuardTest(5)/
  RecommendationThresholdSnapshotGuardTest(4),均经负向注入可红

全量回归 733/0/0/3(基线717+17新增-1删死测试);UI 契约门禁 18/18;STATUS 升 rc.21
This commit is contained in:
WorkBuddy
2026-09-21 02:05:15 +08:00
parent b60c1ffb71
commit 438b38d121
37 changed files with 1033 additions and 101 deletions
+45
View File
@@ -0,0 +1,45 @@
# 硬编码规则审计 — hardcoded-rule-audit.md
> **版本**:V1.0.1 配置与规则纠偏 · **日期**:2026-09-20 · **扫描**:业务代码数值/常量 + `MAX_/LIMIT_/THRESHOLD_/COOLDOWN_/TIMEOUT_/COUNT_/SCORE_`
> **定级**:LOCKED(产品确认)/ DEFAULT(技术默认)/ CONFIG(应配置化)/ TBD(未确认)/ FUTURE(非 V1 范围)
> **判定原则**:未确认数量参数不得作为固定业务常量写死(AGENTS.md #12);必须存在运行初值时,定义为 `DEFAULT + CONFIG` 并登记 `config-register.md`。
---
## 一、已配置化且被真实读取(本轮/历史已合规)
| 规则 | 载体 | 值 | 定级 |
|------|------|----|------|
| 每日推荐上限 | `MatchRuleConfigProperties.defaultDailyLimit`(yml `match.default-daily-limit`) | 6 | LOCKED(已确认每日 6 人) |
| Pass 冷却天数 | `match.default-cooldown-days` | 180 | LOCKED(已确认) |
| 推荐最低阈值 | `match.default-score-threshold` → `MatchingPolicy` | 60 | CONFIG / **TBD**(技术默认,未确认,OQ-MATCH-001) |
| 匹配规则版本 | `match.rule-version` | 1 | CONFIG |
| 10 维推荐权重 | `match.*-weight` | age15/region15/… | CONFIG / TBD(yml 未覆盖,全用类内默认) |
| 照片上限 | `profile.photo.max-count` → `ProfilePolicy` | 6 | CONFIG / **TBD**(技术默认,未确认,OQ-PROFILE-001;服务器端强校验) |
| 注销保留期 | `account.data-retention-months` | 36 | LOCKED(2026-09-19 产品确认) |
| 本地资格佐证参数 | `features.localEvidence*`(保留 365 天/5 文件/10MB/jpg,png) | 见左 | CONFIG(保留期 LEGAL_VERIFY,OQ-LOCAL-ELIG-001) |
| 活体开关 | `features.livenessEnabled/livenessProvider` → `IdentityPolicy` | false / none | CONFIG / TBD(OQ-IDENTITY-001) |
| 幂等 TTL | `idempotency_records`(默认 86400s) | 86400s | CONFIG / LEGAL_VERIFY(第三方分级待定) |
## 二、仍为硬编码 —— 本轮**未纳入**,登记为「待统一」未来项
> 本轮按约束 12 只纠偏文档点名的 3 项(活体键 / 照片上限 / 推荐阈值)。以下为同族但**未动**,避免越界:
| 位置 | 硬编码 | 建议 |
|------|--------|------|
| `AppController` `/app/config` | `dailyRecommendationLimit=6`、`maxInterestTags=8`、`selfIntroMaxLength=500`、`recommendationCooldownDays=180`、`reviewConfig{autoApproveAfterDays=7,maxResubmitCount=3}`、`features` 全 true | 统一改读 `MatchRuleConfigProperties` / 对应配置,前端经 `/app/config` 下发;值确认后转 LOCKED |
| `RecommendationEngineService` / `MatchEligibilityService` | 互选公式系数 `0.6*min + 0.4*avg`(:230/:122)、level 分档 `>=80 high / >=60 medium`(:392-396/:262-266)、`calculateScore` 恒返回 `50.0`(V1 占位) | **打分是 V1 占位**,公式/分档/系数尚未产品化;正式化时一并配置化 + 记入规则版本 |
| `PhotoService` | 图片大小上限 10MB、签名 URL 24h、上传凭证 1h(`SIGNED_URL_EXPIRE_HOURS`) | 属对象存储/S3 参数,非业务规则;如需可调再配置化(低优先级) |
## 三、常量类扫描(非业务数值,多为校验/分页,合规)
| 常量 | 说明 |
|------|------|
| `MAX_LENGTH`(42 处) | 字段长度校验上限,属校验约束,非「未确认业务数量」 |
| `MAX_PAGE_SIZE` / `MAX_VALUE` / `MAX_PER_MINUTE*` / `MAX_LOGIN_ATTEMPTS` | 分页/速率/登录防爆破,合理技术上限 |
| `PHOTO_LIMIT_EXCEEDED`(本轮新增业务码) | 照片超限业务错误码,非数值 |
---
*结论:本轮已将文档点名的 3 项(活体键、照片上限、推荐阈值)落实为「配置源唯一 + 真实读取 + 默认值受控」。
上表第二节为同族未动项,建议在后续 Phase 按同一纪律统一(勿一次性扩大重构)。*