Found while implementing #11703. ⛔ Deliberately not fixed there — that card's split ruling (comment 5396313132, clause ③) named this as its own card in the objectui lane and ruled that it must not hold the server-side fix.
What
clone_permission_set in packages/plugins/plugin-security/src/objects/sys-permission-set.object.ts declares its carried facets as defaultFromRow params. Per ActionParamSchema (packages/spec/src/ui/action.zod.ts), such a param is rendered by objectui's ActionParamDialog as an ordinary editable field, seeded from the row and submitted verbatim.
#11703 took that list from two facets to five. So the Clone dialog now presents, under two ordinary text inputs, five prefilled textareas holding raw JSON — description, object_permissions, field_permissions, system_permissions, row_level_security, tab_permissions. row_level_security on the platform's own member_default is a JSON array of 17+ policy objects in one input.
That is not a regression #11703 introduced so much as one it made unmissable: two blobs read as "advanced, leave it alone", five read as a form the admin is expected to fill in.
Why it is worth a card rather than a shrug
The clone path is now the platform's sanctioned way to customize a package-declared permission set — the save door refuses the in-place edit and its refusal message sends the admin here (#11513 / PR #11702). So this dialog is on the main road, not a corner.
The failure it invites is not fail-closed. A hand-edited RLS blob that is still valid JSON but wrong — a dropped policy, a mangled using clause — produces a clone that grants more or differently than the base, and the data door will accept it: permissionSetBodyFromRow() parses whatever arrives, and PermissionSetSchema validates shape, not intent. Compare #11703's own failure direction, which the ruling tolerated precisely because it was fewer grants.
The shape the ruling preferred
prefer a non-editable carry-over if surfacing three more JSON blobs in the dialog is the alternative
There is no such knob today. ActionParamSchema has visible (a CEL predicate that omits the param entirely — which would also stop it being sent, so it is not the answer), defaultValue, helpText, and the widget knobs; nothing expresses "carry this value through, show it as a read-only summary, do not invite an edit."
Options, for whoever rules on this:
- A. A
readonly / carryOver flag on ActionParam — declared in packages/spec, honoured by objectui's ActionParamDialog. Cross-repo, and it widens an authorable surface, so it is contract-first work rather than a patch. - B. Keep the params editable but render a JSON-typed field-backed param as a collapsed summary — objectui-only, no spec change; the affordance improves for every action with a JSON column param, not just this one.
- C. Move the carry-over server-side — the action stops declaring these params at all and a dedicated clone endpoint copies the facets from the source row, leaving the dialog at its original two inputs. Narrowest dialog, but it takes the clone off the generic data door, which is what makes it work under
managedBy: 'config' today.
Not measured here: which of the three the objectui renderer can actually carry, and whether any other shipped action already hits this (a sweep of defaultFromRow params bound to JSON-serialized columns would answer it).
Not measured
No test pins what the Clone dialog renders; #11703's pin 6 asserts what the action sends, which is a different question and stays green under all three options above.
Related: #11703 (the facets now carried), #11513 / PR #11702 (the ruling that made clone the sanctioned path).
Found while implementing #11703. ⛔ Deliberately not fixed there — that card's split ruling (comment 5396313132, clause ③) named this as its own card in the objectui lane and ruled that it must not hold the server-side fix.
What
clone_permission_setinpackages/plugins/plugin-security/src/objects/sys-permission-set.object.tsdeclares its carried facets asdefaultFromRowparams. PerActionParamSchema(packages/spec/src/ui/action.zod.ts), such a param is rendered by objectui'sActionParamDialogas an ordinary editable field, seeded from the row and submitted verbatim.#11703 took that list from two facets to five. So the Clone dialog now presents, under two ordinary text inputs, five prefilled textareas holding raw JSON —
description,object_permissions,field_permissions,system_permissions,row_level_security,tab_permissions.row_level_securityon the platform's ownmember_defaultis a JSON array of 17+ policy objects in one input.That is not a regression #11703 introduced so much as one it made unmissable: two blobs read as "advanced, leave it alone", five read as a form the admin is expected to fill in.
Why it is worth a card rather than a shrug
The clone path is now the platform's sanctioned way to customize a package-declared permission set — the save door refuses the in-place edit and its refusal message sends the admin here (#11513 / PR #11702). So this dialog is on the main road, not a corner.
The failure it invites is not fail-closed. A hand-edited RLS blob that is still valid JSON but wrong — a dropped policy, a mangled
usingclause — produces a clone that grants more or differently than the base, and the data door will accept it:permissionSetBodyFromRow()parses whatever arrives, andPermissionSetSchemavalidates shape, not intent. Compare #11703's own failure direction, which the ruling tolerated precisely because it was fewer grants.The shape the ruling preferred
There is no such knob today.
ActionParamSchemahasvisible(a CEL predicate that omits the param entirely — which would also stop it being sent, so it is not the answer),defaultValue,helpText, and the widget knobs; nothing expresses "carry this value through, show it as a read-only summary, do not invite an edit."Options, for whoever rules on this:
readonly/carryOverflag onActionParam— declared inpackages/spec, honoured by objectui'sActionParamDialog. Cross-repo, and it widens an authorable surface, so it is contract-first work rather than a patch.managedBy: 'config'today.Not measured here: which of the three the objectui renderer can actually carry, and whether any other shipped action already hits this (a sweep of
defaultFromRowparams bound to JSON-serialized columns would answer it).Not measured
No test pins what the Clone dialog renders; #11703's pin 6 asserts what the action sends, which is a different question and stays green under all three options above.
Related: #11703 (the facets now carried), #11513 / PR #11702 (the ruling that made clone the sanctioned path).