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

14 KiB
Raw Blame History

规则域多租户方案 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 修改点

文件:

需要改造:

  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
  2. 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
  2. ruleGroupSupport.py

改造范围:

  1. ListBindings
  2. CreateBinding
  3. UpdateBinding
  4. DeleteBinding
  5. GetRuleTemplate
  6. CreateRuleDraft

目标:

  1. 绑定表支持租户归属
  2. 同组可见绑定区分:
    • 本租户
    • 继承省级
    • 继承公共
  3. 后台页面能识别“当前生效绑定来自哪里”

8.4 R4 运行链路租户化

涉及文件:

  1. auditServiceImpl.py
  2. storage_adapter.py

改造范围:

  1. 运行时选规则
  2. 创建 audit_run
  3. 结果、错误、指标落库

目标:

  1. 运行链路 tenant-first
  2. 所有衍生记录带租户快照
  3. 后续报表不再依赖复杂 join 推断

8.5 R5 规则配置页聚合租户化

涉及文件:

  1. ruleConfigServiceImpl.py

目标:

  1. ListPackSummariesGetPack 按当前租户解析生效规则
  2. 返回新增标准字段:
    • effectiveTenantCode
    • effectiveScopeType
    • isInherited
    • sourceRuleSetId
  3. 页面能区分:
    • 本租户私有规则
    • 继承省级规则
    • 继承公共规则

8.6 R6 鉴权与权限补齐

涉及文件:

  1. ruleController.py
  2. ruleConfigController.py
  3. 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. 发布级验收已证明不同租户互不串规则、互不串结果