Skip to content

feat(spec): declare requiredPermissions on BulkActionDefSchema (#6257) - #6332

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-6257-bulk-action-required-permissions
Aug 7, 2026
Merged

feat(spec): declare requiredPermissions on BulkActionDefSchema (#6257)#6332
baozhoutao merged 1 commit into
mainfrom
claude/issue-6257-bulk-action-required-permissions

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Closes #6257(objectui 侧镜像单:objectstack-ai/objectui#3564)。

改了什么

BulkActionDefSchema 增加可选 requiredPermissions?: string[],语义与 action.requiredPermissions 逐字一致:缺省/空数组恒通过、多项取 AND、客户端解析不出调用者能力时 fail-open(服务端为准)。渲染层一行未动——objectui#3492 起 BulkActionBar 就在按这个键过滤,本单只是补上「合法写法」这一半(enforced ≠ declarable 的镜像缺口)。数据面 def(update/delete)上这个键只管显隐;写入本身仍由数据 API 的对象权限与服务端 hook 授权。

配套(容易漏的 CI 门,均已过):

  • BULK_ACTION_DEF_KEYS did-you-mean 键池加入新键;ActionSchema 的近似拼写别名(permissions/capabilities/requiresPermissions/requiredCapabilities/acl)在本 schema 上同样重命名到位 —— alias-integrity 全绿
  • gen:schema 产物 authorable-surface/ui.json + gen:docs 产物 content/docs/references/ui/bulk-action.mdx 已再生;check:generated 10/10 全绿
  • 手写指南 content/docs/ui/views.mdx 补「Gating a def by capability」一段
  • changeset:@objectstack/spec minor

showcase 夹具(永久保留)

showcase_project.default 补上 #6157 显隐矩阵钉不住的那一格——内联数据面 def 的能力门:

  • relabel_opsupdate + patch,门 showcase.export_data(Ops 持有)
  • purge_restricteddelete,门 showcase.restricted_ops(特意无人持有,见 security/capabilities.ts)

另加 e2e/bulk-capability-gate.spec.ts(playwright),钉住 admin 负向两格:未加门 4 个按钮可见 + 两个带门按钮同时不可见。

真机 UI 实测(console dev :5190 → showcase --fresh :4010,admin 勾选全部 5 行)

步骤 admin 授予 purge_restricted 声明 批量条实测
① baseline 仅平台能力 ['showcase.restricted_ops'] 4 个未加门按钮;两个带门按钮都不在
② 授予 showcase_ops +showcase.export_data 同上 Relabel (Ops) 出现;Purge 仍不在
③ 声明翻转 同 ② [] Purge (Restricted) 出现
④ 声明还原 同 ② ['showcase.restricted_ops'] Purge 再次消失;Relabel 仍在

同一用户、同一批记录,只动声明或授权——门是活的,admin 也不豁免(能力门读的是授予,不是 admin 位),与 #6257 正文实测结论一致。

测试

  • @objectstack/spec 全量 8500 passed (332 files),含新增 8 条 schema 测试(delete/update+patch/aggregate 三形态、AND、空数组、可选性、非数组拒绝、别名重命名)
  • showcase verify:validate ✓(rc.5 下同样写法硬失败 Unrecognized key(s): requiredPermissions)+ typecheck ✓ + 146 passed (13 files)
  • check:generated 10/10 ✓,changed-files eslint ✓

过程中记录的既有缺口(另开 issue,不在本 PR 修)

hono current-user-endpoints 的独立上下文解析器不读 sys_user_position/sys_position_permission_set,岗位绑定的能力到不了 /me/permissions(上面 ② 一步因此改用 sys_user_permission_set 用户直绑做正向对照)。随后以独立 issue 记录。

🤖 Generated with Claude Code

https://claude.ai/code/session_01PD7tZG1vENc5peMaLQC1uD


Generated by Claude Code

The selection bar has filtered buttons on def.requiredPermissions since
objectui#3492, but the .strict() schema never declared the key, so no
legal metadata could reach that filter — enforced ≠ declarable. The forms
with no workaround were the inline data-plane defs (operation:
'update' | 'delete'): they dispatch no action, so unlike a def promoted
from bulkActions: ['<name>'] they have nothing to inherit a gate from,
and a declarative bulk delete stayed visible to every caller who could
open the list, rejected only per record after the click.

- BulkActionDefSchema: optional requiredPermissions: string[], with
  action.requiredPermissions semantics verbatim (absent/empty pass,
  entries AND, unresolvable caller capabilities fail open; on a
  data-plane def the gate governs visibility only — the write is still
  authorized by the data API). ActionSchema's near-miss aliases
  (permissions/capabilities/requiresPermissions/requiredCapabilities/acl)
  rename onto the key here too, and it joins the did-you-mean pool.
- Regenerated authorable-surface/ui.json and the bulk-action reference
  page; new guide paragraph in content/docs/ui/views.mdx.
- Showcase: the two inline gated defs the #6157 matrix could not pin, on
  showcase_project.default — relabel_ops (update + patch, gated on the
  Ops-held showcase.export_data) and purge_restricted (delete, gated on
  the granted-to-nobody showcase.restricted_ops) — plus a playwright spec
  pinning the admin-negative cells of the selection bar.
- Schema tests: every def form accepts the gate, empty array and
  optionality pinned, non-array rejected, aliases rename.

No renderer change: objectui's BulkActionDef type and BulkActionBar
filter shipped in objectui 11 (objectui#3548).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PD7tZG1vENc5peMaLQC1uD
@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 7, 2026 1:56pm

Request Review

@github-actions

github-actions Bot commented Aug 7, 2026

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 free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/m tests tooling

Projects

None yet

2 participants