审计整改说明.md 7.43 KB

审计整改说明(对应 审计报告-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/OrderCreatedEventEngine.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 前端硬编码SceneFormschema.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 仅取 mastereventPayload 现 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 可伪造 / 无认证:坦诚标注为演示态 stubCommandController 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。