Skip to content

tracking(authz): 双轨赛道下的授权改进开发任务 v2(内核链 ADR 待编号 + 补齐轨 + 地基) #2920

Closed

Description

@os-zhuang

背景:双轨赛道决策

授权系统竞争力赛道已拍板 = 双轨:主轨打「AI-native / 开源」叙事(结构化授权可 lint/explain/diff + 开源自托管 + 包 provenance),补齐轨只挑 2 项接近「能卖」的企业能力。据此重排开发任务,「层级 RLS 开源落地」删除(留企业侧当卖点,IHierarchyScopeResolver 可插拔 seam 已就位、开源版 fail-closed 到 owner-only)、合规认证 / PSG 不排期(按需触发 / 后置)。

已拆出的独立 issue:#2917(管理员手册)、#2918(行写护栏)。本 issue 汇总其余全部开发任务,交由接手 agent 执行。

修订说明

v2(2026-07-14):原版经落点级核实后重写,核实证据见评估评论。要点:「内核链 ADR-0094」引用失效(编号被占)改为新前置任务 B0;B1 落点更正(rls-engine.ts 不存在);原 B3 并入 B2;原 A5 前提不成立已重写;A3 已完成过半估算下调;「待核实 Q7」无出处移除。

v2.1(2026-07-14):

  1. B0 已落地:ADR-0095 成文,PR docs(adr): ADR-0095 — authz kernel chain: tenant isolation as Layer 0, posture ladder, capability-derived posture (B0 of #2920) #2924(draft,评审中)。起草过程中发现新证据 W1:compileFilter 把含 tenant_isolation 在内的全部适用策略 OR 合并(rls-compiler.ts),与 ADR-0066 文档的「tenant-global AND 在上」语义存在分歧——一条宽松业务 RLS 策略在 RLS 层足以放行跨租户行(是否实际暴露取决于 driver 层 applyTenantScope 半缝是否兜住)。这使 B1 同时是「修复文档与实现的语义分歧」,ADR-0095 已把该修复列为行为保持工作中唯一的、显式声明的行为变更(安全修复)。
  2. B5 已否决(maintainer 决策,2026-07-14):PG 原生 RLS 兜底不做,理由记入 ADR-0095 Alternatives(cloud 拓扑已物理隔离;唯一受益方是 EE shared-DB 模式,代价是 PG-only 防线破坏可移植性 + GUC/连接池风险 + 测试矩阵翻倍)。仅当 shared-DB SaaS 形态成为一等产品时重启。
  3. C1 解锁:cloud 仓库已接入本会话 scope,可以评估与执行。

v2.2(2026-07-18,收口):全部开发任务已交付合并并随 15.1.0(2026-07-17)发布,checkbox 补勾;完成状态逐项核实见复核评论。唯一移交的开发缺口——ADR-0099 P0–P2 实现——已另立 #3211 跟踪。本 issue 关闭。


依赖与执行顺序

  • 立即并行开工(不碰内核热路径):A3、A4、A5 + C2-α(explain 契约扩展)+ C1。
  • 串行主线(工程日历瓶颈):B0(评审中)→ B1 → B2 → B4。B1 动手前先把矩阵门下沉到单元层。
  • C2-β(双端实现):契约定稿后可与 B 后段并行。

估算:本 issue 剩余范围合计 ≈ 35–59 PD(B0 已出稿;B5 已否决;含 C1 5–8 PD 待复核)。B 组内核链是关键路径,加人压不动。


A. 地基层(独立并行)

  • A3 — 用户页一站式分配入口(剩余部分) → feat(platform-objects): A3 — 用户页 Permission Sets + Business Units 分配入口 (#2920) #2927 ✅

    • 现状:Positions tab 已落地(packages/platform-objects/src/pages/sys-user.page.ts L141-177,ADR-0090 D3,即目标 record:related_list + add.picker 模式本身)。
    • 剩余:照抄该模式补 Permission Sets(直接授权,junction sys_user_permission_set,picker 对象 sys_permission_set)+ Business Units(junction sys_business_unit_member,picker 对象 sys_business_unit)两个 tab。两 junction 对象定义均已存在(plugin-security / platform-objects/identity)。
    • objectui:零改动(plugin-detail/src/RelatedList.tsx 的 add.picker 与 name-keyed junction 已完整支持)。
    • 判据:管理员在单个用户页完成岗位/权限集/BU 三类分配;直授路径须过 delegated-admin gate(浏览器 dogfood 验证被拦/放行两侧)。
    • 估:1–2 PD。
  • A4 — 权限来源三态统一 + 露出(platform / package / admin) → framework feat(plugin-security): A4 — managed_by 三态统一 + listView 露出 (#2920) #2934 + objectui Dashboard-level filters (date / region) driving multiple charts #2501 ✅

    • 真实工作是三态语义统一,不只是加列。现状不一致:sys_capability = platform/package/admin(select,listView 已有列);sys_permission_set = platform/package/user(text,列已有);sys_position = system/config/user(text,listView 缺列)。
    • 内容:(1) 统一三对象 managed_by 取值词表与字段类型(以 sys_capability 的 select 三态为准,migration/兼容映射 user→admin、system/config→platform/package 需在实现时确认历史数据);(2) sys_position listView 补列;(3) objectui 二态徽标扩三态(PermissionMatrixEditor.tsx L529-538 现仅 Package/Custom)+ i18n key(metadata-admin/i18n.ts)。
    • 注意:Studio AccessPillar 按 provenance 过滤掉 platform 默认集(StudioDesignSurface.tsx L2979-2986),三态徽标落 Setup 记录页链路而非 Studio 矩阵。
    • 判据:管理员一眼分清「平台发的 / 应用发的 / 自己建的」(与 feat(plugin-security): 内置行写护栏 — sys_position / sys_capability 平台/应用托管行可被删改 #2918 互补);三对象词表一致。
    • 估:2–3 PD。
  • A5 — 包级 capability 声明 API(原「声明链打通」重写) → feat(spec,plugin-security): A5 — 包级 capability 声明 API (#2920) #2932 ✅

    • 现状更正:capability 单一真源已成熟(packages/spec/src/security/capabilities.ts + bootstrap-system-capabilities.ts 从 permission set 的 systemPermissions 自动派生 seed);不存在「应用声明又复制进 spec」的重复,契约名是 requiredPermissions/systemPermissions(无 inputs)。
    • 重写后的目标:给包一个正式的 capability 声明入口(如 defineCapability),使应用/包自带的 capability 带 managed_by:'package' + package_id provenance 流入 registry,而非依赖「从 systemPermissions 隐式派生」;配套文档明确「capability ≠ contract,资源用 requiredPermissions 引用、包用声明 API 定义」。呼应 ADR-0094 D5 的「managed_by:'user' 类逐步退役」方向。
    • 判据:示例应用演示包级声明→boot seed→sys_capability 带包 provenance 全链;文档/skill 更新。
    • 估:2–4 PD。

B. 主轨 · 内核链(严格串行,ADR-0095)

高 blast-radius,动的是授权热路径。每步落在 role × object × expected-visible-rows 矩阵快照门后推进。矩阵雏形在 packages/dogfood/test/authz-conformance.matrix.ts(集成层)——B1 动手前先把矩阵门下沉/复制到单元层(plugin-security 测试内)。行为契约与 W1 例外见 ADR-0095。

  • B0 — 内核链 ADR 成文 → ADR-0095(docs/adr/0095-authz-kernel-tenant-layer-and-posture-ladder.md),PR docs(adr): ADR-0095 — authz kernel chain: tenant isolation as Layer 0, posture ladder, capability-derived posture (B0 of #2920) #2924 评审中。回答了拓扑问题(Layer 0 的承重场景 = ADR-0093 multi shared-DB 模式;ADR-0073 的「跨租户 RLS 不存在」声明限定于物理拓扑);否决 PG 兜底;记录 W1 分歧。

  • B1 — 拆租户隔离为 Layer 0(ADR-0095 D1) → feat(plugin-security): B1 — 租户隔离拆为 Layer 0(ADR-0095 D1 + 四处授权 delta)(#2920) #2933 ✅

    • 落点:packages/plugins/plugin-security/src/rls-compiler.ts(租户过滤与业务 RLS 现为同一 pass、OR 合并 = W1)+ security-plugin.ts computeRlsFilter(posture-gated bypass 是唯一短路点,一个 bit 同时短路两层 = W2)+ objects/default-permission-sets.ts(tenant_isolation 通配策略,Layer 0 落地后从 seed 退役)+ packages/core/src/security/resolve-authz-context.ts。
    • 内容:专属 tenant-layer 模块,消费 ADR-0093 tenancy service;multi 模式对租户对象无条件 AND organization_id == ctx.organization_id,始终在先、与业务 RLS 分离代码路径;豁免规则按 ADR-0095 D1(PLATFORM_ADMIN posture × 对象 posture 允许)。
    • 判据:矩阵快照门锁行为;唯一允许的 delta 是 W1 修复(宽松业务策略 × 异租户行 → 不可见),作为显式安全修复带专属矩阵行。
    • 估:8–13 PD。依赖 B0 合并。
  • B2 — posture 阶梯(ADR-0095 D2,含 EXTERNAL 档位预留) → feat(core,plugin-security): B2+B4 — posture 阶梯 + capability 派生 (ADR-0095 D2/D3, #2920) #2938(与 B4 同 PR)✅

    • 落点:packages/core/src/security/resolve-authz-context.ts。
    • 内容:单调 enum PLATFORM_ADMIN > TENANT_ADMIN > MEMBER > EXTERNAL,每档恰好一条注入规则、严格嵌套(rung n 可见集 ⊇ rung n-1,作为被测不变量)。EXTERNAL 语义现在锁死(仅显式共享、永不 OWD、误配只能更少),实现等 portal/external 主体类型出现后另立 issue(对齐 ADR-0093 membership)。
    • 判据:resolve-authz-context.test.ts 升级为 role×object×expected-rows 矩阵快照 + 嵌套不变量断言;EXTERNAL 有枚举级语义锁测试。
    • 估:8–13 PD。依赖 B1。
  • B4 — posture 从 capability 派生(ADR-0095 D3) → feat(core,plugin-security): B2+B4 — posture 阶梯 + capability 派生 (ADR-0095 D2/D3, #2920) #2938 ✅

  • B5 — Postgres 原生 RLS backstop → 已否决(v2.1 修订说明第 2 条;理由见 ADR-0095 Alternatives)。


C. 补齐轨 · 企业能力(只挑 2 项)


执行须知(踩过的坑 / 约束)

  1. worktree-first(Prime Directive Migrate documentation site to Fumadocs with monorepo structure and shared content #11):改文件前每仓开专属 worktree(framework / cloud / objectui 各自),别在共享 main checkout 上动手,会被并发 agent reset 抹掉。guard hook 会拦 Edit/Write。
  2. 双轨约束:层级 RLS 留企业侧(C1),别放进开源;PSG 聚合层、合规认证不在本轮排期。
  3. B 组矩阵门:B 组是行为保持的分层加固,不是改「谁能看什么」;除 ADR-0095 声明的 W1 修复外,矩阵快照暴露的任何 delta 是 bug 不是 feature。先把矩阵门下沉到单元层再动 B1。
  4. ObjectQL 键是 where 不是 filter:findOne/find 的过滤键写错会被静默忽略(历史上锁错 admin,dogfood 才抓到)。
  5. 谓词裸字段会 fail-closed 静默隐藏按钮/行:写 visible/RLS 谓词先查 objectstack-ui / objectstack-formula skill,os build 现会拦裸字段。
  6. 验证:改动要浏览器 dogfood 实测 + 截图,别只读代码推断(尤其 A3/A4/C2 的 UI)。

关联

#2917 · #2918 · epic #2776(Permission Model v2 parking lot)· #2909(两存储类型审计)· ADR-0095 / PR #2924(B0)· ADR-0066 / 0073 / 0090 / 0093 / 0094 · v1→v2 评估评论 · #3211(ADR-0099 P0–P2 实现,收口移交)

Activity

  1. os-zhuang commented on Jul 14, 2026

    @os-zhuang
    ContributorAuthor

    落点核实评估(接手前必读)

    对本 issue 全部 10 项任务做了 framework + objectui 双仓库的落点级核实(文件+行号)。方向与依赖排序判断正确(B1 链首、A/C1 并行、矩阵门约束都成立),但有 4 个执行阻塞项和多处估算修正,接手 agent 请先读下表再开工。

    ⛔ 执行阻塞项(开工前必须解决)

    1. ADR 编号冲突:docs/adr/0094 已被「sys_permission_set pure projection」占用(Accepted 2026-07-14)。本 issue 所称「内核链 ADR-0094」在仓库中无任何草稿——内核链 ADR 需以新编号(≥0095)成文后 B 组才能开工。
    2. B1 落点文件不存在:packages/core/src/security/rls-engine.ts 不存在。实际 RLS 现状:租户隔离是通配 RLS 策略 tenant_isolation(plugin-security/src/objects/default-permission-sets.ts:161-164),与业务 RLS 在 plugin-security/src/rls-compiler.ts 同一 pass、OR 合并;唯一短路点在 security-plugin.ts:1732-1746(computeRlsFilter 的 superuser bypass)。authz 解析在 packages/core/src/security/resolve-authz-context.ts。
    3. B1/B5 与既有 ADR 立场冲突:ADR-0073(L57)认为租户隔离是物理的(env-per-database,ADR-0002),跨租户 RLS「问题不存在」;ADR-0066 把租户隔离归 Layer 3。「拆出 Layer 0」实为新建独立层而非纯重构——须先在新 ADR 里与 0002/0066/0073 协调这个立场。
    4. C1 仓库不可达:cloud/packages/security-enterprise 需要 cloud 仓库 access,当前 agent 会话 scope 只有 framework + objectui。C1 需单独安排。

    逐项核实结果

    任务 核实结论 估算修正
    A3 已完成过半:Positions tab 已在(sys-user.page.ts:141-177,正是目标 record:related_list+add.picker 模式,ADR-0090 D3);sys_user_permission_set / sys_business_unit_member 对象均已存在。objectui 侧 record:related_list+add.picker+name-keyed junction 已完整支持(plugin-detail/src/RelatedList.tsx:67-76,467-481)——objectui 零改动,issue 的「可能需配套渲染」担忧不成立 3-5 → 1-2 PD
    A4 属实,但真实工作是三态语义统一而非加列:capability=platform/package/admin(select,listView 已有列)、permset=platform/package/user(text,已有列)、position=system/config/user(text,唯一缺列)。objectui 需把二态徽标(PermissionMatrixEditor.tsx:529-538 Package/Custom)扩三态 + i18n。注意:Studio AccessPillar 按 provenance 过滤掉 platform 默认集(StudioDesignSurface.tsx:2979-2986),徽标应落 Setup 记录页链路 2-3 PD 合理(按统一语义口径)
    A5 ⚠️ 两个前提不成立:注册表契约名是 requiredPermissions/systemPermissions(ADR-0066),无 inputs;「应用声明 capability 又复制进 framework spec」的重复结构上不存在——spec/src/security/capabilities.ts 是单一真源,应用只在 systemPermissions 按名引用,未 curated 的 boot 时自动派生(bootstrap-system-capabilities.ts)。若 A5 真实目标是包级 capability 声明 API(应用自带 capability 定义流入 registry)则值得做 需先重定义范围
    B1 见阻塞项 2/3。矩阵门雏形已有:packages/dogfood/test/authz-conformance.matrix.ts 可升级为快照门 8-13 PD 偏低(含 ADR 成文 + 矩阵门建设)
    B2 posture enum 不存在,从零建:主体分层现用 positions 数组;platform_admin 是从 admin_full_access 派生的(resolve-authz-context.ts:207-214)。resolve-authz-context.test.ts 现为逐例断言,非矩阵 8-13 PD 合理偏紧
    B3 确是 gap:sharing 全链无 external/portal 概念(sharing-service.ts 全文零命中)。正因如此,得先有「external 用户」的身份概念本身(可能依赖 ADR-0093 tenancy/membership 语义) 3-5 PD 偏低
    B4 派生机制有现成范本:superuser bypass 已从 viewAllRecords/modifyAllRecords 派生(permission-evaluator.ts:208-228,security-plugin.ts:1743-1744 调用) 5-8 PD 合理
    B5 完全绿地:driver-sql(Knex)有 PG 分支,但 SET LOCAL/GUC/CREATE POLICY 全仓库零命中。且受阻塞项 3 的部署拓扑立场制约——若坚持 env-per-database,PG RLS backstop 的形态/价值完全不同,先澄清再动 8-13 PD;建议后置
    C1 无法核实(见阻塞项 4) —
    C2 属实且是真实新工作:前后端均为 object+operation 级——explain-engine.ts(564 行,签名 explain(principal, object, operation),无 record id)、AccessExplainPanel.tsx(九层流水线 + readFilter,请求体无 recordId)。record 粒度需双端扩展(契约 spec/src/security/explain.zod.ts 先行) 8-13 PD 属实偏紧
    Q7(待核实项) ❌ docs 全文 grep Q7 / 投影修复 / projection fix 零命中(仅截图二进制误命中)。仓库内唯一相近主题就是 ADR-0094 pure-projection 本身。建议:要么确认 Q7 即指 ADR-0094 落地收尾,要么从路线图移除 —

    修正后的执行顺序

    1. 立即可做:A3(1-2 PD)、A4(2-3 PD,先定「补列 vs 统一语义」口径)。
    2. 先对齐再做:A5(范围重定义)→ 内核链 ADR 以新编号成文(协调 0002/0066/0073 立场)→ B1→B2→{B3,B4};B3 需先解决 external 身份来源;B5 待部署拓扑澄清。
    3. 另行安排:C1(需 cloud 仓库 access)。
    4. C2:explain 契约扩展定稿后可与 B 后段并行。

    修正后总量:A 组 5-9 PD(原 7-12)、B 组 32-52 PD 另加 ADR 成文、C2 8-13 PD;C1 未评估。


    核实方法:3 个并行探索 agent 对两仓库做文件+行号级核实;关联 #2917 / #2918 已确认拆出且 open。


    Generated by Claude Code

  2. changed the title [-]tracking(authz): 双轨赛道下的授权改进开发任务(内核链 ADR-0094 + 补齐轨 + 地基)[/-] [+]tracking(authz): 双轨赛道下的授权改进开发任务 v2(内核链 ADR 待编号 + 补齐轨 + 地基)[/+] on Jul 14, 2026
  3. os-zhuang commented on Jul 15, 2026

    @os-zhuang
    ContributorAuthor

    ✅ A/B/C 三组开发全部落地

    本 tracking 的全部开发任务已实现、CI 全绿并合并进各自 main。

    A. 地基层

    B. 主轨内核链(ADR-0095)

    C. 补齐轨

    衍生的安全跟踪 issue(后续开发中)

    后续开发(#2937 修复、#2936、C1 的 ADR-0090 position-anchor BU 差异、浏览器 dogfood 验证 A3/A4/C2-β UI)正在推进。


    Generated by Claude Code

  4. os-zhuang commented on Jul 15, 2026

    @os-zhuang
    ContributorAuthor

    Follow-up 收尾(安全审查衍生项 + 企业 e2e 门)

    主体 A/B/C 三组 + 安全修复合并后,又收口了三件衍生工作:

    仍待 maintainer:① 人工过一遍安全敏感 diff(B1 / #2946 / C1);② 跑 changeset version + release 出 v15.0.0。

    posture 是否进 enforcement 裁决(当前仍按 capability/super-bit)是独立的 ADR 级决策,未纳入本轮。


    Generated by Claude Code

  5. os-zhuang commented on Jul 18, 2026

    @os-zhuang
    ContributorAuthor

    剩余任务评估(2026-07-18 复核)

    对本 tracking 的全部任务与三条历史评论声明做了逐项复核(issue/PR 状态 + main 代码落点证据)。结论:开发范围已全部交付并随 15.1.0 发布;血统内仅剩 1 项实质开发缺口(ADR-0099 P0–P2 实现)+ 2 项非开发收尾。

    已核实完成(可对账)

    真正剩余

    1. ADR-0099 P0–P2 实现未开工(唯一实质开发缺口)。ADR-0099(posture 裁决收尾篇,docs(adr): ADR-0099 — posture-adjudicated tiering, EXTERNAL enforcement path, no explicit deny #3109 merged 2026-07-17)目前 Proposed、纯 docs,无任何实现 issue/PR。代码证据:Layer 0 豁免门仍走 hasPlatformAdminPosture 能力探针(security-plugin.ts:2390 / :2426),:71-77 的「posture 未透传」过时注释仍在(P1 明确要求随翻转退役);authz-matrix-gate.test.ts 尚无「探针 vs rung 等价」矩阵格(P0)。explain 侧已读 ctx.posture(fix(plugin-security): explain posture 证据对齐 enforcement 派生(消除标签漂移) #2949 完成了 P1 的一半)。建议:另立实现 issue 承接 P0(等价门)→ P1(Layer 0 豁免门读 rung)→ P2(Layer 1 级判定收敛);P3(EXTERNAL)按 ADR 继续 demand-gated,归 Permission Model v2 — named follow-up ADRs (post-ADR-0090 parking lot) #2776 item 6。
    2. maintainer 人工过安全敏感 diff(B1 / fix(plugin-security): 堵跨租户 UPDATE 写 + org_admin private 对象越墙(security) #2946 / C1)——无显式 sign-off 记录。这些修复已随 15.1.0 发布并经 release: 15.1 QA test checklist — framework 15.1.0 + console (objectui 14.1) #3072 QA + 外部用户实测检验;若认为该证据链足够,此项可勾销,但需 maintainer 拍板而非 agent 代答。
    3. cloud 侧 C1 follow-up(ADR-0090 position-anchor BU 差异)——cloud 仓库不在本会话 scope,无法核实是否已收口;需在 cloud 侧确认(cloud#827/Fix flow reference mismatch in CRM example action #835 之后是否另有跟踪)。
    4. (低风险备注)A3 用户页三 tab 的浏览器 dogfood 在 release: 15.1 QA test checklist — framework 15.1.0 + console (objectui 14.1) #3072 清单中无显式条目;feat(platform-objects): A3 — 用户页 Permission Sets + Business Units 分配入口 (#2920) #2927 合并时已验证,建议下轮 QA 顺手复确认即可,不构成阻塞。

    处置建议

    本 tracking 的使命已尽:建议勾掉 body 全部 checkbox 并 close(completed),ADR-0099 实现另立 issue 跟踪(避免本 issue 变成第二个 parking lot——那是 #2776 的职责)。


    核实方法:GitHub 状态核对(open PR 0 个 authz 相关、security 标签 open issue 中无本血统项)+ main 落点级 grep(tenant-layer/explain/posture)。


    Generated by Claude Code

  6. os-zhuang commented on Jul 18, 2026

    @os-zhuang
    ContributorAuthor

    🏁 收口

    全部开发任务已交付合并并随 15.1.0(2026-07-17)发布,逐项核实见上方复核评论;body checkbox 已补勾(v2.2)。关闭本 tracking。

    移交与遗留:


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions