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
spec/ui: FormField minLength/maxLength (and the number-constraint quartet) still carry the pre-#11566 shape — z.number().optional(), no integer/positivity validation #12174
Found while implementing #11949 (minLength tightening on data/field.zod.ts). Filed unassigned — same defect class, different surface, and the applicability story differs enough that it is not a mechanical rider.
What
FormFieldBaseSchema (packages/spec/src/ui/view.zod.ts, the form-designer field row) declares its own text/number constraint keys:
maxLength: z.number().optional() — "Maximum character length (for text/textarea/email/url/phone)"
minLength: z.number().optional() — "Minimum character length"
min / max / precision / scale — all bare z.number().optional()
So maxLength: 0, minLength: -5, scale: 2.5 all parse cleanly on a form field — the exact shapes #11566 (data maxLength), #11949 (data minLength) and #8321 (data scale/precision) now refuse on the object-field surface, for the same "a malformed count has no defined meaning" argument.
Applicability is a different question here. A form field row references an object field by field name and carries only an optional type override, so "refuse the key outside BOUNDED_STRING_FIELD_TYPES" has no direct analogue when type is omitted (the common case) — the referenced object field's type is not visible to this schema at parse time.
Measure the readers first (objectui form renderer, public-form resolve path), then either: (a) shape-tighten in place (z.number().int().min(1) for the length pair, int().min(0) for precision/scale) if the keys are live; or (b) retire them from the form-field surface if nothing reads them (the object field already declares the same constraints authoritatively — two declarations of one bound is the drift shape #12017 names).
Dedup note: searched by local grep (liveness ledger, audits, view.zod.ts comments — no tracking card referenced). The container's REST issue-list channel was unavailable this session (proxy 403), so the open-issue keyword sweep could not be run; PM triage should dedup before queueing.
Found while implementing #11949 (
minLengthtightening ondata/field.zod.ts). Filed unassigned — same defect class, different surface, and the applicability story differs enough that it is not a mechanical rider.What
FormFieldBaseSchema(packages/spec/src/ui/view.zod.ts, the form-designer field row) declares its own text/number constraint keys:maxLength: z.number().optional()— "Maximum character length (for text/textarea/email/url/phone)"minLength: z.number().optional()— "Minimum character length"min/max/precision/scale— all barez.number().optional()So
maxLength: 0,minLength: -5,scale: 2.5all parse cleanly on a form field — the exact shapes #11566 (datamaxLength), #11949 (dataminLength) and #8321 (datascale/precision) now refuse on the object-field surface, for the same "a malformed count has no defined meaning" argument.Why it is not a mechanical copy of #11949
fieldname and carries only an optionaltypeoverride, so "refuse the key outsideBOUNDED_STRING_FIELD_TYPES" has no direct analogue whentypeis omitted (the common case) — the referenced object field's type is not visible to this schema at parse time.packages/spec/liveness/view.json, the FormField note). Whether any renderer/validator reads the form-levelminLength/maxLengthat all needs measuring before choosing between the spec:maxLengthis authorable on every field type and validated as no more than a number —maxLength: 0andmaxLength: 12.5parse cleanly #11566 template (tighten the shape) and ADR-0049 enforce-or-remove (the keys may be declared-but-inert on this surface entirely).Decision this needs
Measure the readers first (objectui form renderer, public-form resolve path), then either: (a) shape-tighten in place (
z.number().int().min(1)for the length pair,int().min(0)forprecision/scale) if the keys are live; or (b) retire them from the form-field surface if nothing reads them (the object field already declares the same constraints authoritatively — two declarations of one bound is the drift shape #12017 names).Dedup note: searched by local grep (liveness ledger, audits,
view.zod.tscomments — no tracking card referenced). The container's REST issue-list channel was unavailable this session (proxy 403), so the open-issue keyword sweep could not be run; PM triage should dedup before queueing.