业务故事站
P2 Foundry

访问控制与数据治理:看得见才敢信

数据既要"看得见",也要"分得清、管得住"。Foundry 的访问控制让读路径按 RLS/CLS/属性级三层过滤、写路径有记录级 RLS 兜底;数据治理用术语表统一词汇、分类标签标注敏感度、质量规则做闭环。本主题 4 个故事覆盖"能看什么、能改什么、怎么讲清楚、怎么保质量"。

管理员 数据工程师 业务分析师 RLS CLS 质量规则 共 4 个故事

能 / 不能速览

✅ 这个主题能做
  • 只读路径三层过滤:RLS 行级 + CLS 列级(mask/hide/nullify)+ 无 Read 属性列置 NULL(不整行拒绝)
  • 写路径记录级 RLS(RECORD_ACCESS_DENIED)+ 无 WHERE 无边界写整批拒绝
  • 语义查询 / OOL / 指标查询统一注入 RLS/CLS 与属性级安全
  • 术语表关联属性、数据分类(level 0-3)打标、属性治理汇总
  • 质量规则(null/format/unique/referential)挂管道运行时检查 + 问题确认/修复闭环
⛔ 这个主题做不了
  • ABAC 策略只做 CRUD 与显式授权,未接入查询 / 写路径
  • 分类标签不会自动驱动 CLS 访问控制,需管理员另配 cls_policies
  • 质量规则"未达标不得部署"弱化为"run 标红 + 数据照写",error 级不阻断落库
  • 保留策略只有 CRUD 配置,不真正删除 / 归档 / 匿名化数据

适用角色

本主题面向三个角色:

  • 管理员:配置 RLS / CLS / 权限点(用户/角色/策略管理在 AIP 安全后台),授权并追责。
  • 数据工程师:建术语表、打分类标签、写质量规则,让数据"讲得清、保得准"。
  • 业务分析师:消费受保护的只读查询,遇到脱敏 / null 能看懂原因。

能力速览(能做什么)

只读三层过滤

RLS 行级注入 WHERE、CLS 列级 mask/hide/nullify、属性级无 Read 置 NULL——查询一条路全过。

记录级写权限

写路径先 SELECT 主键 + RLS 双计数校验目标记录可见性,越权整批拒绝,绝不静默放大影响。

术语表 + 分类

术语统一"客单价""GMV"这类词汇并关联属性;分类标签(0 公开~3 绝密)标注属性敏感度。

质量规则闭环

null/format/unique/referential 四类规则挂管道输出,违规记 issue,open → acknowledged → fixed。

属性治理汇总

一个接口看全某属性的术语 + 分类 + 基本信息,讲不清楚的属性一键查证。

调整指南(怎么调整)

  • 想管行:在 AIP 安全后台配 RLS 策略(如 region = '{user_id}')挂到角色,读与写同时生效。
  • 想脱敏:配 CLS 策略对敏感列做 mask / hide / nullify,查询自动生效。
  • 想统一词汇:建术语表并关联本体属性,再让分析师按术语搜。
  • 想标敏感度:建 level 0-3 分类给属性打标,治理汇总一处看全。
  • 想拦坏数据:给管道建质量规则,run 后看 /quality/issues,按 open → fix 闭环。

做得好的场景

安全与治理让"敢用数据、说得清数据"成为可能,特别适合以下场景:
  • 分权可见:区域负责人只能看、只能改自己区域的数据,越权写直接被拒。
  • 脱敏合规:敏感列自动脱敏,分析师查数不碰裸数据。
  • 词汇统一:术语表 + 分类让"客单价"还是"平均订单金额"不再打架。
  • 质量前置:管道运行即检查,坏数据一落地就被问题跟踪盯上。

限制与不足

以下是明确的边界,使用前先知道:
  • ABAC 未接入链路:策略 CRUD + /security/authorize 已实现,但不会在查询 / 写路径自动执行。
  • 分类不自动联动:打"机密"标签不会自动隐藏,需管理员另配 CLS。
  • 质量不隔离:error 级违规只把 run 标红,数据照写不阻断。
  • 保留策略是死配置:delete / archive / anonymize 不会真正执行。

场景故事

故事 1 越权改"华南"客户被记录级 RLS 整批拒绝
背景
demo 数据源 foundry_demo_warehouse 的 customers 表有 region 列(张三=华东、李四=华北、王五=华南)。管理员给区域运营账号 zhangsan 配置 RLS 策略 region = '{user_id}',并让数据工程师建了一个 modify 型"客户回写"动作(目标表 customers)。zhangsan 想顺手把华南客户王五(customer_id=3)的 region 改成华东。
传统做法对比
以前一张 UPDATE 全表都能跑,区域运营拿到的权限往往"要么全有要么全无",越权改数据只能靠事后翻日志;现在写路径先做记录级校验,目标记录对你不可见就直接整批拒绝,改都改不动。
角色
管理员(配 RLS 策略与权限点);区域运营 zhangsan(执行动作);数据工程师(建动作定义)。
操作步骤
  1. 管理员在 AIP 安全后台配置 RLS 策略并挂到 zhangsan 角色
  2. 数据工程师建 modify 动作(UPDATE customers SET region=:region WHERE customer_id=:customer_id)并授 action 权限
  3. zhangsan 登录,对 customer_id=3 执行动作
  4. 观察返回:记录级检查通过/拒绝
系统响应
zhangsan 更新王五(华南行)返回 HTTP 403,响应体(status=record_denied):
{
  "code": 0,
  "data": {
    "mode": "VALIDATE_AND_EXECUTE",
    "status": "record_denied",
    "operation_id": "run_6"
  }
}
目标行对 zhangsan 不可见 → 双计数不相等 → 整批拒绝;同时写一条 result=record_denied 的审计。
结果洞察
写路径第三步 stepRecordScope 会先 SELECT 目标主键并注入 RLS 再数可见行:visible == total 才放行;zhangsan 改自己区域的客户(张三)则正常成功。审计里能查到这次被拒操作,越权有痕。
调整建议
RLS 策略按区域/负责人维度设计;给角色的动作权限做最小化;被拒后先查自己的 RLS 可见范围再操作,别硬试。
动手试一试
页面路径:Action 测试 → update 型动作。输入内容:用 zhangsan 改 customer_id=3(王五)。预期结果:返回 status=record_denied(403);改 customer_id=1 成功。记录级检查仅对 modify 型动作生效。
限制提示
记录级检查只对 modify(UPDATE/DELETE 模板)生效,create/link/delete 跳过;RLS 未配置时等价全可见;RLS/CLS 管理路由在 AIP 后台,不在 Foundry。
故事 2 只读三层过滤:amount 脱敏、customer_id 置 null、行级按区域过滤
背景
管理员给分析师账号 lisi 配置了三条规则:RLS 只看得到 orders 中自己区域客户的订单;CLS 对 orders.amount 做脱敏(mask);属性权限里 lisi 对 orders.customer_id 无 Read。lisi 在对象查询里拉订单明细,想看看金额和客户。
传统做法对比
以前要么整张表开只读权限(裸数据裸奔),要么干脆不给查(业务没法用);现在同一查询按"行级 → 列级 → 属性级"三层自动过滤,能看的看、该藏的藏、不该给的不给。
角色
管理员(配 RLS/CLS/属性权限);业务分析师 lisi(消费查询结果)。
操作步骤
  1. 管理员配置 RLS(orders 按区域)、CLS(amount 脱敏)、属性权限(customer_id 无 Read)
  2. lisi 登录,在对象查询选择 order 对象,带 user_id 参数
  3. 提交查询,观察 amount / customer_id 输出
  4. 对照自己区域核对可见行
系统响应
查询返回时 amount 列输出脱敏表达式、customer_id 列为 null、行集被 RLS 过滤:
{
  "code": 0,
  "data": {
    "columns": ["order_id", "amount", "customer_id", "status"],
    "rows": [
      [1, "9**", null, "shipped"],
      [3, "19**", null, "shipped"]
    ]
  }
}
翻译期把无 Read 属性替换为 NULL AS "customer_id",CLS 把 amount 换成 mask 表达式,RLS 追加 WHERE 只留可见行。
结果洞察
三条规则独立叠加、互不干扰:属性级 null 发生在翻译期、RLS/CLS 发生在 SQL 组装后;lisi 拿到的结果"能看趋势、看不到裸敏感值、看不到越权行"。指标 / OOL 查询同样走这套注入。
调整建议
敏感度高的列优先 CLS mask;查询字段尽量收敛,少拉无关列;分析师发现字段为 null 先查属性权限,别怀疑数据丢了。
动手试一试
页面路径:对象查询 → order。输入内容:配置 CLS/属性权限后以 lisi 查询。预期结果:amount 脱敏、customer_id 为 null、行集受 RLS 过滤。RLS/CLS 是字符串级改写,对复杂子查询注入位置可能不准。
限制提示
无 Read 属性返回 null 而不是整行拒绝;聚合查询对无 Read 列是"直接拒绝"而非隐藏;编辑态叠加的值不重新过 RLS/CLS。
故事 3 用术语表和分类标签,让"客单价"不再跟"平均订单金额"打架
背景
月底复盘,销售说"客单价 1020 元",财务说"平均订单金额 890 元",两边数据对不上。数据工程师在 Foundry 数据治理页建术语"客单价",定义 = GMV/订单数,同义词"平均订单金额、AOV",关联到 order 对象的 amount 属性,并把 amount 打上 level=2"机密"分类。
传统做法对比
以前口径散落在 Excel、口头约定和旧报表里,对齐一次口径要开三次会;现在术语表 + 属性关联把"这个词什么意思"固化在平台里,任何人查属性治理汇总就能看到统一口径。
角色
数据工程师(建术语/分类、打标);业务分析师与财务(消费统一口径)。
操作步骤
  1. 在数据治理页建术语"客单价"(定义、同义词、状态 approved)
  2. 创建 level=2"机密"分类标签
  3. 把术语关联到 order.amount 属性,并给 amount 打"机密"标签
  4. 查看属性治理汇总,核对术语 + 分类
系统响应
创建术语返回 {code:0, data:{id:1}};汇总接口返回:
{
  "code": 0,
  "data": {
    "object_name": "order", "property_name": "amount", "data_type": "number",
    "terms": [ { "name": "客单价", "abbreviation": "AOV",
                 "status": "approved", "definition": "GMV/订单数" } ],
    "classifications": [ { "classification_name": "机密", "level": 2,
                            "color": "#e5533b", "applied_by": "zhang" } ]
  }
}
重复关联同一属性返回 409;删除术语级联删除关联。
结果洞察
销售和财务在平台里查 amount 属性,看到的都是同一份术语定义与敏感度标注,口径之争有了唯一的"字典"。敏感度标签同时为后续 CLS 配置提供依据。
调整建议
核心属性都建术语并写定义;敏感属性按 level 0-3 打标;术语状态用 approved 发布后再对外引用。
动手试一试
页面路径:数据治理 → 术语表 / 分类标签。输入内容:建术语"客单价"关联 order.amount,建"机密"分类打标。预期结果:GET /governance/properties/2/3 汇总返回术语与分类。打标签不会自动隐藏数据,需另配 CLS。
限制提示
分类标签不会自动驱动访问控制(CLS 需管理员另行配置);保留策略只有 CRUD 不会真执行;demo 未预置治理示例,需手工造数。
故事 4 管道质量规则:外键缺失被记录,问题走确认 → 修复闭环
背景
数据工程师建了一条把"脏订单"清洗进 orders 表的管道,并在数据质量页给管道挂了一条 referential 规则:customer_id 必须在 customers 表中存在,severity=error。管道跑完后,发现确实有 2 行引用了不存在的客户。
传统做法对比
以前坏数据进了表,要等报表算出来才发现不对,定位问题靠 DBA 手工查一遍;现在质量规则挂在管道输出上,跑完自动检查、自动记 issue,带样本数据一眼看到问题。
角色
数据工程师(建管道 + 质量规则 + 修数据);运营(消费结果)。
操作步骤
  1. 在数据质量页创建 referential 规则(column=customer_id、ref_table=customers)挂到管道
  2. 手动运行管道(POST /pipelines/:id/run)
  3. 打开问题列表查看 open 问题与样本
  4. 修完数据后把问题标记 fix
系统响应
管道 run 返回 failed(error 级违规),问题列表出现 open 记录:
GET /quality/issues → {
  "code": 0,
  "data": { "issues": [
    { "id": 1, "rule_id": 1, "affected_table": "orders",
      "affected_rows": { "count": 2,
        "sample": [ { "customer_id": 99 }, { "customer_id": 88 } ] },
      "status": "open" } ] } }
POST /quality/issues/1/fix 后状态变 fixed。
结果洞察
四类规则(null/format/unique/referential)自动生成检查 SQL 并返回 {Total, Passed, Failed, Sample≤10};severity=error 违规把 run 标 failed,但结果表数据照写("data written, issues isolated")。问题状态机 open → acknowledged → fixed 全程留痕。
调整建议
关键输出表挂 referential + null 规则;format 规则用正则校验字段格式;修复后把 issue 标记 fix 关闭;error 级规则建议配合人工门禁,别只靠 run 标红。
动手试一试
页面路径:数据质量 → 建规则 → 运行管道。输入内容:referential 规则(orders.customer_id → customers.customer_id)。预期结果:/quality/issues 出现 open 问题且带样本;error 级违规时 run 状态 failed。数据照写不隔离。
限制提示
质量规则只对 scope=pipeline 生效(scope=object 只 CRUD 不执行);unique/format 是整列拉内存比对,大表慎用;error 级不阻断落库。

常见问题

RLS / CLS 策略在哪里配置?

用户/角色/RLS/CLS 策略的管理路由在 AIP 安全后台(RolesPage / UsersPage / SecurityPage);Foundry 服务端只注册登录与 ABAC 策略路由,策略数据存同一套平台库。

属性被置为 null 是数据丢了吗?

不是。只读路径对无 Read 权限的属性列输出 NULL(而非整行拒绝);聚合查询则直接返回"禁止聚合"(422),因为聚合列 null 化会产生错误统计值。

记录级权限和 RLS 什么关系?

写路径不 SQL 改写,而是先按 RLS 数出"你能看到的行数",再和模板目标行数比对,相等才放行;RLS 未配置时等价全可见,因此策略要配在角色上才有效。

打了"机密"标签会自动隐藏数据吗?

不会。分类标签只做标注,访问控制需要管理员另行配置 CLS 策略;"打标即生效"的自动联动是待补齐能力。

质量规则能阻止坏数据落库吗?

当前不能完全阻止:error 级违规把 run 标 failed 并记 issue,但数据照写;需要隔离语义(未达标不落库)的部署场景,需等该能力补齐。

主题小结

一句话:Foundry 用"读三层过滤 + 写记录级兜底"管住数据可见与可改,用"术语表 + 分类 + 质量规则"把数据讲清楚、保得住。记住三件事:ABAC 尚未接入链路、打标签不会自动隐藏、质量不隔离(error 只标红)。