You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(spec): userActions.edit/delete accept per-record CEL predicates (objectui#2614) (#3076)
* feat(spec): userActions.edit/delete accept per-record CEL predicates (objectui#2614)
Extend the object-level userActions.edit / userActions.delete flags from
plain booleans to a union with an object form
{ enabled?, visibleWhen?, disabledWhen? } (RowCrudActionOverrideSchema),
so the built-in row Edit/Delete affordances can be hidden or disabled per
record via CEL predicates — the same evaluation contract custom actions
already use. Semantics: visibleWhen false → not rendered (fail-closed);
disabledWhen true → rendered disabled (fail-soft). The predicates are
advisory UI gating; server enforcement stays with permissions/hooks.
resolveCrudAffordances() keeps returning the resolved booleans (enabled
falls back to the managedBy bucket default) and now surfaces the
predicates as editPredicates / deletePredicates, pass-through as
authored. Boolean-only inputs produce byte-identical output — zero
behavior change for existing schemas.
clampManagedObjectWrites (ADR-0092 D2 hint clamp) treats the object form
by its explicit enabled flag only: per-record predicates are not a write
grant, so a managed object stays fail-closed unless enabled === true.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HnCZhYpQjRyg2E44RHBiNE
* chore: add changeset for objectui#2614 spec slice
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HnCZhYpQjRyg2E44RHBiNE
* chore(spec): regenerate api-surface snapshot for RowCrudActionOverride exports
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HnCZhYpQjRyg2E44RHBiNE
* test(dogfood): classify userActions row-CRUD predicates in the ADR-0058 expression ledger
The new data/object.zod.ts:visibleWhen / :disabledWhen surfaces
(objectui#2614) tripped the conformance ratchet. Two rows, matching
their actual fail policies: visibleWhen is fail-closed (a faulting
predicate hides the row button), disabledWhen is fail-soft-log (a
faulting predicate leaves it enabled; server hooks are the boundary).
Both interpret on the canonical celEngine via objectui useRowPredicate.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HnCZhYpQjRyg2E44RHBiNE
* docs(showcase): demo per-record row Edit/Delete CEL gating on Invoice (objectui#2614)
A PAID invoice's fields already freeze via readonlyWhen; the built-in
row actions now follow the same truth: Edit renders DISABLED on paid
rows (disabledWhen), Delete is HIDDEN outright (visibleWhen). Draft and
sent invoices keep the untouched menu. Browser-verified against the
objectui HMR console: paid row menu = greyed Edit only; sent row menu =
enabled Edit + Delete.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HnCZhYpQjRyg2E44RHBiNE
---------
Co-authored-by: Claude <noreply@anthropic.com>
enforcement: 'console (objectui) RowActionMenu BuiltinRowActionItem + data-table DataTableBuiltinRowActionItem → useRowPredicate → @objectstack/formula celEngine (interpret); TRUE renders the button disabled, a fault leaves it enabled (server hooks are the real boundary)',
0 commit comments