Uh oh!
There was an error while loading. Please reload this page.
feat: gate detail/form edit & delete on the server's effective operation set (#3546) - #2832
Merged
Merged
Conversation
Extend the #3391 PR-4 effective-operation intersection from the list/toolbar surface to the detail/form surfaces, so a record page and its forms never offer an edit/delete/create operation the server would 405. - core: isObjectInlineEditable(obj, effectiveApiOperations?) gains the same optional 2nd arg as resolveCrudAffordances — inline-edit ANDs with server `update`. - app-shell RecordDetailView: thread effective ops into the synthesized Edit/Delete header actions and the record-body inline-edit `canEdit` gate. - app-shell RelatedRecordActionsBridge: intersect each child object's Create/Edit/Delete handlers with that child's own effective set. - plugin-detail record:details: AND inline-edit with effective `update`. - plugin-form ObjectForm: blanket managed-object field lock also engages when the server denies `update` (edit) / `create` (create). Backward-compatible: missing effective set (unrestricted / old backend / no PermissionProvider) leaves the bucket+userActions decision untouched. Layers on top of the existing check('edit')/check('delete') gates (intersection). Tests: core isObjectInlineEditable effective-ops cases; a RelatedRecordActions Bridge component test asserting Create/Edit/Delete button visibility under full-CRUD / read-only / update-only / undefined effective sets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012L8EfEa157Pe6C73qRnaJH
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
os-zhuang
marked this pull request as ready for review
July 27, 2026 05:49
Uh oh!
There was an error while loading. Please reload this page.
os-zhuang added a commit
that referenced
this pull request
Jul 28, 2026
…e operation set (objectstack#3720) (#2889) The fourth surface objectstack#3391 left open. The toolbar (#2823), detail/form (#2832 + #2876) and related lists (#2832) all route through `resolveCrudAffordances`; the main list's row CRUD has its own resolver and none of those rounds reached it. Its gate was `operations ?? { update: !!onEdit, delete: !!onDelete }`, and ObjectView wires onEdit/onDelete unconditionally while view JSON rarely declares `operations` — so it was effectively always-on. A caller whose effective set carried neither `update` nor `delete` still got the row kebab's Edit/Delete and the bulk delete. - plugin-grid `resolveRowCrudAffordances` takes `managedBy` + `effectiveApiOperations` and resolves the object verdict through the shared `resolveCrudAffordances` policy, so the row gate is the same decision every other face makes. It also returns `objectCanDelete` — bulk delete rides `onBulkDelete`, a different callback from the row `onDelete`, so it must not be judged by whether the row handler happens to be wired. - plugin-grid `ObjectGrid` threads its existing `effectiveApiOps` (until now fed only to Export) into the row gate, and applies the delete verdict to bulk delete: the implicit `['delete']`, a declared `bulkActions: ['delete']`, and any `bulkActionDefs` entry with `operation: 'delete'`. Custom ids and non-delete operations pass through untouched. - plugin-list `ListView`'s own bulk bar (the non-grid views) drops its built-in `delete` under the same verdict. Also closes the ADR-0103 gap on this chain: the bucket lock was documented as applied upstream via the view's `operations.*`, but the all-open default meant it never was — an engine-owned system / append-only / better-auth object leaked a generic row Edit/Delete the engine rejects. A `userActions` opt-in still re-opens it. Intersection, never union. A missing effective set preserves current behavior. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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 freeto 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.
背景
框架 #3391 的独立 follow-up ③(前端,objectui 仓;对应 objectstack#3546)。
PR-4(objectui#2823)让列表/工具栏面(
ObjectViewImport、ListView/ObjectGridExport)接入了服务端下发的 effective 操作集(/me/permissions的apiOperations,经resolveCrudAffordances(obj, effectiveApiOperations?)第二参交集)。detail / form 面的 edit/delete 此前仍只按resolveCrudAffordances(obj)(bucket +userActions)判定,不与服务端 effective 集交集。本 PR 把同一交集扩展到 detail/form 面,使记录页及其表单永不提供服务端会 405 的 edit/delete/create。改动
isObjectInlineEditable(obj, effectiveApiOperations?)获得与resolveCrudAffordances相同的可选第二参 —— inline-edit 现在额外与服务端update取交集。RecordDetailView把该对象的 effective 操作集传入 header 合成的 Edit/Delete 动作与记录体 inline-edit 门(canEdit);RelatedRecordActionsBridge把每个子对象的 Create/Edit/Delete handler 与该子对象自身的 effective 集取交集。record:details的 inline-edit 与 effectiveupdate取交集。ObjectForm的托管对象整表字段锁,在服务端拒绝update(edit 模式)/create(create 模式)时同样生效。契约 / 兼容
向后兼容:effective 集缺失(全开对象、旧后端、或未挂
PermissionProvider)时,保持 bucket +userActions的判定不变(即今天的行为)。叠加在既有的 per-objectcheck('edit')/check('delete')权限门之上(取交集,永不取并集)。测试
isObjectInlineEditable的 effective-ops 用例:含/不含update、空集、undefined回退、bucket 已禁则服务端授权也不再开启。RelatedRecordActionsBridge组件测试:在 full-CRUD / read-only / update-only / undefined 四种 effective 集下断言 Create/Edit/Delete 按钮的显隐。record-details/ObjectForm.managedEdit/crudAffordances套件回归通过;core / plugin-detail / plugin-form / app-shell 构建(tsc + dts)全绿。关联
🤖 Generated with Claude Code
https://claude.ai/code/session_012L8EfEa157Pe6C73qRnaJH
Generated by Claude Code