fix(spec): scope the modifyAllRecords bypass declaration to what sharing enforces (#6698) - #6852
Merged
Conversation
…aring enforces (#6698) `ObjectPermissionSchema.modifyAllRecords` promised a bypass of "Sharing Rules and Ownership checks". On an object with NO owner field it bypasses neither: record sharing does not enforce there at all (`checkEdit`/`checkDelete` answer `abstain` before the bypass is probed, #6428), so the platform's own row-level write floor `created_by == current_user.id` (#1985) survives and the by-id write is refused — measured and pinned in plugin-security's `row-write-widener-composition.test.ts` by #6684. Option A on #6698: only the DECLARATION moves. The describe now scopes the bypass to the objects record sharing enforces on and discloses the surviving platform floor, while keeping legible that on an owner-bearing object — the common case this bit is granted for — the bypass is real. No runtime change; the accepted/rejected metadata set is byte-for-byte unchanged; no `plugin-sharing` or `plugin-security` file is touched. `content/docs/references/security/permission.mdx` is regenerated by `pnpm --filter @objectstack/spec gen:docs` (two table cells). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ffcE95NaMJcL9XJ9VDYgk
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 112 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Aug 9, 2026
os-project-manager
marked this pull request as ready for review
August 9, 2026 00:50
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6698
Option A only。 本 PR 只动声明,不动任何运行时:
plugin-sharing/plugin-security一个文件都没有碰(改动文件共 4 个,见下)。option B(把hasModifyAllBypass探测提到hasOwnerField提前返回之前)明确不做,option C 按 #6564 §7 本来就被否掉。缺陷
packages/spec/src/security/permission.zod.ts把modifyAllRecords描述成 "Super-user write access. Bypasses Sharing Rules and Ownership checks",.describe()则是Modify All Data (Bypass Sharing)。在没有 owner 字段的对象上,这两样都不成立:checkEdit/checkDelete在探测 bypass 之前就abstain(plugin-sharing/src/sharing-service.ts:504/:586,ISharingService 写判定补三态(放行/不表态/拒绝)—— #5492 裁决 B 案的 step1,二态 canEdit 已实测产出 fail-open #6428 的三态);created_by == current_user.id(plugin-security/src/platform-ownership-policies.ts里 [security][P0] Broken access control — any authenticated member can read AND modify other users' records #1985 的owner_only_writes/owner_only_deletes通配策略)继续生效,按 id 写别人创建的行仍然 403。这一格是 #6684 明确测量并钉住的既定行为(
plugin-security/src/row-write-widener-composition.test.ts:472,"an abstention does not become permission for a Modify-All holder either"),不是缺陷。缺陷在于声明比实现讲得多 —— ADR-0049declared ≠ enforced的那一类残留。改法
.describe()前后对照:Modify All Data (Bypass Sharing)Modify All Data (Bypass Sharing) — bypasses sharing rules and ownership on the objects record sharing enforces on; on an object with NO owner field sharing abstains, so the platform created_by write floor still applies (#6698).旁边的文档注释同步改掉了它自己那句无限定的 "Bypasses Sharing Rules and Ownership checks" —— issue 正文引用的就是这句,只修 describe 会把被点名的原话留在文件里。文档注释属于同一处声明的散文,不进生成文档,也不影响接受集合。
刻意保留了另一半。 带 owner 字段的对象 —— 也就是授予这个位的常见场景 —— bypass 是真的,措辞里 "bypasses sharing rules and ownership" 原样留着,避免矫枉过正成相反的谎:读者不该以为这个位是空的。能力面没有增长,这是一次纯字符串改动。
接受集合逐字节不变
.describe()不参与 parse。旁证:gen:schema重跑后authorable-surface/**、json-schema.manifest/**、authorable-defaults/(1308 个默认值)零 diff,check:authorable-surface绿;permission.test.ts原有 47 例(含#4001未知键拒绝套件)全绿。没有动任何 enum 成员、键或 refinement。生成产物
.describe()确实进content/docs/references/**。pnpm --filter @objectstack/spec gen:docs重算后只有content/docs/references/security/permission.mdx变化,且只有两格(authoring 表 +EffectiveObjectPermissionSchema响应侧表各一行)。check:generated10/10 绿。check:generated报api-surface/陈旧,是脚本自己警告过的「未 build 就检查」幻影 ——pnpm --filter @objectstack/spec build后复跑即绿,该产物无实际改动。Pin 与反向验证(方向先预测,后测量)
新增
packages/spec/src/security/permission.test.ts的[#6698] modifyAllRecords declares its bypass AND the limit of that bypass:把描述从 schema 里读回来再断言它必须承载的事实(idiom 匹配,不锁措辞),三条断言全为正向,因此清空.describe()必然变红。Modify All Data (Bypass Sharing)2 failed | 45 passed.describe('')(反空转)3 failed | 44 passed1 failed | 46 passed47 passed验证
pnpm --filter @objectstack/spec test——Test Files 346 passed (346)/Tests 8880 passed (8880)pnpm --filter @objectstack/spec typecheck——tsc --noEmit+check:scripts-typecheck+check:test-typecheck全绿(测试层 58 file / 266 error 的收缩型 ratchet 未变)pnpm --filter @objectstack/spec check:generated——✓ All 10 generated artifacts are up to date.npx eslint两个改动 TS 文件 —— exit 0,无告警check:type-check-coverage(spec 已在@ts-expect-error退役 pin 在packages/spec里是幽灵检查:tsconfig 把**/*.test.ts排除出唯一的tsc --noEmit#5286 毕业,不在 DEBT/TEST_DEBT 台账内)、check:nul-bytes、check:doc-authoring、check:role-word、check:quick-reference-counts、check:docs-audit-scope、check:adr-anchors、check:empty-changeset—— 全绿改动文件(4)
packages/spec/src/security/permission.zod.ts(describe + 文档注释)packages/spec/src/security/permission.test.ts(pin)content/docs/references/security/permission.mdx(生成产物,未手改).changeset/modifyall-records-owner-less-declaration.md(@objectstack/spec: patch)未触碰
content/docs/releases/。Generated by Claude Code