Commit Graph
7 Commits
Author SHA1 Message Date
WorkBuddy 6c2601950b docs(governance): ZC-MM-007 同步治理文档——红娘专项 DEC-MATCHMAKER-001~006 收口
- decision-register.md: 登记 DEC-MATCHMAKER-001~006 全部 LOCKED(实施摘要 + 落地提交链 2d60f78/861c78e/5e484d0/3caf5f8/1be0d98 + 验证数字 mvn verify 884/884、UI 契约 24/24、后端契约 198、负向注入 7 处判红→还原)
- open-questions.md: 新增 OQ-MATCHMAKER-003~008——003 受控联系开放前 5 项确认(①②LEGAL_VERIFY)+ ContactAuthorizationPolicy DEFERRED(MatchmakerContactGuardTest 机械锁强制复审)/ 004 NULL=NULL 平台直属规则 / 005 零缓存实时查库压测复议条件 / 006 写接口 404 化语义边界(RESOLVED)/ 007 purpose_code matchmaker.service.view 定义未使用口径漂移(QA P2①)/ 008 运营域 active 与用户域 normal 状态口径差(QA P2②)
- PENDING_DECISIONS.md: 红娘专项六项决策标已落地;新增两项待产品确认——受控联系授权机制开放(OQ-003 引用)、C 端死代码退役 3 项(getCandidates/cancelService/getRecommendationsForUser,grep 零调用已核)专项治理批次

ZC-MM-001~007 全链路闭环(架构师落盘 + 主理人 grep 锚点终验:DEC-MATCHMAKER/DEFERRED/LEGAL_VERIFY/OQ-003~008 全命中,零代码变更)
2026-10-11 10:26:35 +08:00
WorkBuddy 3caf5f8816 feat(matchmaker,referral): ZC-MM-005 统一数据范围与字段隐私(DEC-MATCHMAKER-005/§5.2 落地)
依据《善缘丹阳 V1.1 红娘角色权限正式决策与开发规则》DEC-MATCHMAKER-005 最小必要原则
与 §5.2 字段级隐私,ZC-MM-005 范围=「读接口行级数据范围统一接入判定器 + 字段白名单 +
组长团队脱敏统计」。承接 ZC-MM-002 落地的 matchmaker_assignments 事实源与
ServiceAssignmentPolicy 判定器。

E1 双轨切纯判定器(不留回退):
- assertServiceAccess 纯化(删 assigned_operator_id 回退分支),判定器成唯一事实源
- getServiceDetail 删 viewerIsOwner 双态与「非负责人脱敏详情」整段

E2 非负责人防探测 404:
- ServiceAssignmentPolicy.assertActiveAssignmentOrNotFound:无生效分配→先落
  DATA_SCOPE_DENIED 审计再抛 NOT_FOUND(响应 404),存在性不可枚举,
  与「查无此单」响应体逐字段一致(MM-PRIVACY-001)

E3 字段白名单显式化 + 用户隐私开关:
- 抽取 assembleMatchmakerUserProfile:仅 7 键(displayName/gender/age 派生/regionName/
  educationCode/occupationCode/maritalStatus),无 birthDate 原值/详细地址/手机号/微信/
  身份证;接 UserPrivacySettings.showOccupation(缺省全放行)

E4 死端点清理:
- 删除 GET /operator/matchmaker/my-services(operatorId 误当 user_id、恒空、前后端零调用),
  替代路径 /operator/matchmaker/assignments/my;C 端 /matchmaker/services 与
  counseling myServices 保留

P1 残留收口(读/写路径仍信任废弃 assigned_operator_id 残留列,与 E1 同类洞):
- P1-1 运营端推荐列表:MatchmakerRecommendationMapper.findByOperatorId 改 join
  生效分配(active+expires),撤/结后不再可见
- P1-2 dashboard 三计数:count*ByOperator 改 join 生效分配 + COUNT(DISTINCT) 防重,
  end/revoke 后不再计入(DEC-002 规则7)
- P1-3 转介授权:ReferralService.assertMatchmakerServesUser 切
  serviceAssignmentPolicy.assertActiveAssignment(DATA_SCOPE_DENIED 审计 + 403),
  删残留列查询 findActiveByOperatorAndUser

新端点(组长团队脱敏统计):
- GET /operator/matchmaker/team/statistics(@PreAuthorize matchmaker.team.assign):
  本组织 active 分配数/按红娘分组/在岗红娘数,纯计数无用户 PII;org 边界
  IS NOT DISTINCT FROM(NULL=NULL 平台直属)

P2-4 operatorName 脱敏决策:保留不脱敏(§5.2 字段分类:红娘姓名=团队范围内
工作人员标识非用户 PII;组长统计本团队工作量属管理职责),依据登记
docs/governance/open-questions.md OQ-MATCHMAKER-002(RESOLVED)

死代码清理:getOperatorServices(零调用)+ MatchmakerServiceMapper.findByOperatorId
(残留列查询,调用清零)删除;C 端 MatchmakerService 遗留信任残留列按豁免未动(006/007 退役)

测试:
- MatchmakerDataScope005Test(13 用例):MM-PRIVACY-001/002、MM-AUTH-001/003 读侧、
  MM-LIFECYCLE-001 读侧、P1-1/2/3 残留收口负向(撤/结后推荐不可见/计数归零/转介 403)、
  防探测逐字段一致、showOccupation 三态
- MatchmakerFieldPrivacyGuardTest(3 用例):字段白名单源码扫描 + 无导出端点锁定
- MatchmakerReferralPhase13Test 转介口径收紧(IllegalStateException→AccessDeniedException)
- 负向注入自证(P1-3 残留列变异→判红→恢复复绿)

验证:定向 73/73;全量 851/851(3 预存 skip);UI 契约 24/24。
2026-10-10 11:51:15 +08:00
WorkBuddy 9fc3385d6c feat(ci): 新增后端契约门禁 scripts/run-backend-contracts.mjs 并接入 CI
CI/CD Pipeline / Backend Build & Test (push) Canceled after 0s
CI/CD Pipeline / Admin Web Build (push) Canceled after 0s
CI/CD Pipeline / Mini Program Compile Check (push) Canceled after 0s
CI/CD Pipeline / Migration Validation (push) Canceled after 0s
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Canceled after 0s
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Canceled after 0s
CI/CD Pipeline / E2E (live stack) (push) Canceled after 0s
与 scripts/run-ui-contracts.mjs 同级:固化一组关键后端回归/契约测试
(含 v1.1.0 修复的 3 个回归测试 + JwtAuthFilter Cookie 兜底 + 核心不变量),
先校验测试源文件存在性下限(防改名/删除后门禁假绿),再用 mvn test -Dtest
真跑并解析 surefire 汇总。在 backend job 的 mvn verify 之后执行,复用已
编译产物与依赖缓存,开销极小。同步更新 CODE_REVIEW_STANDARDS.md 门禁说明。
2026-09-30 16:21:25 +08:00
WorkBuddy ca0db57f24 chore(release): 冻结 v1.1.0 版本
- 同步版本号:VERSION / backend pom / admin-web / miniapp 均升至 1.1.0
- 合并本轮代码审查修复(详见 docs/CODE-REVIEW-2026-09-24.md):
  - 后端:微信登录真实实现 RealWechatLoginProvider、实名核验真实实现 RealIdentityVerificationProvider(本地强校验 + 可配置第三方 + fail-closed/fail-fast)
  - 照片直传落库端点 POST /me/photos/confirm(fileKey 归属校验 + 对象存在性校验后 savePhoto)
  - 刷新 Token Redis TTL 修正(getExpirationMs()*2 的 4h → refreshExpirationMs 的 14 天)
  - 管理端 token 改为 HttpOnly Cookie + silent-refresh,移除 localStorage 明文存储与 30+ 处手工注入
  - 小程序:红娘接单鉴权头错位修复、serviceType 中文映射、生产域名可配置
- 隔离本地产物(.workbuddy/、*.bundle、*.dump、secrets、application-dev.yml 等已被 .gitignore 覆盖)

未验证项(打标签 ≠ 生产发布):
- 后端编译 / 单测未在本环境执行(Maven 慢、Docker DNS 受限)
- 管理端 登录→刷新→登出 端到端、小程序真机走查待人工验收
- 生产部署需注入 WECHAT_APP_ID / WECHAT_APP_SECRET、VERIFICATION_API_URL / VERIFICATION_API_KEY 与小程序生产域名
2026-09-30 12:10:00 +08:00
WorkBuddy 8bd1ab804a fix(organization): 修复创建机构审计缺操作人;补全机构修复的验证并部署 Docker 测试环境
一、机构审计归属缺陷(本轮活栈验收中新发现)
- 现象:audit_logs 中 CREATE_ORGANIZATION 的 operator_id 7/7 为 NULL,
  而 DISABLE/ENABLE_ORGANIZATION 均正确记录操作人。审计不可归属 = 无效审计。
- 根因:OrganizationController.create 持有 @AuthenticationPrincipal OperatorPrincipal,
  却只把 params 传给 Service,未透传 principal.id() → saveAuditLog(null, ...)。
- 修复:createOrganization(params, operatorId) 签名透传;新增测试断言
  createOrganizationRecordsOperatorInAuditLog 长期守卫。
- 复验:新写入的 7 条 CREATE 审计全部带 operator_id,旧 14 条仍为 NULL(前后对照清晰)。

二、补全 rc.22 的验证缺口(此前记为「已修复待验证」)
- 全量回归 757 / 0 / 0 / 3,BUILD SUCCESS,108 个测试类,6:44(基线 741 + 新增 16)。
- 负向注入:ORG_STATUS_ACTIVE 改回 "normal" → 16 例变 3 失败 + 7 错误
  (守卫三条断言各自命中 + 服务侧 7 例被 H2 CHK_ORG_STATUS 拦下)。
  注入采用「仓库只读挂载 + 容器内副本改写」,工作区哈希前后一致,源码零污染。
- 活栈实测(Docker 全栈):创建/停用/启用均 2xx、非法输入 400、不存在 404、全程零 5xx(15/15)。
- 对已部署栈 pytest tests/e2e → 65 passed。

三、Docker 测试环境部署与工具链固化
- 测试镜像 danyang-match-backend-test 与命名卷 danyang-m2-cache 因 Docker Desktop 重装丢失,
  构建定义此前是临时产物 → 落盘为仓库资产 infrastructure/test-toolchain/Dockerfile。
- 本地栈统一使用 docker compose -p danyang(原项目名 infra 与另一项目撞名,
  其 --remove-orphans 会误删本项目容器;已确认邻项目数据无丢失,见 known-risks KR-09)。

四、UI 门禁脆弱性修复
- ui-document-baseline-contracts.mjs 解析 docker-compose.staging.yml 时报假红
  (「守卫自身失效」);真因是该文件为 CRLF 而守卫正则要求 \n 紧随 container_name 之后
  (prod.yml 是 LF 所以此前能过)。解析改为行尾无关,真实断言未削弱。门禁 18/18。

五、文档
- STATUS.md 新增 rc.23 并将 rc.22 由「待验证」订正为「已验证关闭」。
- 实施计划附 B.1、PROGRESS-ASSESSMENT-2026-09-21.md 同步订正。
- known-risks.md:KR-07 解除(Docker 已恢复)、KR-01/KR-06 按复测订正,
  新增 KR-08(Docker Hub 域名 DNS 被投毒,改用国内镜像源绕行)与 KR-09(compose 项目名撞名)。

验证状态:全量回归 757/0/0/3 全绿;UI 契约门禁 18/18;对已部署栈 E2E 65/65;
负向注入可变红;工作区哈希未被注入过程污染。
未验证:GitHub Actions 首次真绿(仍未推送,见 KR-06)。
2026-09-22 00:46:10 +08:00
WorkBuddy 60c591fc68 V1.0.1 纠偏 DoD 补齐:canonical key 字面化(V051+KEY_ALIASES)+ 照片并发突破实测(锁用户行+锁后计数)+ AGENTS 规则27 + known-risks
按文档 DoD/约束逐条复查后补齐的差距(承接 438b38d 主体纠偏):
- CFG-001 字面化:FeatureFlagConfig.KEY_ALIASES(identity.liveness.enabled / 遗留
  livenessVerification.enabled → 实现字段 livenessEnabled,读兼容)+ Controller PUT/DELETE
  落库归一到 canonical 键 + V051 迁移(删遗留键、写入 identity.liveness.enabled=false);
  MigrationValidationTest 基线 50→51。
- PHOTO-004 真实并发突破:新增 PhotoLimitConcurrencyGuardTest(3 线程 H2 并发冲顶)——
  实测咬住「锁照片行+读时计数」在 H2 MVCC 快照漏读、3/3 全成功突破上限的缺陷;
  并发控制改为锁用户行(UserMapper.lockUserRow FOR UPDATE)+ 锁后新语句 COUNT,
  0 张照片亦有锁可加(补首张并发缺口);UserPhotoMapper 计数方法同步替换。
- FF-LIVENESS-003 + canonical 持久化:FeatureFlagPersistenceGuardTest +4
  (canonical 加载 / 遗留别名读兼容 / PUT 落 canonical 键 / 切换即生效无旧缓存)、
  FeatureFlagControllerTest +3(canonical/legacy/reset)。
- 文档同步:AGENTS.md 规则 27(配置治理纪律);docs/governance/known-risks.md
  (7 项含本机 WSL/Docker 故障 KR-07);config-register / open-questions 更新 canonical 口径;
  STATUS rc.21 行补 ⑥⑦⑧。

全量回归 741/0/0/3(基线 717 + 25 新增 − 1 删死测试,宿主机 JDK21+Maven 3.9.9 实测,
本机 WSL/Docker 引擎故障期间);UI 契约门禁 18/18
2026-09-21 11:13:14 +08:00
WorkBuddy 438b38d121 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
2026-09-21 02:05:15 +08:00