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
fix(spec): fold FormViewSchema.groups into sections at the producer (#6926) (#7128)
* fix(spec): fold FormViewSchema.groups into sections at the producer (#6926)
`FormViewSchema` declared `groups` as "Legacy support -> alias to sections"
and nothing in this repo performed the fold. The alias was honored exactly one
boundary downstream, inside ObjectUI's renderer, so a `groups`-authored public
form rendered in the console and degraded on all three REST public-form routes,
which read `sections` only.
The fold now happens at the producer, as a `.overwrite()` on `FormViewSchema`:
groups-only folds onto `sections`, `sections` wins when both are present (the
renderer's own `sections ?? groups` rule, so nothing that renders today renders
differently), and `groups` is absent from every parsed form. Declared once and
inherited by every parse door — `ViewSchema.form` / `.formViews.*`, both
`ViewItemSchema` form arms, and `ViewMetadataSchema`'s container and flattened
form-overlay members.
`.overwrite()` rather than `.transform()`, measured: a transform returns a
ZodPipe, which breaks `FormViewSchema.extend()` for the overlay member and makes
`overlayTypeValues()` answer with an empty set — a silent mis-dispatch.
The acceptance face is unchanged: `groups` stays a legal authoring key, and the
`pane` refinement still reports `groups.0.pane`, the path the author wrote.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiRUoQkTSBBmpyXBY3cVn2
* docs(spec): record that the two objectui folds disagree on empty `sections` (#6926)
Verified first-hand against objectui @5e52495 while confirming the precedence
this fold was told to pin. `spec-bridge/bridges/form-view.ts` uses
`spec.sections ?? spec.groups`, so an EMPTY `sections` wins; `plugin-form/
ObjectForm.tsx` gates on `!folded.sections?.length`, so there the alias wins
when `sections` is empty. The fold picks the primary path's answer — an alias is
consulted when the canonical key is absent, and a fallback-on-empty is the
lenient-consumer shape this change exists to remove.
Also records that ObjectForm's fold rewrites sub-keys (title -> label,
defaultCollapsed -> collapsed) as a renderer-local adaptation, so nobody later
mistakes it for spec semantics and reproduces it here.
Comment only; no behavior change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PiRUoQkTSBBmpyXBY3cVn2
* test(spec): use a valid dotted ViewItem name in the #6926 parse-door pin
* docs(spec): regenerate view reference for the folded groups alias (#6926)
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|**defaultSort**|`never`| optional |[REMOVED]`form.defaultSort` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — nothing read it: a related list inside a form sorts by its own list view's `sort`. Delete the key and set the sort on the related list view instead. Run `os migrate meta --from 16` to rewrite existing sources automatically. |
268
268
|**sharing**|`{ enabled?: boolean; publicLink?: string; password?: string; allowedDomains?: string[]; … }`| optional | Public sharing configuration for this form |
Copy file name to clipboardExpand all lines: packages/spec/liveness/view.json
+4-1Lines changed: 4 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -293,7 +293,10 @@
293
293
},
294
294
"groups": {
295
295
"status": "live",
296
-
"note": "objectui: legacy alias of sections, normalized at ObjectForm.tsx:90 and spec-bridge form-view.ts:169 (spec.sections ?? spec.groups). Audit L24 drift resolved by alias-at-one-boundary."
296
+
"verifiedAt": "2026-08-09",
297
+
"evidenceScope": "cross-repo",
298
+
"evidence": "packages/spec/src/ui/view.zod.ts (foldFormGroupsIntoSections + the .overwrite on FormViewSchema — the PRODUCER fold, #6926: groups-only folds onto sections, sections wins when both are present, and groups is absent from every parsed form); objectui: packages/react/src/spec-bridge/bridges/form-view.ts:169 packages/plugin-form/src/ObjectForm.tsx:129-142 (objectui @7b3e048 — the pre-existing boundary folds, now redundant for parsed forms and retiring in a later cross-repo lap)",
299
+
"note": "WHERE THE FOLD LIVES: at the producer, as of #6926 — a `.overwrite()` on FormViewSchema, inherited by every parse door (ViewSchema.form/.formViews.*, both ViewItemSchema form arms, and ViewMetadataSchema's container AND flattened form-overlay members, which picks it up through .extend()). Before #6926 the alias was declared but folded NOWHERE in this repo: it was honored one boundary downstream in objectui (alias-at-one-boundary, objectui#2545, after a groups-only spec rendered nothing), while the framework's REST public-form routes read `sections` only — so the same authored form rendered in the console and degraded on GET /forms/:slug, POST /forms/:slug/submit and GET /forms/:slug/lookup/:field. That omission is what let #6926 be filed reading a live key as dead; it is recorded here so the next reader cannot repeat it. STILL NOT FOLDED (measured 2026-08-09, #6926): a RUNTIME-saved sys_metadata row — saveMetaItem validates through ViewMetadataSchema and then deliberately discards parsed.data to keep Studio round-trip keys, and the read replays the ADR-0087 stored-row conversion chain, which is not a zod parse. Code-authored views (defineView/defineForm → registry) DO reach REST folded. Pre-parse consumers still read the authored key and are right to: packages/lint's view rules walk authored sources. Audit L24 drift resolved by alias-at-one-boundary; superseded by the producer fold."
0 commit comments