Skip to content

fix(spec): scope the modifyAllRecords bypass declaration to what sharing enforces (#6698) - #6852

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-6698-modifyall-declaration
Aug 9, 2026
Merged

fix(spec): scope the modifyAllRecords bypass declaration to what sharing enforces (#6698)#6852
os-project-manager merged 1 commit into
mainfrom
claude/issue-6698-modifyall-declaration

Conversation

@os-project-manager

Copy link
Copy Markdown
Collaborator

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.tsmodifyAllRecords 描述成 "Super-user write access. Bypasses Sharing Rules and Ownership checks",.describe() 则是 Modify All Data (Bypass Sharing)。在没有 owner 字段的对象上,这两样都不成立:

这一格是 #6684 明确测量并钉住的既定行为(plugin-security/src/row-write-widener-composition.test.ts:472,"an abstention does not become permission for a Modify-All holder either"),不是缺陷。缺陷在于声明比实现讲得多 —— ADR-0049 declared ≠ 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:generated 10/10 绿。⚠️ 首次跑 check:generatedapi-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)断言 1 绿、2+3 红一致:2 failed | 45 passed
.describe('')(反空转)三条全红一致:3 failed | 44 passed
矫枉过正串(删掉 "bypass" 只讲限制)断言 1 红、2+3 绿一致:1 failed | 46 passed
本 PR 的串全绿一致:47 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-bytescheck:doc-authoringcheck:role-wordcheck:quick-reference-countscheck:docs-audit-scopecheck:adr-anchorscheck: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

…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
@vercel

vercelBot commented Aug 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 9, 2026 12:35am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

112 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/spec)
  • content/docs/api/environment-routing.mdx(via @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via @objectstack/spec)
  • content/docs/automation/connectors.mdx(via @objectstack/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/cli.mdx(via @objectstack/spec)
  • content/docs/deployment/tenancy-modes.mdx(via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via @objectstack/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx(via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx(via @objectstack/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via @objectstack/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/spec)
  • content/docs/kernel/services.mdx(via @objectstack/spec)
  • content/docs/permissions/authorization.mdx(via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/rls.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx(via @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v16.mdx(via @objectstack/spec)
  • content/docs/releases/v17.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/spec)
  • content/docs/ui/actions.mdx(via @objectstack/spec)
  • content/docs/ui/apps.mdx(via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/spec)
  • content/docs/ui/field-grouping-and-order.mdx(via @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/spec)
  • content/docs/ui/translations.mdx(via @objectstack/spec)
  • content/docs/ui/views.mdx(via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

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

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

modifyAllRecords still does not widen a by-id write on an object with NO owner field (sharing abstains, the platform created_by floor holds)

2 participants

@os-project-manager@claude