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
Found while implementing #4069 (PR #4084). Filed unassigned; deliberately out of
that card's scope, which the maintainer's ruling framed in terms of the static required flag.
#4069 ruled that in create mode a field declaring a runtime defaultValue
(a DEFAULT_VALUE_TOKENS member — 'NOW()' / 'current_user' — or a CEL
Expression envelope) suppresses the client-side required rule and is omitted
from the payload: the control is deliberately left empty so ObjectQL.applyFieldDefaults resolves the declaration at insert, so the field
is not "missing", it is server-owned.
PR #4084 implements that on the static flag. It resolves the effective required when a runtime form field is built from the object schema, in packages/plugin-form — ObjectForm, sectionFields (serving Modal / Drawer /
Tabbed / Split / Wizard) and the two no-sections paths.
requiredWhen is resolved downstream, in the form renderer
(packages/components/src/renderers/form/form.tsx), by resolveFieldRuleState
against the live record — it OVERRIDES the static flag that #4084 computes. So
when the predicate resolves TRUE on a create form, the field is required again,
the control is still empty by design, and the submit is refused with nothing
sensible for the user to type. Exactly the shape #4069 describes, one layer over.
It is not obviously the same answer. A static required is an
unconditional storage claim, and the producer's guarantee always covers it. A requiredWhen predicate says "required in this state", which an author may
well intend as a claim about what the USER must supply in that state —
plausibly outranking the declared default rather than yielding to it. Someone
has to rule which reading wins; guessing risks silently disabling a rule an
author wrote on purpose.
Not measured
No occurrence found in the shipped example apps — the same note #4069 carried
about its own combination, which had none either and was still ruled worth
fixing. Filing plainly for triage to grade rather than sitting on it; severity
judged at filing time is unreliable in both directions.
Reproduce
packages/plugin-form/src/createDefaults.test.tsx (extended in PR #4084) has the
ready-made fixture: RUNTIME_OBJECT_SCHEMA builds one required field per runtime
shape straight from the spec's DEFAULT_VALUE_TOKENS. Replace one field's required: true with a requiredWhen that resolves TRUE and re-run the
"submits with the runtime-default fields left empty" pin.
Found while implementing #4069 (PR #4084). Filed unassigned; deliberately out of
that card's scope, which the maintainer's ruling framed in terms of the static
requiredflag.What #4084 fixed, and where it stops
#4069 ruled that in create mode a field declaring a runtime
defaultValue(a
DEFAULT_VALUE_TOKENSmember —'NOW()'/'current_user'— or a CELExpression envelope) suppresses the client-side
requiredrule and is omittedfrom the payload: the control is deliberately left empty so
ObjectQL.applyFieldDefaultsresolves the declaration at insert, so the fieldis not "missing", it is server-owned.
PR #4084 implements that on the static flag. It resolves the effective
requiredwhen a runtime form field is built from the object schema, inpackages/plugin-form—ObjectForm,sectionFields(serving Modal / Drawer /Tabbed / Split / Wizard) and the two no-sections paths.
The conditional spelling is untouched:
requiredWhenis resolved downstream, in the form renderer(
packages/components/src/renderers/form/form.tsx), byresolveFieldRuleStateagainst the live record — it OVERRIDES the static flag that #4084 computes. So
when the predicate resolves TRUE on a create form, the field is required again,
the control is still empty by design, and the submit is refused with nothing
sensible for the user to type. Exactly the shape #4069 describes, one layer over.
Why it was not folded into #4084
Two reasons, both worth a separate decision rather than a silent widening:
packages/components' formrenderer, or thread a "this field is producer-owned" fact into
resolveFieldRuleStatein@object-ui/core. A required field whosedefaultValueis a runtime token (NOW()/current_user) cannot be submitted from a create form #4069's card was explicitlyscoped to
packages/plugin-form.requiredis anunconditional storage claim, and the producer's guarantee always covers it. A
requiredWhenpredicate says "required in this state", which an author maywell intend as a claim about what the USER must supply in that state —
plausibly outranking the declared default rather than yielding to it. Someone
has to rule which reading wins; guessing risks silently disabling a rule an
author wrote on purpose.
Not measured
No occurrence found in the shipped example apps — the same note #4069 carried
about its own combination, which had none either and was still ruled worth
fixing. Filing plainly for triage to grade rather than sitting on it; severity
judged at filing time is unreliable in both directions.
Reproduce
packages/plugin-form/src/createDefaults.test.tsx(extended in PR #4084) has theready-made fixture:
RUNTIME_OBJECT_SCHEMAbuilds one required field per runtimeshape straight from the spec's
DEFAULT_VALUE_TOKENS. Replace one field'srequired: truewith arequiredWhenthat resolves TRUE and re-run the"submits with the runtime-default fields left empty" pin.
Generated by Claude Code