532 lines
14 KiB
Markdown
532 lines
14 KiB
Markdown
# 规则域多租户方案 A 实施计划
|
||
|
||
> 适用范围:`leaudit-platform` 新平台规则配置、评查组、规则版本、评查运行结果链路
|
||
> 方案结论:采用 `方案 A = 共享业务树 + 租户规则绑定 + 租户结果快照`
|
||
> 更新日期:2026-05-21
|
||
> 文档定位:把“规则域如何接入多租户”从概念方案落成可执行的修改计划,作为后续开发、联调、数据库迁移、验收的统一基线。
|
||
|
||
---
|
||
|
||
## 1. 定案结论
|
||
|
||
规则域本轮正式采用 `方案 A`,不直接做“每租户独立整棵业务树”,也不在第一阶段引入“租户扩展节点”。
|
||
|
||
当前统一口径如下:
|
||
|
||
1. `leaudit_evaluation_point_groups` 继续作为共享业务树
|
||
2. 租户差异主要放在:
|
||
- `leaudit_rule_sets`
|
||
- `leaudit_rule_versions`
|
||
- `leaudit_rule_group_bindings`
|
||
- `leaudit_audit_runs`
|
||
- `leaudit_rule_results / leaudit_run_errors / leaudit_run_metrics`
|
||
3. 运行时规则生效顺序固定为:
|
||
- `TENANT`
|
||
- `PROVINCIAL`
|
||
- `PUBLIC`
|
||
4. `tenant_code` 是唯一真实租户边界
|
||
5. `tenant_name` 只做展示与快照
|
||
6. `area / region / default / 公共 / 省级` 只允许留在兼容层与历史清洗层
|
||
|
||
---
|
||
|
||
## 2. 当前问题复盘
|
||
|
||
规则域目前不是“功能不可用”,而是“资产归属模型仍是全局共享思路”,因此天然不满足真正多租户隔离。
|
||
|
||
当前高风险点如下:
|
||
|
||
1. `leaudit_rule_sets` 仍缺 `tenant_code`
|
||
2. `leaudit_rule_versions` 仍缺租户快照
|
||
3. `leaudit_rule_group_bindings` 仍缺租户边界
|
||
4. `leaudit_audit_runs` 仍缺租户快照,导致结果链条没有稳定归属锚点
|
||
5. `leaudit_rule_results / leaudit_run_errors / leaudit_run_metrics` 只能靠 `run_id` 间接推断租户
|
||
6. `auditServiceImpl` 运行时按 `group_id` 取规则,但没有按租户选“当前生效规则”
|
||
7. `ruleServiceImpl` 仍以全局 `rule_type -> rule_set` 为主语义
|
||
|
||
这意味着:
|
||
|
||
1. 不同租户可能共用同一个规则集与版本链
|
||
2. 一个租户发布的新版本,可能直接影响另一个租户的运行结果
|
||
3. 规则结果报表、失败诊断、运行统计无法稳定按租户回溯
|
||
|
||
---
|
||
|
||
## 3. 方案 A 的边界定义
|
||
|
||
## 3.1 保持共享的部分
|
||
|
||
以下内容第一阶段继续共享:
|
||
|
||
1. 业务树:`leaudit_evaluation_point_groups`
|
||
2. 文档类型:`leaudit_document_types`
|
||
3. 入口模块与业务树的主挂载关系
|
||
|
||
共享的含义不是“不做租户控制”,而是:
|
||
|
||
1. 树结构本身平台统一维护
|
||
2. 哪些租户能看到哪些入口/业务节点,由可见性控制解决
|
||
3. 某业务节点下到底生效哪套规则,由租户绑定解决
|
||
|
||
## 3.2 租户化的部分
|
||
|
||
以下内容必须 tenant-first:
|
||
|
||
1. 规则集归属
|
||
2. 规则版本归属
|
||
3. 业务组到规则集的绑定关系
|
||
4. 评查运行记录
|
||
5. 评查结果、错误、指标等衍生记录
|
||
|
||
## 3.3 暂不纳入第一阶段的部分
|
||
|
||
本轮明确不做:
|
||
|
||
1. 每租户复制整棵业务树
|
||
2. 租户自定义树层级结构
|
||
3. 树节点级继承编辑器
|
||
4. 租户扩展节点能力
|
||
|
||
这些能力只预留扩展位,不进入本轮交付范围。
|
||
|
||
---
|
||
|
||
## 4. 目标架构
|
||
|
||
规则域的目标链路收口为:
|
||
|
||
`文档(tenant_code) -> 共享业务树 group -> 按 tenant_code 解析生效 binding -> 命中 tenant/provincial/public 规则集 -> 锁定规则版本 -> 创建带租户快照的 audit_run -> 结果/错误/指标带租户快照落库`
|
||
|
||
核心设计点:
|
||
|
||
1. 业务树是“分类锚点”
|
||
2. 规则绑定是“租户差异入口”
|
||
3. `audit_run` 是“历史快照锚点”
|
||
4. 结果表是“查询与报表加速层”,不再只靠运行时 join 推断租户
|
||
|
||
---
|
||
|
||
## 5. 数据模型修改计划
|
||
|
||
## 5.1 `leaudit_rule_sets`
|
||
|
||
### 新增字段
|
||
|
||
1. `tenant_code VARCHAR(64) NULL`
|
||
2. `scope_type VARCHAR(32) NOT NULL DEFAULT 'PROVINCIAL'`
|
||
3. `source_rule_set_id BIGINT NULL`
|
||
4. `tenant_name_snapshot VARCHAR(255) NULL`
|
||
|
||
### 约束与索引
|
||
|
||
1. 索引:`idx_leaudit_rule_sets_tenant_code`
|
||
2. 索引:`idx_leaudit_rule_sets_scope_type`
|
||
3. 唯一索引建议调整为:
|
||
- `tenant_code + rule_type + deleted_at IS NULL`
|
||
- 或 `COALESCE(tenant_code, '') + rule_type + deleted_at IS NULL`
|
||
|
||
### 语义
|
||
|
||
1. `TENANT`:租户私有规则集
|
||
2. `PROVINCIAL`:省级统一治理规则集
|
||
3. `PUBLIC`:真正公共资源域规则集
|
||
4. `source_rule_set_id`:租户规则集如果来自省级继承/复制,记录来源
|
||
|
||
## 5.2 `leaudit_rule_versions`
|
||
|
||
### 新增字段
|
||
|
||
1. `tenant_code_snapshot VARCHAR(64) NULL`
|
||
2. `scope_type_snapshot VARCHAR(32) NULL`
|
||
3. `source_version_id BIGINT NULL`
|
||
|
||
### 原则
|
||
|
||
1. 版本归属以创建时快照固化
|
||
2. 不允许完全依赖 join `rule_set` 才知道版本属于谁
|
||
|
||
## 5.3 `leaudit_rule_group_bindings`
|
||
|
||
### 新增字段
|
||
|
||
1. `tenant_code VARCHAR(64) NULL`
|
||
2. `scope_type VARCHAR(32) NOT NULL DEFAULT 'PROVINCIAL'`
|
||
3. `tenant_name_snapshot VARCHAR(255) NULL`
|
||
|
||
### 索引与约束
|
||
|
||
1. 索引:`idx_leaudit_rule_group_bindings_group_tenant`
|
||
2. 索引:`idx_leaudit_rule_group_bindings_scope_type`
|
||
3. 唯一索引调整为:
|
||
- `group_id + rule_set_id + COALESCE(tenant_code, '') + deleted_at IS NULL`
|
||
|
||
### 语义
|
||
|
||
同一个 `group_id` 可以同时存在:
|
||
|
||
1. 一个租户私有绑定
|
||
2. 一个省级绑定
|
||
3. 一个公共绑定
|
||
|
||
运行时按优先级解析,不再只看 `priority`。
|
||
|
||
## 5.4 `leaudit_rule_type_bindings`
|
||
|
||
### 第一阶段处理原则
|
||
|
||
1. 不再作为新主链路真相来源
|
||
2. 补 `tenant_code / scope_type` 仅用于兼容老接口与迁移脚本
|
||
3. 新平台运行与配置以 `leaudit_rule_group_bindings` 为准
|
||
|
||
## 5.5 `leaudit_audit_runs`
|
||
|
||
### 必补字段
|
||
|
||
1. `tenant_code VARCHAR(64) NULL`
|
||
2. `tenant_name_snapshot VARCHAR(255) NULL`
|
||
3. `scope_type_snapshot VARCHAR(32) NULL`
|
||
4. `group_id_snapshot BIGINT NULL`
|
||
5. `rule_binding_id_snapshot BIGINT NULL`
|
||
|
||
### 原因
|
||
|
||
`audit_run` 是整个历史追溯的锚点。
|
||
没有这层快照,后续规则换绑、租户改名、共享域清洗后,历史运行会失去稳定归属。
|
||
|
||
## 5.6 `leaudit_rule_results`
|
||
|
||
### 建议新增字段
|
||
|
||
1. `tenant_code VARCHAR(64) NULL`
|
||
2. `tenant_name_snapshot VARCHAR(255) NULL`
|
||
|
||
### 原则
|
||
|
||
虽然可以通过 `run_id` 反查,但结果表是高频列表、导出、统计来源,补快照能避免后续大量 join。
|
||
|
||
## 5.7 `leaudit_run_errors`
|
||
|
||
### 建议新增字段
|
||
|
||
1. `tenant_code VARCHAR(64) NULL`
|
||
2. `tenant_name_snapshot VARCHAR(255) NULL`
|
||
|
||
## 5.8 `leaudit_run_metrics`
|
||
|
||
### 建议新增字段
|
||
|
||
1. `tenant_code VARCHAR(64) NULL`
|
||
|
||
---
|
||
|
||
## 6. 历史数据回填策略
|
||
|
||
## 6.1 回填总原则
|
||
|
||
1. 现有规则资产默认回填为 `PROVINCIAL`
|
||
2. 不把现有全局规则直接回填成 `PUBLIC`
|
||
3. 历史 `region/default/公共/省级` 只作为映射依据,不作为新模型长期值
|
||
|
||
## 6.2 回填顺序
|
||
|
||
1. 先补字段与索引
|
||
2. 再给 `rule_sets / rule_versions / group_bindings` 回填省级归属
|
||
3. 再给 `audit_runs` 补租户快照
|
||
4. 最后给 `rule_results / run_errors / run_metrics` 做快照回填
|
||
|
||
## 6.3 回填映射口径
|
||
|
||
1. 原来全局共享规则集:回填 `tenant_code='PROVINCIAL'`
|
||
2. 原来 `default / 省级 / 省局`:统一映射到 `PROVINCIAL`
|
||
3. 原来真正公共资源:才回填 `PUBLIC`
|
||
|
||
---
|
||
|
||
## 7. 运行时解析修改计划
|
||
|
||
## 7.1 目标规则
|
||
|
||
运行时解析“某文档某分组到底用哪套规则”时,必须以文档 `tenant_code` 为第一主语义。
|
||
|
||
## 7.2 生效顺序
|
||
|
||
固定解析顺序:
|
||
|
||
1. 精确租户:`tenant_code = document.tenant_code`
|
||
2. 省级继承:`tenant_code = 'PROVINCIAL'`
|
||
3. 公共继承:`tenant_code = 'PUBLIC'`
|
||
|
||
即:
|
||
|
||
`TENANT -> PROVINCIAL -> PUBLIC`
|
||
|
||
## 7.3 修改点
|
||
|
||
文件:
|
||
|
||
- [auditServiceImpl.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/services/impl/auditServiceImpl.py)
|
||
|
||
需要改造:
|
||
|
||
1. `_resolve_rule_binding_from_group`
|
||
2. `_resolve_unique_group_binding_by_doc_type`
|
||
3. `Run`
|
||
|
||
目标:
|
||
|
||
1. 查询绑定时显式带入 `tenant_code`
|
||
2. 绑定结果返回:
|
||
- `binding_id`
|
||
- `binding tenant_code`
|
||
- `binding scope_type`
|
||
- `rule_set tenant_code`
|
||
3. 创建 `audit_run` 时直接写入租户快照与绑定快照
|
||
|
||
---
|
||
|
||
## 8. 后端改造任务拆分
|
||
|
||
## 8.1 `R1` 数据库迁移脚本
|
||
|
||
涉及:
|
||
|
||
1. 新增一套规则域迁移 SQL
|
||
2. 新增预检 SQL
|
||
3. 新增回填验证 SQL
|
||
|
||
建议文件:
|
||
|
||
1. `scripts/创建sql/schema_rule_domain_tenant_phase1.sql`
|
||
2. `scripts/创建sql/precheck_rule_domain_tenant_phase1.sql`
|
||
3. `scripts/创建sql/verify_rule_domain_tenant_phase1.sql`
|
||
|
||
交付目标:
|
||
|
||
1. 字段补齐
|
||
2. 索引补齐
|
||
3. 历史数据回填
|
||
4. 验证 SQL 可重复执行
|
||
|
||
## 8.2 `R2` 规则资产服务租户化
|
||
|
||
涉及文件:
|
||
|
||
1. [ruleServiceImpl.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/services/impl/ruleServiceImpl.py)
|
||
2. [ruleController.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/controllers/ruleController.py)
|
||
|
||
改造范围:
|
||
|
||
1. `ListSets`
|
||
2. `GetVersions`
|
||
3. `GetContent`
|
||
4. `CreateVersion`
|
||
5. `PublishRuleVersion`
|
||
6. `RollbackRuleVersion`
|
||
|
||
目标:
|
||
|
||
1. 规则集列表按当前租户 + 继承层展示
|
||
2. 创建新版本时,不再按全局 `rule_type` 命中资产
|
||
3. 发布/回滚只影响当前租户生效链
|
||
|
||
## 8.3 `R3` 业务组绑定租户化
|
||
|
||
涉及文件:
|
||
|
||
1. [evaluationPointGroupServiceImpl.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/services/impl/evaluationPointGroupServiceImpl.py)
|
||
2. [ruleGroupSupport.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/services/impl/ruleGroupSupport.py)
|
||
|
||
改造范围:
|
||
|
||
1. `ListBindings`
|
||
2. `CreateBinding`
|
||
3. `UpdateBinding`
|
||
4. `DeleteBinding`
|
||
5. `GetRuleTemplate`
|
||
6. `CreateRuleDraft`
|
||
|
||
目标:
|
||
|
||
1. 绑定表支持租户归属
|
||
2. 同组可见绑定区分:
|
||
- 本租户
|
||
- 继承省级
|
||
- 继承公共
|
||
3. 后台页面能识别“当前生效绑定来自哪里”
|
||
|
||
## 8.4 `R4` 运行链路租户化
|
||
|
||
涉及文件:
|
||
|
||
1. [auditServiceImpl.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/services/impl/auditServiceImpl.py)
|
||
2. [storage_adapter.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/leaudit_bridge/storage_adapter.py)
|
||
|
||
改造范围:
|
||
|
||
1. 运行时选规则
|
||
2. 创建 `audit_run`
|
||
3. 结果、错误、指标落库
|
||
|
||
目标:
|
||
|
||
1. 运行链路 tenant-first
|
||
2. 所有衍生记录带租户快照
|
||
3. 后续报表不再依赖复杂 join 推断
|
||
|
||
## 8.5 `R5` 规则配置页聚合租户化
|
||
|
||
涉及文件:
|
||
|
||
1. [ruleConfigServiceImpl.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/services/impl/ruleConfigServiceImpl.py)
|
||
|
||
目标:
|
||
|
||
1. `ListPackSummaries` 与 `GetPack` 按当前租户解析生效规则
|
||
2. 返回新增标准字段:
|
||
- `effectiveTenantCode`
|
||
- `effectiveScopeType`
|
||
- `isInherited`
|
||
- `sourceRuleSetId`
|
||
3. 页面能区分:
|
||
- 本租户私有规则
|
||
- 继承省级规则
|
||
- 继承公共规则
|
||
|
||
## 8.6 `R6` 鉴权与权限补齐
|
||
|
||
涉及文件:
|
||
|
||
1. [ruleController.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/controllers/ruleController.py)
|
||
2. [ruleConfigController.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/controllers/ruleConfigController.py)
|
||
3. [evaluationPointGroupController.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/controllers/evaluationPointGroupController.py)
|
||
|
||
目标:
|
||
|
||
1. 所有规则域接口强制登录态
|
||
2. 功能权限校验与租户上下文透传统一化
|
||
3. 杜绝“裸接口 + 全局资产”的组合风险
|
||
|
||
---
|
||
|
||
## 9. 前端改造计划
|
||
|
||
## 9.1 规则配置页
|
||
|
||
目标:
|
||
|
||
1. 展示当前规则来源
|
||
2. 展示当前租户是否继承上层规则
|
||
3. 发布/回滚操作前明确告知影响范围
|
||
|
||
应补能力:
|
||
|
||
1. “当前生效租户域”标签
|
||
2. “继承来源”标签
|
||
3. “复制省级为租户私有规则”入口
|
||
|
||
## 9.2 评查组管理页
|
||
|
||
目标:
|
||
|
||
1. 共享业务树继续展示
|
||
2. 绑定列表显式展示租户域
|
||
3. 避免让用户误以为业务树已经按租户独立
|
||
|
||
## 9.3 历史兼容口径
|
||
|
||
前端主模型不再依赖:
|
||
|
||
1. `region`
|
||
2. `default`
|
||
3. 中文共享常量
|
||
|
||
前端应统一消费:
|
||
|
||
1. `tenant_code`
|
||
2. `tenant_name`
|
||
3. `scope_type`
|
||
4. `isInherited`
|
||
|
||
---
|
||
|
||
## 10. 验收矩阵
|
||
|
||
## 10.1 规则资产
|
||
|
||
1. 租户 A 创建规则版本,不影响租户 B 当前规则
|
||
2. 省级发布规则,未覆盖的租户自动继承
|
||
3. 已有租户私有规则的组,不再被省级发布直接覆盖
|
||
|
||
## 10.2 运行链路
|
||
|
||
1. 梅州文档运行时优先命中 `MZ`
|
||
2. `MZ` 无绑定时回退 `PROVINCIAL`
|
||
3. `PROVINCIAL` 无绑定时回退 `PUBLIC`
|
||
4. `audit_run` 落库后可直接看到租户快照
|
||
|
||
## 10.3 结果与报表
|
||
|
||
1. `rule_results` 可直接按 `tenant_code` 过滤
|
||
2. `run_errors` 可直接按 `tenant_code` 过滤
|
||
3. `run_metrics` 可直接按 `tenant_code` 聚合
|
||
|
||
## 10.4 页面行为
|
||
|
||
1. 规则配置页能显示“本租户规则 / 继承省级 / 继承公共”
|
||
2. 评查组绑定页能正确显示当前生效规则来源
|
||
3. 非当前租户用户不能修改本租户规则资产
|
||
|
||
---
|
||
|
||
## 11. 执行顺序
|
||
|
||
建议按下面顺序推进,不再交叉大爆改:
|
||
|
||
1. `R1` 数据库迁移脚本
|
||
2. `R4` 运行链路租户化
|
||
3. `R2` 规则资产服务租户化
|
||
4. `R3` 业务组绑定租户化
|
||
5. `R5` 规则配置页聚合租户化
|
||
6. `R6` 鉴权与权限补齐
|
||
7. 前端联调与发布级验收
|
||
|
||
执行原则:
|
||
|
||
1. 先补“数据真相字段”
|
||
2. 再改“运行时生效逻辑”
|
||
3. 最后改“后台配置与页面展示”
|
||
|
||
---
|
||
|
||
## 12. 风险与边界
|
||
|
||
## 12.1 高风险
|
||
|
||
1. `rule_type` 当前可能被多处假定为全局唯一
|
||
2. 历史运行结果回填需要保证与旧 `document.tenant_code` 一致
|
||
3. 省级与公共域清洗口径必须先定死,不能一边跑一边改
|
||
|
||
## 12.2 中风险
|
||
|
||
1. 前端若仍只展示“当前绑定”,用户会误判租户隔离是否生效
|
||
2. `rule_type_bindings` 老兼容链路如果不断回写,容易污染新模型
|
||
|
||
## 12.3 本轮不做
|
||
|
||
1. 不做租户扩展节点
|
||
2. 不做独立业务树
|
||
3. 不做历史规则资产自动差异合并
|
||
|
||
---
|
||
|
||
## 13. 最终交付定义
|
||
|
||
当以下 6 条同时满足时,规则域多租户方案 A 才算真正落地:
|
||
|
||
1. 规则集、规则版本、组绑定都有稳定 `tenant_code`
|
||
2. 运行时规则解析已改为 `TENANT -> PROVINCIAL -> PUBLIC`
|
||
3. `audit_run` 已带完整租户快照
|
||
4. `rule_results / run_errors / run_metrics` 已能直接按租户查询
|
||
5. 规则配置页能明确展示当前规则来源与继承关系
|
||
6. 发布级验收已证明不同租户互不串规则、互不串结果
|