#3391 的遗漏项(前端,objectui 仓)。在收口 #3546 时扫描全仓调用点发现。
背景
/me/permissions 的 effective 操作集(apiOperations)目前已接入三个面:
但主列表的「行级 CRUD」走的是一条完全独立、从未接入的链路 —— 它不经过 resolveCrudAffordances,因此上面三轮改动一次都没覆盖到它。
问题
plugin-grid/src/rowCrudAffordances.ts:49 的 resolveRowCrudAffordances() 签名里没有 effective 集参数。行级门(ObjectGrid.tsx:1479)只由三项决定:
operations ?? { update: !!onEdit, delete: !!onDelete } // ← 默认全开
∧ userActions.{edit,delete} 显式 false 的 opt-out
而 ObjectView 是无条件下传 onEdit / onDelete 的,所以视图 JSON 未显式声明 operations 时该门恒为 true。另外:
ObjectGrid 的 effectiveApiOps 只喂给 export(ObjectGrid.tsx:1266、2295);ListView.tsx:672 同理 —— 这正是 PR-4 当时的范围。
ObjectGrid 内唯一的权限调用是字段级 perms.checkField(1238),没有对象级 can()。
- 同一个
canDelete 还驱动批量删除(ObjectGrid.tsx:1615:canDelete && onBulkDelete → effectiveBulkActions = ['delete'])。
即:effective 集不含 update / delete 的调用者,主列表行 kebab 的 Edit/Delete 和批量删除仍然照常显示。批量删除是破坏性操作,风险高于 #3546 修的那批按钮。
顺带:该链路连 ADR-0103 的 bucket 锁也没接 —— rowCrudAffordances.ts 的注释写「bucket-level lock is applied upstream via the view's operations.*」,但上面的默认值说明并没有。建议一并确认。
复现(已验证)
写了一个针对真实 ObjectGrid 的组件级探针,mock usePermissions().getObjectApiOperations,带控制组:
| 用例 |
effective 集 |
行 Edit/Delete + 选择框 |
| A 基线 |
['get','list','create','update','delete'] |
出现 ✅ 符合预期 |
| B 本 issue |
['get','list'] |
仍然出现 ❌ |
| C 控制组 |
full,但 userActions:{edit:false,delete:false} |
消失 ✅ |
C 通过是关键:它证明断言确实能观测到「隐藏」,所以 B 不是假阳性。
服务端侧也确认状态 B 真实可达 —— annotateEffectiveApiOperations(plugin-hono-server/src/hono-plugin.ts:339)在对象 apiMethods 收紧曝光、或 allowExport:false 时就会下发受限数组。
⚠️ 说明:以上为组件级 + 服务端代码走查验证。未做端到端浏览器实测(本次会话缺少 preview 工具链),因此「真实 console 里点得到」这一步仍是推断。
范围(objectui)
保持与前三轮一致的语义:交集,永不并集;effective 缺失(全开对象 / 旧后端 / 未挂 PermissionProvider)回退现行为。
关联
#3391(跟踪)、#3546(detail/form 面)、objectui#2823(PR-4 工具栏)、objectui#2832、objectui#2876。
#3391 的遗漏项(前端,objectui 仓)。在收口 #3546 时扫描全仓调用点发现。
背景
/me/permissions的 effective 操作集(apiOperations)目前已接入三个面:ObjectViewImport、ListView/ObjectGridExport;RelatedRecordActionsBridge的子对象 Create/Edit/Delete。但主列表的「行级 CRUD」走的是一条完全独立、从未接入的链路 —— 它不经过
resolveCrudAffordances,因此上面三轮改动一次都没覆盖到它。问题
plugin-grid/src/rowCrudAffordances.ts:49的resolveRowCrudAffordances()签名里没有 effective 集参数。行级门(ObjectGrid.tsx:1479)只由三项决定:而
ObjectView是无条件下传onEdit/onDelete的,所以视图 JSON 未显式声明operations时该门恒为 true。另外:ObjectGrid的effectiveApiOps只喂给 export(ObjectGrid.tsx:1266、2295);ListView.tsx:672同理 —— 这正是 PR-4 当时的范围。ObjectGrid内唯一的权限调用是字段级perms.checkField(1238),没有对象级can()。canDelete还驱动批量删除(ObjectGrid.tsx:1615:canDelete && onBulkDelete → effectiveBulkActions = ['delete'])。即:effective 集不含
update/delete的调用者,主列表行 kebab 的 Edit/Delete 和批量删除仍然照常显示。批量删除是破坏性操作,风险高于 #3546 修的那批按钮。顺带:该链路连 ADR-0103 的 bucket 锁也没接 ——
rowCrudAffordances.ts的注释写「bucket-level lock is applied upstream via the view'soperations.*」,但上面的默认值说明并没有。建议一并确认。复现(已验证)
写了一个针对真实
ObjectGrid的组件级探针,mockusePermissions().getObjectApiOperations,带控制组:['get','list','create','update','delete']['get','list']userActions:{edit:false,delete:false}C 通过是关键:它证明断言确实能观测到「隐藏」,所以 B 不是假阳性。
服务端侧也确认状态 B 真实可达 ——
annotateEffectiveApiOperations(plugin-hono-server/src/hono-plugin.ts:339)在对象apiMethods收紧曝光、或allowExport:false时就会下发受限数组。范围(objectui)
resolveRowCrudAffordances()增加 effective 操作集入参,canEdit∧update、canDelete∧delete。ObjectGrid把已有的effectiveApiOps(目前只喂 export)接到行级门 + 批量删除。ListView/ 移动端卡片等其他消费rowActions的面。userActionsopt-out 的控制组用例。保持与前三轮一致的语义:交集,永不并集;effective 缺失(全开对象 / 旧后端 / 未挂
PermissionProvider)回退现行为。关联
#3391(跟踪)、#3546(detail/form 面)、objectui#2823(PR-4 工具栏)、objectui#2832、objectui#2876。