Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions .changeset/7650-retired-dialect-choke-point.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,26 @@ Canonicalize the retired object-schema dialect once, at the ingestion choke poin
`normalizeSchemaReferenceKeys` now has two arms. The `reference` / `reference_to` pair
is unchanged. The new arm folds any key a served field def carries that
`@objectstack/spec`'s `FieldSchema` does **not** declare, but whose snake/camel twin it
does — `display_field` onto `displayField`, `description_field` onto `descriptionField`,
`lookup_filters` onto `lookupFilters`, and `lookup_columns` onto `lookupColumns`.
does — `display_field` onto `displayField`, `lookup_filters` onto `lookupFilters`, and so
on.

**The accepted set is MEASURED, not enumerated — and it grows with the linked spec**
(corrected on objectui#8938; this paragraph previously read as though the keys the cards
in this family happened to name were the whole of it). One spelling rule is applied to
`FieldSchema`'s **entire** declared key set at run time, so the accepted set is a property
of the installed `@objectstack/spec` and widens the moment the spec grows a camel key.
Besides the four above, today's spec puts the gate keys `visible_when` / `readonly_when` /
`required_when`, `default_value`, `required_permissions`, `masking_rule`, `track_history`,
`delete_behavior`, `external_id`, `depends_on`, `lookup_page_size`, the `related_list*` and
`inline_*` families, and the managed-by lock keys `_lock_reason` / `_lock_source` /
`_lock_docs_url` / `_package_id` / `_package_version` inside it — and case / kebab variants
of every one of them fold too. A stored legacy spelling of any of these is therefore
**active** on the client where consumers previously ignored it.

No count of that surface is written here on purpose: it is derived from the installed spec,
and a number in this paragraph would be derived once and never again. The instrument that
re-derives it on every run is the pin named `the width IS the spec's declared key set, not
a list anyone typed`, beside the classes above as a live membership assertion.

**Why this is needed at all.** The object-schema serve path never parses:
`ObjectStackAdapter.getObjectSchema` fetches the document, applies two mutations and
Expand All @@ -35,8 +53,10 @@ share. And it does not "correct" anything: a key that probes onto no declared ke
alone, so a typo (`sortible`) stays a typo and `id_field` — which has no declared
successor — stays as it is.

**Not covered.** `id_field` needs a `@objectstack/spec` release carrying the
`FIELD_KEY_GUIDANCE.id_field` row before its diagnostic can quote the contract rather than
a copy of it; that row is in no published version yet. `title_format` is out of scope
pending a separate maintainer ruling. Both land in the leave arm by the same rule, with no
special case.
**Not covered.** `id_field` and `title_format` are not folded — `id_field` has no declared
successor and `title_format` is out of scope pending a separate maintainer ruling. Both land
in the leave arm by the same rule, with no special case. What still waits on a
`@objectstack/spec` release carrying the `FIELD_KEY_GUIDANCE.id_field` row is the
**successor guidance** for `id_field`, which no published version carries; the leave arm
itself is no longer silent (objectui#8938 — the diagnostic states what it measured against
the linked spec rather than quoting a copy of contract prose).
39 changes: 39 additions & 0 deletions .changeset/8938-retired-dialect-measured-surface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
'@object-ui/core': minor
---

The ingestion choke point says out loud when it CANNOT fold a retired spelling
(objectui#8938)

Maintainer ruling item 3 on objectui#7650 asked the retired-dialect fold for "a loud
diagnostic (not a silent drop) for a spelling the choke point cannot fold". What shipped
warned about the spelling it CAN fold and said nothing about the three it cannot, which is
the half that matters to a reader: a key that folds reaches every consumer, and a key that
does not reaches none of them — the retirement cards in this family (objectui#7155, #7166,
#7435) narrowed those consumers to the canonical spelling.

`normalizeSchemaReferenceKeys` now names all three refusals, in dev only and memoised per
(object, field, spelling, reason), the discipline the two existing warnings already use:

- **no declared twin** — `FieldSchema` declares neither the key nor anything sharing its
alias spelling, so there is nothing to fold onto (`id_field`, `title_format`, and a typo
such as `sortible`). The message ⛔ never offers a near match: the refused alternative
was the spec's `lintAuthoredRecordKeys`, whose Levenshtein fall-through answers "did you
mean `sortable`?" for that input, and a serve path that suggests a correction is one
revision away from applying it.
- **ambiguous probe** — two or more declared keys share the alias spelling, so the fold
refuses to choose. Unreachable against a spec with no collision; the pin that exercises
it substitutes a colliding `FieldSchema`.
- **occupied canonical** — the declared twin is on the def carrying a **different** value.
The producer's value stands (this choke point never overwrites one) and the retired value
is inert. Same value under both spellings is deliberately silent: that is the state the
pass leaves behind on its own second run, and the adapter re-serves a cached schema.

**Nothing about which keys fold changes.** The diagnostic fires only on the paths that
already left the key alone, the leave arm stays lossless, and it is a no-op under
`NODE_ENV=production`. Whether the fold's full width — lock and gate keys included — is
the intended accept set is an open decision on objectui#7650, untouched here.

Landed with the width pin objectui#8938 asked for, which drives every snake twin the
linked `@objectstack/spec` implies through the public choke point, and with the correction
to the objectui#7650 changeset that presented a handful of keys as the accepted set.
Loading
Loading