Observation
buildDefaultPageSchema emits the Reference Rail's region as
{name: 'aside',width: 'small',className: 'hidden xl:flex flex-col gap-4',components: […]}PageRegionSchema (@objectstack/spec, packages/spec/src/ui/page.zod.ts) declares
name / width / components only, and it is closed under the same ADR-0089 D3a
.strict() flip as the page component shape. Parsing that region against the vendored
spec (17.0.0-rc.6) gives:
unrecognized_keys | <root> | Unrecognized key(s) on this page region: `className`.
Until #4001 closed this shape these were dropped silently — the page still rendered,
without whatever the key was meant to configure.
So a synthesized page that carries the Reference Rail has no spelling a server write
would accept.
Why this is filed as an observation, not a defect
It is not reachable from any persisted payload today. The only path that stores a
synthesized page is Studio's page-create seed
(packages/app-shell/src/views/metadata-admin/anchors.ts → createSeed), which calls
buildDefaultPageSchema(objectDef) with no options — so showReferenceRail is off,
slots.rightRail is empty, and the aside region is never emitted into the PUT. Every
other caller (RecordDetailView, PagePreview) renders the tree in the browser and
never writes it, where the region's className is honoured by RegionContent
(packages/components/src/renderers/layout/page.tsx) and everything works.
It is worth recording because it is the same defect class as #4232 (which fixed the
component-level half — props now go in the spec's properties carrier), and because the
day anything persists a page with the rail on, that write fails the same way page-create
did.
Why #4232 did not fix it
Unlike recordChrome / items, this key has no spec-shaped carrier. The options and
their costs, so whoever picks this up does not have to re-derive them:
- Drop the
className — loses the responsive hide (hidden xl:) and the rail's own
flex flex-col gap-4 spacing. The rail would render at every width, taking a column
from the main content on laptop widths, which is the layout the class exists to prevent. - Move it onto the child components —
PageComponentSchemadoes declare className
and responsiveStyles, but the hide has to apply to the region wrapper: hiding the
children leaves an empty column occupying its width below xl. The gap-4 between
siblings is a container concern and has no per-child spelling at all. - Give
PageRegionSchema a carrier (a className, or an ADR-0065 responsiveStyles
at region level) — an objectstack-lane spec change, and the only option that keeps the
semantics intact. Needs the usual "is there real business pull" read: today the only
author of a region className is this synthesizer.
Evidence
Measured on objectui origin/main @ 49ae9f42d with the vendored @objectstack/spec
17.0.0-rc.6, by parsing buildDefaultPageSchema(def, { showReferenceRail: true, related: [ …2 lists ] })'s
aside region with PageRegionSchema.safeParse.
Related: #4232 (component-level half, fixed).
Generated by Claude Code
Observation
buildDefaultPageSchemaemits the Reference Rail's region asPageRegionSchema(@objectstack/spec,packages/spec/src/ui/page.zod.ts) declaresname/width/componentsonly, and it is closed under the same ADR-0089 D3a.strict()flip as the page component shape. Parsing that region against the vendoredspec (17.0.0-rc.6) gives:
So a synthesized page that carries the Reference Rail has no spelling a server write
would accept.
Why this is filed as an observation, not a defect
It is not reachable from any persisted payload today. The only path that stores a
synthesized page is Studio's page-create seed
(
packages/app-shell/src/views/metadata-admin/anchors.ts→createSeed), which callsbuildDefaultPageSchema(objectDef)with no options — soshowReferenceRailis off,slots.rightRailis empty, and theasideregion is never emitted into the PUT. Everyother caller (
RecordDetailView,PagePreview) renders the tree in the browser andnever writes it, where the region's
classNameis honoured byRegionContent(
packages/components/src/renderers/layout/page.tsx) and everything works.It is worth recording because it is the same defect class as #4232 (which fixed the
component-level half — props now go in the spec's
propertiescarrier), and because theday anything persists a page with the rail on, that write fails the same way page-create
did.
Why #4232 did not fix it
Unlike
recordChrome/items, this key has no spec-shaped carrier. The options andtheir costs, so whoever picks this up does not have to re-derive them:
className— loses the responsive hide (hidden xl:) and the rail's ownflex flex-col gap-4spacing. The rail would render at every width, taking a columnfrom the main content on laptop widths, which is the layout the class exists to prevent.
PageComponentSchemadoes declareclassNameand
responsiveStyles, but the hide has to apply to the region wrapper: hiding thechildren leaves an empty column occupying its width below
xl. Thegap-4betweensiblings is a container concern and has no per-child spelling at all.
PageRegionSchemaa carrier (aclassName, or an ADR-0065responsiveStylesat region level) — an objectstack-lane spec change, and the only option that keeps the
semantics intact. Needs the usual "is there real business pull" read: today the only
author of a region
classNameis this synthesizer.Evidence
Measured on objectui
origin/main@49ae9f42dwith the vendored@objectstack/spec17.0.0-rc.6, by parsing
buildDefaultPageSchema(def, { showReferenceRail: true, related: [ …2 lists ] })'sasideregion withPageRegionSchema.safeParse.Related: #4232 (component-level half, fixed).
Generated by Claude Code