一、机构审计归属缺陷(本轮活栈验收中新发现) - 现象: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)。
14 KiB
项目进度评估报告 — 2026-09-21
评估方式:以
docs/STATUS.md(权威状态表)为索引,逐项回溯代码、迁移、测试与 CI 配置实测复核, 不采信文档中的历史「✅」声明。凡本文标注「实测」的结论均可按「核查证据」栏复现。评估基线:
main@60c591f(2026-09-21 11:13),工作区干净;最新 tagv101-dod-complete-2026-09-21。
一、总体结论
代码与测试面已具备进入 UAT 的条件;阻塞点是人工确认与环境补绿,外加一处此前登记但未修复的运营端写操作缺陷。
| 维度 | 结论 |
|---|---|
| 业务功能 | Phase 01 |
| 质量门禁 | 后端 741 / 0 失败 / 0 错误 / 3 跳过;UI 契约门禁 18/18;E2E 本机活栈 65 通过 |
| 数据层 | 迁移 V001~V051(51 个文件,无缺号);H2 测试库表漂移盲区已在本轮前多轮补齐 |
| 停点 | Phase 24(UAT)启动门前 —— 按项目规则须由用户确认,不得自动进入 |
| 风险等级 | 中 —— 无架构级问题,但存在 1 项 High 未修缺陷 + 2 项环境/流程阻塞 |
二、进度快照
2.1 Phase 矩阵
| Phase 区间 | 状态 | 证据 |
|---|---|---|
| 01~06 基线 / Auth / RBAC / Profile / 审核 / Match Engine | ✅ 关闭 | 各 Phase Completion Report |
| 07 V1.1 首页 + 找对象 | ✅ 关闭 | 2026-09-16 用户验收(基本达标);11 页 UI 验收通过 |
| 08~13A Like/Match/Block · Chat · 图片安全 · 通知 · 关系扩展 · 红娘转介 · 咨询辅导 | ✅ 关闭 | 2026-09-16/17 KEEP-VERIFY,共修复 40+ 真实缺陷 |
| 14~20 多类型活动 · 报名签到 · 互选双确认 · 举报风控 · 申诉 · 运营后台 · Analytics | ✅ 关闭 | 2026-09-17 复验,修复 60+ 缺陷(含 4 处必崩级) |
| 21 账户生命周期 | ✅ 关闭 | 2026-09-18;注销三处 TODO 桩已实现;数据保留流程 V049 落地 |
| 22 Feature Flag | ✅ 关闭 | 死配置已移除;PUT /feature-flags 真持久化(V048) |
| 23 可信系统测试重建 | ⚠️ 部分关闭 | 假覆盖归零、E2E 场景真实实现;仅余 CI 上首次跑绿 |
| 23B E2E 基建 + 横向加固(HTTP 语义 / 身份收敛 / 幂等键) | ✅ 关闭 | 幂等键 30 端点、105 处真实状态码 |
| V1.0.1 配置与规则纠偏 | ✅ 关闭 | rc.21(2026-09-21);governance 六表 + 并发强校验 + canonical key |
| 24 UAT | ⏳ 待启动 | 用例 46 条(9 角色 × 7 路径)已编写;需用户确认 |
| 25 RC 内容 / 26 生产 Smoke | ⏳ 待运营 | 真实素材未提供;13 项 smoke 待执行 |
2.2 量化指标
| 指标 | 实测值 | 核查方式 |
|---|---|---|
| 后端测试 | 741 / 0 failures / 0 errors / 3 skipped | docs/STATUS.md rc.21 行(离线容器 mvn -o test,命令见计划附 B-9) |
| 测试类文件 | 108 个 | backend/src/test/**/*.java 计数 |
| UI 契约门禁 | 18/18(UI_GUARDS_MIN 下限守卫防删除报绿) |
ui-tests/ 18 个 .mjs;执行器 scripts/run-ui-contracts.mjs |
| E2E 用例 | 65 通过(本机真栈真库) | tests/e2e/ 14 个测试文件 |
| 数据库迁移 | V001~V051,51 个,无缺号重复 | backend/src/main/resources/db/migration |
| CI job | 7 个:backend / admin-web / miniapp / migration / test-shell-guard / ui-contracts / e2e | .github/workflows/ci.yml |
| 待产品决策 | 13 项 + 第三方开放遗留 7 项 | docs/PENDING_DECISIONS.md、docs/governance/open-questions.md |
三、关键发现:一处 High 缺陷登记后未修复
3.1 机构创建 / 停用 / 启用三个写操作必然失败(High,2026-09-22 已验证关闭)
处置完成(2026-09-22 复核):本项已按第五节 P0-1 执行完毕 ——
Constants新增ORG_STATUS_ACTIVE/INACTIVE、三处状态值修正、type白名单前置校验、 测试库schema-h2.sql补两条 CHECK 及 NOT NULL/DEFAULT、 新增OrganizationConstraintParityTest与OrganizationServiceTest。2026-09-22 完成全部补跑验证(此前记为「已修复待验证」的缺口已补齐):
- 全量回归 757 / 0 / 0 / 3,BUILD SUCCESS(108 个测试类,6:44;基线 741 + 新增 16 = 757);
- 负向注入可红:把
Constants.ORG_STATUS_ACTIVE改回"normal"后,16 个用例变 3 失败 + 7 错误 —— 守卫backendWhitelistsMatchProductionDdl/orgStatusConstantsCoverProductionWhitelist/orgStatusMustNotReuseAccountStatusValues三条断言各自命中该误用,服务侧 7 例被 H2CHK_ORG_STATUS拦下。注入采用 仓库只读挂载 + 容器内副本改写,工作区哈希前后一致(28aaaedb…),源码零污染;- 活栈实测(Docker 全栈):创建 / 停用 / 启用全部 2xx 且落库为
active/inactive, 非法type与缺字段 400VALIDATION_ERROR,不存在机构 404NOT_FOUND, 全流程零 5xx(15/15 通过);- 对已部署栈跑
pytest tests/e2e:65 passed。本项状态:已验证关闭。 另:活栈验收中新发现同族缺陷「创建机构审计缺操作人」——
CREATE_ORGANIZATION审计行operator_id7/7 为 NULL(停用/启用却正确记录),已一并修复并复验,见docs/STATUS.mdrc.23。
该问题于 2026-09-19 已在实施计划「附 B.1」中登记并实测复现,但截至本次评估(2026-09-21)代码未改动。
缺陷本体(实测复核,2026-09-21):
| 位置 | 写入值 | 生产约束 | 结果 |
|---|---|---|---|
OrganizationService.java:43 createOrganization |
ACCOUNT_STATUS_NORMAL = "normal" |
V001:45 chk_org_status CHECK (status IN ('active','inactive')) |
违约 → 500 |
OrganizationService.java:63 disableOrganization |
ACCOUNT_STATUS_SUSPENDED = "suspended" |
同上 | 违约 → 500 |
OrganizationService.java:73 enableOrganization |
ACCOUNT_STATUS_NORMAL = "normal" |
同上 | 违约 → 500 |
根因:organizations.status 复用了语义上属于 users 表的常量 Constants.ACCOUNT_STATUS_*。
Constants 中不存在机构状态常量(ORG_STATUS_ACTIVE/INACTIVE 均无)—— 典型的「跨表常量误用」,
与项目此前多轮修复的「实体↔迁移漂移」「CHECK 白名单未对齐」同族。
二阶影响(决定优先级):
activities.organizer_org_id 为 NOT NULL → 无机构则无法创建活动。
即运营端「新建机构 → 新建活动 → 用户报名 → 互选」这条链路的第一环是断的。
而 UAT 用例覆盖活动互选、报名、签到等场景,因此该缺陷可能阻塞 UAT 执行。
为什么门禁全绿却没发现:
- 108 个测试类中没有任何一个引用
OrganizationService/createOrganization(实测:0 命中); tests/e2e/sql/seed_e2e_activity.sql是直接写库插入机构与活动,绕过了 Service 层 —— E2E 全绿掩盖了 API 路径的失败;- H2 测试库此前长期缺约束复刻,即便有测试也可能静默通过。
这正好复现项目已总结过两次的模式:「测试环境用数据为空 / 直连绕过,掩盖代码必崩」。
附带问题(同文件,Low):
createOrganization与updateOrganization均未校验type白名单 (chk_org_type仅允许 women_federation / trade_union / charity_center / volunteer_team / civil_affairs_partner / other);- 私有
saveAuditLog未填ip/userAgent(Phase 17 只增强了AuditLogService.recordSensitiveAccess)。
建议修法:新增 Constants.ORG_STATUS_ACTIVE/INACTIVE,三处改为 active / inactive;
补 type 白名单校验;新增 OrganizationServiceTest(走真实 DB,覆盖创建/停用/启用/type 非法),
另加一条解析 V001 DDL 取最终白名单的常量守卫(参照 MatchmakerReferralPhase13Test 的写法,
不要硬编码白名单副本 —— 那条教训已记录在 Phase 13 报告中)。修复后需 git tag 打点并回读验证。
3.2 其余已登记未处置项
| 项 | 级别 | 说明 |
|---|---|---|
| 用户侧取消预约不校验状态 | Medium | ServiceAppointmentService.cancelAppointment 只校验归属,已确认/已完成也能被本人取消;运营侧明确拒绝 completed。两侧口径不一致,需产品裁定(计划附 B.3) |
| Phase 22 Deployment/Ops 5 项未复验 | Medium | 删除镜像跳过测试的发布路径、生产关 Mock/Seed/Swagger、端口依赖检测、备份加密 + 真实恢复演练、Rollback 目标(REMAINING_WORK.md B 组) |
| 多实例下 flag 内存值不自动刷新 | Low | 已知边界,需各自重启(Phase 22 报告) |
四、环境与流程风险
4.1 Git 在当前执行环境不可用(阻塞提交纪律)
实测:git 报 fatal: detected dubious ownership in repository。
仓库目录属主为 S-1-5-21-881075190-…,当前用户为 CLIMBER/13070,二者不匹配。
影响:AGENTS.md 的版本控制约定(每批独立 commit + 单段名 tag + git bundle 自保 + 回读验证)
是项目防御「常驻进程删 refs 导致 HEAD 悬空」的核心手段,该链路当前无法执行。
本次评估为只读目的,以 GIT_CONFIG_COUNT/KEY/VALUE 环境变量临时注入 safe.directory 绕过,
未修改任何全局配置。
建议:由用户决定是否执行
git config --global --add safe.directory 'E:/develop/公益婚恋服务平台'。
在修复前,任何需要提交的工作都应先确认该前提,否则改动无法被打点保护。
(另:feat-ui-v11 已被 main 完全包含(落后 71 个提交、领先 0),仅为冗余锚点,
可考虑清理,但 AGENTS.md 目前要求保留 —— 属文档与事实的轻微不一致。)
4.2 CI 回归防线从未在真实 CI 上验证过
7 个 job 均已配置,其中 ui-contracts(18 门禁)与 e2e(Compose 起全栈 + seed + pytest)配置完整,
但 E2E 作业从未在 GitHub Actions 上跑绿过一次(计划 Task 2.3 Step 3)。
本机已用同一序列模拟实测 65/65,但「本机绿」与「CI 绿」不是同一件事
—— 此前已发生过「本机有遗留 admin 账号所以本地一直绿、CI 全新库必然 401」的先例。
4.3 文档体量与自相矛盾
docs/ 91 个文件、STATUS.md 单文件 90KB,内含多处「历史声明块(已作废)」并列保留;
PENDING_DECISIONS.md 与 docs/governance/* 三表职责交叉并依赖「矛盾以 governance 三表为准」的约定;
REMAINING_WORK.md 被迫以「原编号索引」兼容历史引用。
这是治理的必要代价,但已产生实际成本:文档中出现过与实际严重不符的陈述
(如 CHANGELOG.md 3.3MB vs 实际 4.2KB、指向从未存在的报告文件)。
建议:不再新增并列的「状态类」文档;本评估报告即为一次性快照,结论应回写进 STATUS.md 而非另立体系。
五、下一步建议
优先级 P0 — 建议立即做(无需用户决策,纯技术清偿)
- 修复机构三个写操作 + 补测试与守卫(3.1)。✅ 已修复且已通过全部验收项(2026-09-22):
全量回归 757 / 0 / 0 / 3 全绿;负向注入 16 例变 3 失败 + 7 错误(守卫三条断言全中 + H2
CHK_ORG_STATUS拦下 7 例); 活栈实测POST /operator/organizations与停用/启用均 2xx、非法输入 400、不存在 404、全程零 5xx(15/15); 对已部署栈pytest tests/e2e65 passed。本项关闭。 附带清偿同族缺陷「创建机构审计缺操作人」(见 rc.23)。 - 确认 Git 可用性(4.1)。决定是否加
safe.directory,否则先不要写代码 —— 写了也打不了点。
优先级 P1 — 需用户/环境配合
- 推送一次 CI,拿到 E2E 与 ui-contracts 的首次真绿(需有 Docker Hub 出口的 runner)。 完成后 Phase 23 可由「部分关闭」转为关闭。
- 管理端桌面端目视复验(1440px)(批 4 Task 4.1)。小程序 375px 增补页面同理。 这是当前唯一「代码已就绪但从未被真人看过」的验收项。
- 13 项产品决策 + 7 项第三方开放遗留(批 4 Task 4.2)。
建议分批:先决
OQ-MATCH-001(推荐阈值)、OQ-PROFILE-001(照片上限)、OQ-IDENTITY-001(活体核验)三项 —— 它们已被配置化,决策后只需改配置值; Banner 最大活跃数(OQ-BANNER-001)是真缺口,需产品定值后需实现 active-count 校验。
优先级 P2 — UAT 启动后的并行工作
- Phase 24(UAT)启动确认 —— 按项目规则须用户明确同意,AI 不得自动进入。 启动前建议先完成 P0-1 与 P1-4。
- Phase 22 Deployment/Ops 5 项复验,其中「备份加密 + 真实恢复演练」是上线硬门槛。
- 用户侧取消预约口径统一(3.2)—— 一次性产品裁定即可关闭。
优先级 P3 — 运营侧长周期
- Phase 25 真实素材(Banner / 课堂 / 反诈 / 关于我们 / 组织信息),不得 Seed 假数据。
- Phase 26 上线前 13 项 smoke + RC 冻结(镜像 / DB 版本 / 配置清单 / Rollback 目标)。
六、本次评估的核查证据
| 结论 | 证据 |
|---|---|
| 代码与测试就绪 | docs/STATUS.md 文首「当前有效结论」+ rc.19~rc.21 版本演进行 |
| 机构缺陷未修 | backend/src/main/java/com/danyang/match/platform/organization/service/OrganizationService.java:43,63,73;Constants.java:11,14;V001__init_base_tables.sql:45(三处逐一读源确认) |
| 机构零测试覆盖 | backend/src/test/** 全量检索 OrganizationService / createOrganization → 0 命中(108 个测试类) |
| E2E 绕过 Service 层 | tests/e2e/sql/seed_e2e_activity.sql 直插库 |
| CI 配置完整但未验证 | .github/workflows/ci.yml 全文;计划 Task 2.3 Step 3 仍为未勾选项 |
| Git 不可用 | git rev-parse HEAD 报 dubious ownership;属主 SID 与当前用户不一致 |
| 迁移基线 | db/migration 计数 51,最新 V051__canonical_liveness_flag_key.sql |
| 剩余项清单 | REMAINING_WORK.md、docs/PENDING_DECISIONS.md、计划「批 4 / 批 5」 |
评估人:WorkBuddy · 创建:2026-09-21
性质:一次性快照。结论请回写 docs/STATUS.md,本文件不作为长期状态源。