Repository navigation
澄清:viewAllRecords / modifyAllRecords 在 public_read_write 下失效,是否为开源版有意设计? #3005
Description
Activity
已按 15.0.0 的实际执行链逐层核实。结论:两个现象都是有意行为,但成因和你们的推断不同——
*AllRecords不是企业版能力,#2920 的「fail-closed 到 owner-only」指的也不是它。逐条说明:1. 读全开、
viewAllRecords无区别 —— 是 OWD 语义本身public_read_write在 sharing 层的含义就是「组织内人人可读写」(plugin-sharing/src/sharing-service.tseffectiveSharingModel→public,不注入任何行级过滤)。viewAllRecords的作用是把 sharing 轴的深度拉到org——在private/public_read下它会解除属主过滤;在public_read_write下基线已经是 org 全开,没有可再放宽的东西,所以「授不授没区别」是这个 OWD 的预期结果,不是开关失效。机密行不应放在public_read_write对象上;把 OWD 设为private(ADR-0090 D1 的 fail-closed 默认)或public_read,viewAllRecords立即有意义(实测路径:getEffectiveScope→__readScope: 'org'→buildReadFilter返回 null,纯开源可用)。2.
modifyAllRecords拦不住跨属主写 —— 拦的不是 OWD,是基线 RLS + posture 门public_read_write下 sharing 层对写是放行的(canEdit→public→ true)。真正拦住非属主 update/delete 的是平台基线权限集member_default自带的两条通配 RLS 策略owner_only_writes/owner_only_deletes(created_by == current_user.id,适用域positions: ['org_member'],plugin-security/src/objects/default-permission-sets.ts),经由写前 pre-image 检查强制(#1985 的修复)。每个 membership role 为member的用户都自动持有org_member岗位,所以它对全体普通成员生效——与 OWD 是什么无关。而
modifyAllRecords之所以解不开它:超级用户位对 RLS 的短路是 posture-gated 的(ADR-0066 D2 修订①原文:"only when the object's posture permits it (platform-global or private)"),即仅限access: { default: 'private' }、tenancy.enabled: false或 better-auth 托管对象;普通租户业务对象不满足,computeLayeredRlsFilter(security-plugin.ts)里 Layer 1 不短路。这是有 ADR 记录的设计,动机是共享库多租户下不让超级位静默跨租户(现在 Layer 0 拆出后该动机部分由 ADR-0095 结构性承接,但 15.0.0 的行为就是如此)。3. 对 #2920 的理解需要修正
#2920 留在企业侧的只有层级深度作用域(
own_and_reports/unit/unit_and_below),它们依赖IHierarchyScopeResolver(@objectstack/security-enterprise),开源版对这三个值 fail-closed 到 owner-only(sharing-service.tsresolveOwnerScopeIds)。viewAllRecords/modifyAllRecords和org深度完全是开源功能,由开源plugin-security强制执行。4. 「属主可编辑 + 主管可改任意记录」在开源版 RBAC 可以实现
- 方案 A(推荐):给主管岗位绑一条 OR 放宽的 RLS 策略——
{ object: '*', operation: 'update', using: 'organization_id == current_user.organization_id', positions: ['supervisor'] }(delete 同理)。同对象 RLS 策略 OR 合并(ADR-0066 ②-3),普通成员保持属主门、主管放宽到全组织。 - 方案 B:主管的 membership role 设为
admin(→org_admin岗位,不在org_member适用域内,天然不受属主门约束)——但附带整套 org admin 权限,面较宽。 - 方案 C:机密对象改用
access: { default: 'private' }posture + 显式授权,此时modifyAllRecords按 ADR-0066 设计正常旁路 RLS。
文档
按建议补了文档,但没有采用「
*AllRecords为企业版能力」的表述(那不准确):PR #3008 在 sharing 文档(OWD 表下)新增了「View/Modify All 与 OWD 的交互」小节 + supervisor 配方,并给permissions-matrix.mdx里那句无条件的 "both bypass ownership and sharing"(正是误导预期的句子)加上了 posture 门限定。一句话总结:不用另开 bug;行为符合 ADR-0066/0090/0095 的设计。需要跨属主写请走上面 A/B/C 三条 RBAC 路径,层级(汇报链/BU 子树)提权才是企业版能力。
Generated by Claude Code
- 方案 A(推荐):给主管岗位绑一条 OR 放宽的 RLS 策略——
- added a commit that references this issue
on Jul 16, 2026
背景
框架 15.0.0,对象采用默认 OWD
public_read_write。我们观察到(真机,11 用户 × 51 对象):
viewAllRecords没有任何区别。modifyAllRecords: true,行级属主门仍拦非属主的 update/delete。因此在public_read_write下,「属主可编辑 + 主管可编辑任意记录」通过 RBAC 无法实现。问题
这在开源版里是有意设计吗?我们把 #2920 理解为:开源版fail-closed 到 owner-only,而层级 / all-records 提权是企业版能力、不随开源框架发布。若如此,则
viewAllRecords/modifyAllRecords在public_read_write下失效属于有意设计,我们会把「主管看 / 改全部」当作企业版 / admin / Hook 层面的事,而不是 bug。能否确认?如果确属设计,建议在 sharing 文档里加一行说明(「
*AllRecords为企业版能力;开源版在public_read_write下为 owner-only」),可以省掉后来者的同样排查。如果这些开关本应在开源版生效,我们再另开 bug 附复现。