# 规则域多租户方案 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. 发布级验收已证明不同租户互不串规则、互不串结果