Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/action-param-visible.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@objectstack/spec': patch
'@objectstack/platform-objects': patch
---

**Action params gain a `visible` predicate; the create-user `phoneNumber` param is gated on `features.phoneNumber`.**

`ActionParamSchema` gains an optional `visible` (CEL, `ExpressionInputSchema`) evaluated against the same scope as action `visible` (`current_user`/`app`/`data`/`features`); a UI that honors it omits the param when it's false. The `sys_user` `create_user` action's `phoneNumber` param now carries `visible: 'features.phoneNumber == true'`, so the form no longer offers a Phone Number field when the opt-in `phoneNumber` auth plugin is off — otherwise the endpoint rejects it with "Phone numbers require the phoneNumber auth plugin". Pairs with the objectui `ActionParamDialog` change that evaluates `param.visible`.
5 changes: 5 additions & 0 deletions packages/platform-objects/src/identity/sys-user.object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ export const SysUser = ObjectSchema.create({
type: 'text',
required: false,
helpText: 'Sign-in phone number (E.164, e.g. +8613800000000). Required when no email is given.',
// Only offer phone when the opt-in phoneNumber auth plugin is loaded —
// otherwise the create-user endpoint rejects a phone with
// "Phone numbers require the phoneNumber auth plugin". `features.phoneNumber`
// is served in /api/v1/auth/config (getPublicConfig).
visible: 'features.phoneNumber == true',
},
{ field: 'name', required: false },
{
Expand Down
9 changes: 9 additions & 0 deletions packages/spec/src/ui/action.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ export const ActionParamSchema = lazySchema(() => z.object({
* context. Useful for edit dialogs that pre-fill from the selected row.
*/
defaultFromRow: z.boolean().optional(),
/**
* Visibility predicate (CEL) — same scope as the action-level `visible`
* (`current_user` / `app` / `data` / `features`). When it evaluates false the
* dialog omits this param entirely. Use it to hide a param that the backend
* only accepts under an opt-in capability, e.g. the create-user `phoneNumber`
* param gated on `features.phoneNumber` so the form never offers a field the
* default backend rejects. Absent = always visible.
*/
visible: ExpressionInputSchema.optional().describe('Param visibility predicate (CEL); omits the param when false.'),
}).refine(
(p) => Boolean(p.name) || Boolean(p.field),
{ message: 'ActionParam requires either "name" or "field"' },
Expand Down