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)。
This commit is contained in:
WorkBuddy
2026-09-22 00:46:10 +08:00
parent c195133680
commit 8bd1ab804a
9 changed files with 111 additions and 31 deletions
@@ -523,11 +523,22 @@
> - **新增守卫**:`OrganizationConstraintParityTest`(生产 DDL ↔ 测试库 ↔ 后端白名单 ↔
> Constants 四方比对 + 解析器自检)、`OrganizationServiceTest`(走真实 DB,
> 9 个用例覆盖创建/停用/启用/往返/type 合法与非法/名称空白/404 语义)。
> - ⚠️ **未在本机运行测试**:2026-09-21 探测确认本机**无 Docker、无 JDK**,
> `wsl.exe` 被安全策略阻止(与 `known-risks.md` 的 WSL/Docker 故障一致),
> 故 `mvn -o test` 与负向注入**均未能执行**。已用等价正则的独立脚本验证
> 守卫机制判别力与两处 DDL 一致性(PASS,脚本留痕于 `.workbuddy/_verify_org_guard.py`)。
> **补跑全量回归 + 负向注入前,本项不得计入「已验证」。**
> - ✅ **2026-09-22 补跑验证完成(此前记为「待验证」,现关闭)**:
> ① **全量回归 757 / 0 / 0 / 3,BUILD SUCCESS**(108 个测试类,6:44;基线 741 + 新增 16 = 757);
> ② **负向注入可红**:把 `ORG_STATUS_ACTIVE` 改回 `"normal"` → 16 例变 **3 失败 + 7 错误**,
> 守卫三条断言(后端白名单 vs DDL / Constants vs 白名单 / 机构状态 vs 账号状态不相交)各自命中,
> 服务侧 7 例由 H2 `CHK_ORG_STATUS` 拦下。注入用**仓库只读挂载 + 容器内副本改写**,
> 工作区哈希前后一致,源码零污染(脚本 `.workbuddy/negative-injection.sh`);
> ③ **活栈实测**创建/停用/启用**全部 2xx**、非法 type 与缺字段 400、不存在 404、**零 5xx**(15/15);
> ④ 对已部署 Docker 栈 `pytest tests/e2e` → **65 passed**。
> - **2026-09-22 附带清偿同族缺陷:创建机构审计缺操作人**。活栈验收复核 `audit_logs` 发现
> `CREATE_ORGANIZATION` 的 `operator_id` **7/7 为 NULL**(而 `DISABLE/ENABLE_ORGANIZATION`
> 都正确记录了操作人)—— 控制器持有 `@AuthenticationPrincipal` 却未向 Service 透传,
> 审计不可归属等于无效审计。已改为 `createOrganization(params, principal.id())`,
> 并新增断言 `createOrganizationRecordsOperatorInAuditLog` 长期守卫。
> 修后复验:新写入的 7 条 CREATE 审计全部带 `operator_id`,旧 14 条仍为 NULL(前后对照清晰)。
> - ⚠️ **仍未处置(不在本轮范围)**:`AnalyticsService` 一处误用独立类
> `shared.exception.BusinessException`(该类无 `@ExceptionHandler`,抛出会退化为 500)。
2. **互选记录永不过期**(Medium,即批 3 Task 3.3 的 P16-T13)
`createMutualConsent` 从不写 `expires_at`(列无默认值),而
`confirmSideIfPending` 的过期闸门 `expires_at IS NULL OR expires_at > NOW()`