# 审计整改说明(对应 `审计报告-2026-07-20.md`) 本轮按"全面改造"口径整改。核心思路:**把散落在 Java/TS 里的业务字面量上移为可机器读的本体元数据**, 让引擎真正通用地解释执行。所有改动均加法、向后兼容。 ## 一、模型层新增的结构化元数据(加法) | 模型 | 新增字段 | 用途 | |---|---|---| | M1 | 属性 `constraints`(min/max/pattern/patternMessage) | 通用校验(取代中文子串匹配 + 硬编码字段) | | M2 | 命令 `commandType`(create/update/cancel) | 通用分派(取代"一律新建")| | M2 | 命令 `effect`(op/targetField/keyParam/amountParam/guardField) | 跨聚合副作用通用执行(取代硬编码扣库存)| | M2 | 命令 `derivations`(如 totalAmount=sum(quantity*itemPrice)) | 服务端重算(防 totalAmount 篡改)| | M2 | 新增 `StockReturn` 命令 | 取消订单回补库存(修正 ME 与语义相反)| | ME | 跨聚合规则 `sourceItemEntity` + `paramMap` | 通用组装目标命令入参(取代硬编码 productId/quantity)| | ME | 补齐 `OrderItemAdded/OrderPaymentTermSet/OrderDeliveryAddressSet/ProductStockReturned` | 修复 M2 引用了 ME 未定义的事件 | | M4 | 新增 `SCENE_CREATE_CUSTOMER` | 修复 M8 悬空绑定;顺带证明"第二个聚合/场景零代码可跑" | | M5 | 新增 `customer_create` 权限 | 配套客户场景 | ## 二、按发现的整改(A 级 32 条 / B 级 18 条) ### 铁律违背 → 全部改为模型驱动 - **A1/A13/A16/B8 跨聚合硬编码 StockDeduct/Product/stockNum/productId/OrderCreated**:`EventEngine.applyCrossConsistency` 现遍历**实际发出的事件**,按 ME `crossAggConsistencyRules` 匹配,用 M2 `effect` + `paramMap` **通用执行**任意增/减副作用;`CommandEngine` 不再传字面量 `"OrderCreated"`。 - **A2/A9/A10/A23 风控变量白名单 + customerLevel()/productStock() 专用方法**:删除这两个方法;`runRules` 现把 master/detail 全字段注入规则 env,并按 **M1 `refAggregate`** 通用解析被引用聚合属性(customerLevel、stockNum 自动可用)。新增引用其他字段的规则即生效。 - **A11/A12/A25 中文子串匹配 + 硬编码实体/字段校验**:删除;改由 **M1 `constraints`**(pattern/min/max)通用校验,遍历 master 与各子实体行。 - **A29 firstItemEntity/idPrefix "O for Order"**:删除 `firstItemEntity` 字面量兜底(改由 ME `sourceItemEntity` 指定);`idPrefix` 取聚合根名首字母(通用)。 - **A31 seed 硬编码 Customer/Product**:改为遍历 `seed-data.yaml` 的聚合 key 通用落库。 - **A7/A8/A16/A17/A21/A22/A28 前端硬编码**:`SceneForm` 用 `schema.sceneName` + `result.rootId`(后端新增稳定键 `rootId/rootIdField`);`TracePanel`/`OrdersEventsPanel` 列改由 `/api/meta/aggregate/{id}` 的 M1 属性与引擎通用动作形状驱动。 - **A19/A20 /orders/list 硬编码 OrderAggregate**:改为通用 `/api/data/{aggregateId}/list`;前端 `api.list(agg)`。 - **A30 前端默认场景硬编码**:改为取 `/meta/scenes` 首个 `hasTemplate` 场景。 - **EventEngine Outbox 表名硬编码**:改读 ME `outbox.table`。 ### 正确性 / 数据一致性 - **B1 超卖**:create 语义下,跨聚合动作任一非 OK(库存不足/不存在)→ `setRollbackOnly` 回滚整单,返回 `CONSISTENCY_FAILED`(已加测试:P002 库存8 下单100 → 失败且库存仍为8)。 - **A5 并发扣减竞争**:改为原子条件更新 `... SET col=col+? WHERE pk=? AND col+?>=0`,受影响 0 行即判不足。 - **A27 负数数量膨胀库存**:`effect` 执行拒绝 amount≤0;且 M1 `constraints.min=1` 在校验阶段拦截。 - **A4/B15/B16 非数字入 int/decimal / dueDays 绕过 / NULL 库存崩溃**:校验阶段按 M1 类型做数值可解析性校验(precheck 与 execute 同源);`readLong` 容错 NULL。 - **A6 reload 数据竞争**:`ModelRepository` 改为**不可变快照 + volatile 原子发布**,读取方永远看到完整旧/新快照。 - **A24 修改/取消被误当新建插入**:按 `commandType` 分派 create/update/cancel,不再对非新建命令插入新根。 - **A14/A32 ME OrderCancelled→StockDeduct 语义相反且从不触发**:新增 `StockReturn`(increment),ME 指向它;触发改为遍历实际事件,cancel 场景从库加载明细回补库存。 - **B18 事件 payload 仅取 master**:`eventPayload` 现 master 优先、其次子实体行查找。 - **B7 Map.of NPE**:改用可空 Map 组装(现由 paramMap 通用组装,容忍空值并 SKIP)。 ### 安全 - **A26 storageEncrypt 从未兑现**:新增 `EncryptService`(AES-GCM),落库前加密、读出后解密(M5 声明的字段)。**已加测试断言物理列为 `enc:` 密文**。 - **A15 totalAmount 客户端篡改**:M2 `derivations` 服务端按明细重算,喂给风控与落库。 - **B5 permitted 失败即放行**:改为 fail-closed(无 permissionBind 的场景默认拒绝)。 - **A3 X-Principal 可伪造 / 无认证**:坦诚标注为**演示态 stub**(`CommandController` Javadoc + README);热重载改为**仅管理员**(M8 dragRolePermission)可触发。*真正的 OAuth2/JWT 属生产接入项,见"仍为演示简化"。* - **B12 CORS 全放行**:改为按 profile 配置 `onto.cors.allowed-origins`,生产收紧为具体域名。 - **B11/B14 H2 控制台无鉴权 / 弱默认口令**:生产 profile 已禁用 H2 控制台;加密密钥与 CORS 域名在 prod profile 要求经环境/密管注入(文档强调)。 ### 模型完整性 - **B3 M8 绑定未定义的 SCENE_CREATE_CUSTOMER**:M4 补齐该场景 + M5 权限,客户模板变为可跑。 - **B4 M2 引用 ME 未定义事件**:ME 补齐三事件定义。 - **B9 控件不随 M1 type 变**:`FieldControl` 在 compType 为通用文本时按 M1 `fieldType`(int/decimal/boolean/datetime)升级控件,兑现"改 M1 type→控件变"。 ## 三、仍为演示简化(诚实标注,未在本轮做成生产级) - **真实认证(A3)**:未接入 Spring Security + OAuth2/JWT;`X-Principal` 仅演示 M5 权限分支。生产必须替换。 - **幂等(B2)**:未加请求幂等键;生产应加唯一约束去重表。 - **M0 JSON-Schema 强校验(B10)**:M0 仍为规范文档,未在加载时对各层做 Schema 校验(各层命名 snake_case 与 M0 Identifier 模式的历史不一致亦未强改)。 - 生产重组件(MySQL/RocketMQ/SkyWalking/Prometheus)仍以 `deploy/` docker-compose + 文档形式交付。 > **更新(补全 M8 后)**:M8 已补齐 `SCENE_CANCEL_ORDER`(订单取消模板)与 `SCENE_MODIFY_ORDER_ADDR`(收货地址修改模板)两套模板,四个场景全部可渲染。引擎相应把 `update` 命令做成**含子实体更新**(`updateChildByParent`,据 M3 定位子实体表按父外键更新),`cancel` 走通用 `StockReturn` 回补库存。已加测试:改地址断言子实体行被更新、取消断言库存回补。故原"update/cancel 子实体级修改未接线"一项已闭合。 ## 四、验证 - 后端 9 个 JUnit 全绿:schema 合成、有效下单(通用一致性)、大额 REJECT、约束校验、**超卖回滚**、负数数量拒绝、预检、**客户权限**、**手机号密文落库**。 - `tests/verify-model-change.sh`:改 MetaRule 阈值 + 热重载 → 同单通过↔拦截。 - 浏览器端到端:订单与客户两个场景均由 M8 动态渲染;执行追踪显示 derive/通用跨聚合动作/正确 topic。