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
+40 -6
View File
@@ -46,11 +46,45 @@ exports.BUSINESS_LIMITS = {
};
/**
* 用服务端返回的配置覆盖默认值(规范 §118)
* @param {Partial<typeof exports.BUSINESS_LIMITS>} overrides 服务端配置
* @returns {typeof exports.BUSINESS_LIMITS} 合并后的配置
* 服务端 /app/config 的嵌套结构 → 客户端 UPPER_SNAKE 常量的显式映射。
*
* <p>此前用平铺合并 {@code {...BUSINESS_LIMITS, ...overrides}},命不中嵌套 key
* (服务端返回的是 {@code businessLimits.maxProfilePhotos} / {@code features.x}),
* 导致服务端下发的照片上限 / 推荐阈值等配置<b>从不生效</b> —— 前后端规则漂移
* (V1.0.1 配置纠偏 PROFILE-001 前端侧根因)。现改为按节(section)+ 键显式映射,
* 且仅在「服务端给了该键 && 客户端确有该常量」时才覆盖,缺省回退本地默认值。
*/
exports.mergeAppConfig = (overrides) => {
if (!overrides || typeof overrides !== 'object') return exports.BUSINESS_LIMITS;
return { ...exports.BUSINESS_LIMITS, ...overrides };
const SERVER_SECTION_TO_CLIENT_KEY = {
businessLimits: {
dailyRecommendationLimit: 'DAILY_RECOMMENDATION_LIMIT',
maxProfilePhotos: 'MAX_PROFILE_PHOTOS',
maxInterestTags: 'MAX_INTEREST_TAGS',
selfIntroMaxLength: 'MAX_INTRO_LENGTH',
},
features: {
activityEnabled: 'ACTIVITY_ENABLED',
matchmakerEnabled: 'MATCHMAKER_ENABLED',
imageChatEnabled: 'CHAT_IMAGE_ENABLED',
},
};
/**
* 用服务端返回的配置覆盖默认值(规范 §118)
* @param {object} serverConfig 服务端 /app/config 的完整响应(含 businessLimits / features 等嵌套节)
* @returns {typeof exports.BUSINESS_LIMITS} 合并后的运行时配置
*/
exports.mergeAppConfig = (serverConfig) => {
const merged = { ...exports.BUSINESS_LIMITS };
if (!serverConfig || typeof serverConfig !== 'object') return merged;
for (const [section, keyMap] of Object.entries(SERVER_SECTION_TO_CLIENT_KEY)) {
const src = serverConfig[section];
if (!src || typeof src !== 'object') continue;
for (const [serverKey, clientKey] of Object.entries(keyMap)) {
if (Object.prototype.hasOwnProperty.call(src, serverKey)
&& Object.prototype.hasOwnProperty.call(merged, clientKey)) {
merged[clientKey] = src[serverKey];
}
}
}
return merged;
};