Skip to content

Object-level metadata payloads emit three keys ObjectSchema refuses by name (group, sortOrder, relationships) — the #5761 parity gate reaches field shapes only #6223

Description

@yinlianghui

Found while fixing objectui#6041 / objectui#6044 (the field-level members of the #5761 parity family). Filed, not fixed — out of the scope of those cards, and each key plausibly takes a different correct resolution, which is the #5761 ruling.

The measurement

The gate built for #5761 (scripts/check-designer-field-key-parity.mjs) compares declared payload keys against FieldSchema. Its PAYLOAD_SHAPES list contains three field shapes and no object shape, so nothing checks the parent document the designers actually PUT.

Measured against the installed @objectstack/spec 17.2.0, ESM build (dist/data/index.mjs), on origin/main @ 7da7b8a1d:

const base = { name: 'account', label: 'Account', fields: { n: { type: 'text', label: 'N' } } };
ObjectSchema.safeParse(base) => success = true (control)
ObjectSchema.safeParse({ ...base, isSystem: true }) => success = true (control)
ObjectSchema.safeParse({ ...base, pluralLabel: 'A' }) => success = true (control)
ObjectSchema.safeParse({ ...base, group: 'Sales' }) => success = false
unrecognized_keys keys=["group"]
ObjectSchema.safeParse({ ...base, sortOrder: 3 }) => success = false
unrecognized_keys keys=["sortOrder"]
ObjectSchema.safeParse({ ...base, relationships: [ … ] }) => success = false
unrecognized_keys keys=["relationships"]

ObjectSchema's accept set is 42 keys and contains none of the three. The controls matter: isSystem and pluralLabel are accepted, so this is a real key-by-key result and not a schema that refuses everything.

The writers

Both are on the wire — the body of PUT /api/v1/meta/object/:name.

  • packages/app-shell/src/services/MetadataService.tsObjectMetadataPayload declares group, sortOrder and relationships; toObjectPayload populates all three and saveObject PUTs it.
  • packages/plugin-designer/src/MetadataObjectsPage.tsx — the merged ServerObjectSchema written on save carries group verbatim.

group is the live one: the Object Manager renders a grouping control, and toObjectDefinition populates group unconditionally ('System Objects' / 'Custom Objects' in metadataConverters, raw.group in MetadataObjectsPage). So saving an object through the designer looks like the exact shape #5761 describes — a hard 422 INVALID_METADATA that then blocks every later save of that object, with nothing in the UI to say which key did it. Whether it is live today depends on what the deployed route parses with, which is worth measuring rather than assuming — this issue reports the schema fact, not a reproduced HTTP response.

Why this is not a mechanical rename

Same reason #5761 gave for the field-level keys, and the reason it ruled one card per key:

Suggested shape of the fix

Extend PAYLOAD_SHAPES with the object-level shapes and give the gate a second oracle (ObjectSchema alongside FieldSchema), so the class is closed one level up rather than three more tombstones being written after the fact. The gate's ledger already ratchets in both directions and would carry these three the same way it carries formula and sortOrder.

Refs: #5761 (the gate) · #6041 · #6044 · #6045 · #4644 · #4687 · #4676

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatched

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions