Found while implementing #5542. Filed unassigned for PM triage — outside that card's
declared file surface (the type declaration and its pin, not the merge logic).
Mechanism
apps/console/src/components/FormPage.tsxbuildSections merges a FormView's field
overrides with the target object's field definitions. Its docstring states the rule, at
:340 on the merged ref cad512fe1:
* Field-level FormField overrides take precedence over object defaults.
Every key in the loop is built that way — override.label ?? def.label,
override.required ?? def.required, override.readonly ?? false, and so on. One is
not, at :367:
maxLength: def.maxLength,
No override.maxLength ??. The object schema's ceiling wins unconditionally, and the
form's own is discarded.
It is load-bearing, not decorative — the value reaches the DOM twice, at :875 and
:983:
maxLength={field.maxLength}
So an author who sets a tighter per-form limit (a short public intake form over a field
whose object-level ceiling is generous) gets the generous one, silently. There is no
diagnostic, and the form still submits, so the symptom is a value the author believed
was refused at the input being accepted.
Why it survived
The console's local FormFieldSpec did not declare maxLength at all until #5542, so
nobody typing a spec in this app could write the override in the first place — the key
was unreachable from the type side, and the merge gap it exposes was therefore never
exercised. #5542 converged that type onto the shared app-shell declaration, which does
declare maxLength, so the key is now writable here and lands on the inert branch.
The behaviour is unchanged by #5542 in both directions: the runtime always ignored the
override, and it still does. What changed is that the gap is now expressible, which is
why it is worth recording rather than leaving as an accident of a too-narrow type.
FormPage.fieldSpec.test.ts (added by #5542) records the current answer explicitly
rather than assuming it:
expect(row.maxLength).toBeUndefined();
so whichever way triage rules, the existing pin says which behaviour is being changed.
The decision triage owns
Two coherent outcomes, and picking by "which is less work" would be wrong:
- honour it —
maxLength: override.maxLength ?? def.maxLength, matching the
docstring and every sibling key. One line, and the docstring becomes true. - declare it object-only — if a per-form ceiling is deliberately not a thing (a
storage constraint is not a presentation choice), then the docstring's blanket claim
is what is wrong, and it should name the exception.
Related but distinct: #5201 and #5253 (both closed) recorded max_length ceilings
failing to reach the DOM in the built-in form branches. Same key, different renderer and
different mechanism — those were spelling/lookup failures, this one is a merge branch
that was never written.
Boundary
Found while implementing #5542. Filed unassigned for PM triage — outside that card's
declared file surface (the type declaration and its pin, not the merge logic).
Mechanism
apps/console/src/components/FormPage.tsxbuildSectionsmerges a FormView's fieldoverrides with the target object's field definitions. Its docstring states the rule, at
:340on the merged refcad512fe1:Every key in the loop is built that way —
override.label ?? def.label,override.required ?? def.required,override.readonly ?? false, and so on. One isnot, at
:367:No
override.maxLength ??. The object schema's ceiling wins unconditionally, and theform's own is discarded.
It is load-bearing, not decorative — the value reaches the DOM twice, at
:875and:983:So an author who sets a tighter per-form limit (a short public intake form over a field
whose object-level ceiling is generous) gets the generous one, silently. There is no
diagnostic, and the form still submits, so the symptom is a value the author believed
was refused at the input being accepted.
Why it survived
The console's local
FormFieldSpecdid not declaremaxLengthat all until #5542, sonobody typing a spec in this app could write the override in the first place — the key
was unreachable from the type side, and the merge gap it exposes was therefore never
exercised. #5542 converged that type onto the shared app-shell declaration, which does
declare
maxLength, so the key is now writable here and lands on the inert branch.The behaviour is unchanged by #5542 in both directions: the runtime always ignored the
override, and it still does. What changed is that the gap is now expressible, which is
why it is worth recording rather than leaving as an accident of a too-narrow type.
FormPage.fieldSpec.test.ts(added by #5542) records the current answer explicitlyrather than assuming it:
so whichever way triage rules, the existing pin says which behaviour is being changed.
The decision triage owns
Two coherent outcomes, and picking by "which is less work" would be wrong:
maxLength: override.maxLength ?? def.maxLength, matching thedocstring and every sibling key. One line, and the docstring becomes true.
storage constraint is not a presentation choice), then the docstring's blanket claim
is what is wrong, and it should name the exception.
Related but distinct: #5201 and #5253 (both closed) recorded
max_lengthceilingsfailing to reach the DOM in the built-in form branches. Same key, different renderer and
different mechanism — those were spelling/lookup failures, this one is a merge branch
that was never written.
Boundary
override precedence phrasings). Nothing open covers this renderer's merge gap.