Files
leaudit-platform-backend/docs/权限与地区隔离/规则域多租户方案A实施计划.md

532 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 规则域多租户方案 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. 发布级验收已证明不同租户互不串规则、互不串结果