Files
leaudit-platform-backend/docs/权限与地区隔离/地区到租户编码映射清洗清单.md

7.9 KiB

地区到租户编码映射清洗清单

适用范围:当前系统中 area / region / 省局 / 省级 / default / 空字符串 / tenant_name 混合使用的历史数据治理
文档定位:给后续数据库清洗、兼容脚本、接口兼容层和测试验收提供一份可执行的“历史值归一清单”。


1. 结论先行

当前系统如果直接上 tenant_code,但不先做历史值映射清洗,会立刻出现三类问题:

  1. 同一租户在不同表里仍然无法匹配
  2. 首页入口、RAG、模板、文档等模块会出现“配置了但看不到”
  3. 统计和权限执行器会因为历史脏值继续分裂

所以租户化改造的第一前提不是写新表,而是先收口旧值。


2. 当前确认存在的历史值类型

按目前代码和 SQL 已确认的高风险值如下。

2.1 地方租户值

  1. 梅州
  2. 云浮
  3. 揭阳
  4. 潮州

2.2 省级 / 公共语义值

  1. 省局
  2. 省级
  3. default
  4. ''

2.3 展示或组织补充字段

  1. tenant_name
  2. dep_name
  3. ou_name

这些值目前在部分前端逻辑里被拿来反推地区。


3. 推荐标准租户编码

建议先建立一套稳定编码:

现展示值 推荐 tenant_code tenant_type 说明
梅州 MZ LOCAL 地市租户
云浮 YF LOCAL 地市租户
揭阳 JY LOCAL 地市租户
潮州 CZ LOCAL 地市租户
省局 PROVINCIAL HEADQUARTER 省局管理租户
公共资源域 PUBLIC PUBLIC 跨租户公共资源,不建议继续用中文值

说明:

  1. PROVINCIAL 表示省局这个租户主体
  2. PUBLIC 表示真正公共资源域
  3. 以后不要再让 省局 既表示租户又表示公共范围

4. 历史值映射规则

4.1 推荐映射表

建议如下:

历史值 归一 tenant_code 处理说明
梅州 MZ 直接映射
云浮 YF 直接映射
揭阳 JY 直接映射
潮州 CZ 直接映射
省局 PROVINCIAL 表示省局租户主体
省级 PUBLICPROVINCIAL 需按业务字段判定,不能一刀切
default PUBLIC 仅限公共兜底语义,不应映射成省局主体
'' PUBLICUNKNOWN 需分场景处理
NULL PUBLICUNKNOWN 需分场景处理

4.2 为什么 省级 不能一刀切

省级 在当前系统至少有两种含义:

  1. 省局主体租户
  2. 全省公共资源

例如:

  1. 合同模板里的 省级 更接近公共模板域
  2. 某些角色或用户语义里的“省级管理员”更接近省局主体

所以 省级 必须结合表和业务语义判断,不能直接全量更新成一个值。


5. 按表清洗策略

5.1 sso_users

重点字段:

  1. area
  2. tenant_name

建议:

  1. 新增 tenant_code
  2. 先根据 area 映射
  3. area 为空时再尝试依据 tenant_name
  4. 仍无法识别的写入 UNKNOWN 或留空待人工处理

人工复核重点:

  1. area 为空但 tenant_name 不为空
  2. areatenant_name 语义冲突
  3. 一个 tenant_name 对应多个 area

5.2 leaudit_documents

重点字段:

  1. region

建议:

  1. default 先归到 PUBLIC
  2. 地方地区名直接归到对应 tenant_code
  3. 不可识别值进入人工复核表

5.3 contract_templates

重点字段:

  1. region

建议:

  1. 省级 默认优先解释为 PUBLIC
  2. 如果后续明确部分模板实际是省局内部专属,再单独调整为 PROVINCIAL

原因:

合同模板当前更接近“公共模板库”模型。

5.4 rag_dataset / rag_chat_app

重点字段:

  1. area
  2. is_public
  3. is_default

建议:

  1. 地方地区名直接映射
  2. area=''is_public=true 的,映射到 PUBLIC
  3. area='省级' 的记录,默认映射到 PUBLIC
  4. is_default=true 不代表公共,只代表默认应用/默认知识库

5.5 leaudit_entry_modules

重点字段:

  1. areas JSONB

建议:

  1. 逐个 area 元素映射到标准 tenant_code
  2. 保留原始 JSON 快照供审计
  3. 后续写入迁移到关系表,不再长期依赖原 JSON

6. 代码级归一规则

6.1 所有输入都必须先归一

后续后端收到以下字段时,都必须先走统一归一函数:

  1. area
  2. region
  3. tenant_name
  4. 前端传入的入口模块租户列表
  5. RAG/模板筛选条件

建议统一函数签名:

resolve_tenant_code(raw_value: str | None, context: str) -> str | None

其中 context 用于区分:

  1. user_area
  2. document_region
  3. template_region
  4. entry_module_area
  5. rag_area

6.2 严禁前端继续做别名猜测

当前前端 cross-checking-access.ts 会用:

  1. includes("梅州")
  2. includes("省")
  3. provincial_admin => 省局

这种逻辑必须下线,原因是:

  1. 新租户名字不一定包含旧关键字
  2. 展示名称变化会导致功能失效
  3. 前端无法承担主数据归一责任

7. 推荐清洗脚本步骤

7.1 第一步:盘点唯一值

先导出下列字段的唯一值和数量:

  1. sso_users.area
  2. sso_users.tenant_name
  3. leaudit_documents.region
  4. contract_templates.region
  5. rag_dataset.area
  6. rag_chat_app.area
  7. leaudit_entry_modules.areas[].area

7.2 第二步:生成映射表

生成一张临时对照表:

  1. raw_value
  2. source_table
  3. sample_count
  4. proposed_tenant_code
  5. review_status
  6. review_comment

7.3 第三步:区分自动映射和人工复核

自动映射:

  1. 梅州
  2. 云浮
  3. 揭阳
  4. 潮州
  5. 省局
  6. default

人工复核:

  1. 省级
  2. 空值
  3. 复合字符串
  4. 未知中文别名
  5. 组织名称形式的 tenant_name

7.4 第四步:回写标准字段

为业务表新增 tenant_code 后,按映射结果批量回写。

7.5 第五步:保留审计痕迹

必须保留:

  1. 原始字段值
  2. 映射规则版本
  3. 清洗时间
  4. 执行人
  5. 人工修正记录

8. 重点风险清单

8.1 default 不能全量等于 PROVINCIAL

当前 default 更多是“兜底公共范围”,不是“省局租户”。

如果错误映射为 PROVINCIAL,会造成:

  1. 公共资源被省局独占
  2. 非省局租户看不到原本可见的内容

8.2 省级 不能在所有表中同义

因为它在不同业务里承担的不是同一个概念。

8.3 tenant_name 不能直接等于 tenant_code

tenant_name 是展示或组织分组名称,数据质量不一定可控。

8.4 入口模块 JSON 最容易残留旧值

因为它不是结构化关系表,清洗后仍可能被旧接口再次写入脏数据。


9. 推荐验收清单

清洗完成后至少要验证:

  1. 每个用户都有可解析的 tenant_code
  2. 每个入口模块的租户分配都能映射到有效主数据
  3. RAG 数据集不会再出现 ''省级default 混杂
  4. 合同模板的公共模板不会因为映射错误被隐藏
  5. 首页入口可见性在旧租户和新租户下都正确
  6. 统计地区维度不会同时出现 梅州MZ 两套口径

10. 本文档解决什么问题

本文档主要解决:

  1. 历史地区值具体怎么映射到租户编码
  2. 哪些字段必须清洗
  3. 哪些旧值可以自动处理
  4. 哪些旧值必须人工复核
  5. 为什么租户主数据改造前必须先做这一步

建议联动阅读:

  1. 租户主数据模型设计.md
  2. 地区租户化与自定义租户扩展改造方案.md
  3. 自定义租户功能连带影响深度补充.md