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:
@@ -111,7 +111,7 @@ if (!existsSync(resolve(root, prodComposePath))) {
|
||||
// 不直接写 /ports:\s*\n\s*-\s*"/ —— 端口上方允许有注释行,那样会匹配不到并让守卫误判为失效。
|
||||
const prodCompose = read(prodComposePath)
|
||||
const prodAdminBlock = prodCompose.match(
|
||||
/container_name:\s*danyang-match-admin\n([\s\S]*?)(?=\n {2}[a-z]|$)/,
|
||||
/container_name:\s*danyang-match-admin\r?\n([\s\S]*?)(?=\r?\n {2}[a-z]|$)/,
|
||||
)?.[1]
|
||||
assert.ok(prodAdminBlock, '未能从 docker-compose.prod.yml 切出 admin-web 服务块(守卫自身失效)')
|
||||
const prodAdminMapping = prodAdminBlock.match(/-\s*"([^"]+)"/)?.[1]
|
||||
@@ -130,8 +130,13 @@ if (!existsSync(resolve(root, prodComposePath))) {
|
||||
// 端口改了、脚本没同步,不会有任何检查变红。现该变量已接到实测的管理端可达性检查上,
|
||||
// 这里再用门控保证它与 staging compose 的发布端口一致 —— 否则实测会稳定地测错对象。
|
||||
const stagingCompose = read('infrastructure/docker-compose.staging.yml')
|
||||
// 行尾必须容忍 CRLF —— 本仓库同时存在两种行尾(staging.yml / run-uat.sh 是 CRLF,
|
||||
// prod.yml 是 LF),而 prod 那段在 CI 上因文件被 gitignore 根本不执行,
|
||||
// 所以只有 staging 这段会在 Windows 工作区暴雷。若写死 \n:
|
||||
// 窗口内夹了 \r 后解析直接失败,守卫会报「自身失效」——
|
||||
// 那是**假红**(真实端口 13521 与 run-uat.sh 一致),比不检查更坏。
|
||||
const stagingAdminMapping = stagingCompose
|
||||
.match(/container_name:\s*danyang-match-staging-admin\n([\s\S]*?)(?=\n {2}[a-z]|$)/)?.[1]
|
||||
.match(/container_name:\s*danyang-match-staging-admin\r?\n([\s\S]*?)(?=\r?\n {2}[a-z]|$)/)?.[1]
|
||||
?.match(/-\s*"([^"]+)"/)?.[1]
|
||||
assert.ok(stagingAdminMapping, '未能从 docker-compose.staging.yml 的 admin-web 解析出端口映射(守卫自身失效)')
|
||||
const stagingAdminPort = stagingAdminMapping.split(':').at(-2)
|
||||
|
||||
Reference in New Issue
Block a user