Skip to content

Commit 2d2e6f0

Browse files
os-trumpclaude
andauthored
fix(spec): name reference, not the rejected referenceTo alias, in the public-picker prose (#13198)
* fix(spec): name `reference`, not the rejected `referenceTo` alias, in the public-picker prose `FormFieldPublicPickerSchema.object` told authors the picker target resolves from `referenceTo` on the parent object's field definition. `referenceTo` is not a key `FieldSchema` accepts — it is a rejected alias listed only so `strictUnknownKeyError` can offer a rename hint, so an author who followed the sentence had their whole object metadata refused at parse. The `.describe()` half is the sharper one: it is published into the generated JSON Schema and the reference docs, so it reached authors (and AI authors reading the generated schema as ground truth) who never open this file. Purely textual. Nothing about the runtime resolution changes, and this takes no position on the REST route's legacy-spelling chain — the sentence is wrong under either outcome, because a conformant authored field carries `reference` in both worlds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4 * docs(spec): regenerate the ui/view reference for the corrected picker prose, add changeset `check:generated` proved exactly one artifact stale after the describe change: `content/docs/references/ui/view.mdx`. Regenerated with the repo's own `pnpm --filter @objectstack/spec gen:docs`, never by hand. The false sentence rendered TWICE on that page — the picker schema is emitted both nested under `FormField` and standalone as `FormFieldPublicPicker` — which is the published half of the defect the card names. Changeset is a `@objectstack/spec` patch, matching in-repo precedent for describe-string corrections that regenerate a references page. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent bfaada0 commit 2d2e6f0

3 files changed

Lines changed: 43 additions & 6 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
fix(spec): `FormFieldPublicPickerSchema.object` now names `reference` — the key `FieldSchema` actually accepts — instead of the rejected `referenceTo` alias (#13138)
6+
7+
Both sentences on the `object` key told authors the picker target resolves from
8+
`referenceTo` on the parent object's field definition. `referenceTo` is not a
9+
key `FieldSchema` accepts: it is a **rejected alias**, listed in the field
10+
schema's alias map only so `strictUnknownKeyError` can offer a rename hint when
11+
a parse fails on it. An author who followed the sentence and wrote `referenceTo`
12+
on the parent object's field got their whole object metadata refused at parse —
13+
a failure, not a degraded render.
14+
15+
Measured against the built `packages/spec/dist/data/index.mjs` with a three-level
16+
control (a two-level one cannot separate "rejected" from "not measured"):
17+
18+
- `reference: 'sys_user'` (positive control) parses, `parsed.reference` is `'sys_user'`
19+
- `zzz_not_a_key` (negative control) is refused `unrecognized_keys`, with no rename hint
20+
- `referenceTo` is refused `unrecognized_keys`, **with** the hint ``Did you mean `referenceTo` → `reference`?``
21+
22+
The `.describe()` half is the load-bearing one: it is published, flowing into the
23+
generated JSON Schema and `content/docs/references/ui/view.mdx`, so the wrong key
24+
name reached authors who never open this file — and AI authors reading the
25+
generated schema as ground truth. The reference docs are regenerated with the
26+
repo's own `gen:docs` in the same change.
27+
28+
Prose only: no schema shape, no accept/reject movement, no new or removed keys —
29+
every previously-valid input still parses byte-identically. This takes no
30+
position on whether the REST route's legacy-spelling fallback chain survives:
31+
the sentence was wrong under either outcome, because a conformant authored field
32+
carries `reference` in both worlds, and the route already reads `reference` first.

content/docs/references/ui/view.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ Form-view select option — the object-field option shape minus the per-option `
235235
| **displayFields** | `string[]` | optional | Fields projected into each picker result (with `id`); the visitor's search matches `contains` on the first entry. At most 5 (the route projects no more); omitted → ['name']. |
236236
| **maxResults** | `integer` | optional | Maximum rows a lookup returns (default 20, hard ceiling 50 — the route clamps; anonymous visitors cannot paginate past it). |
237237
| **filter** | `{ field: string; operator?: Enum<'equals' \| 'not_equals' \| 'contains' \| 'not_contains' \| 'icontains' \| …>; value?: string \| number \| boolean \| null \| (string \| number)[] }[]` | optional | Static pre-filter rows ANDed ahead of the visitor's search (e.g. only active records are searchable). Same `{ field, operator, value }` dialect as list-view filters. |
238-
| **object** | `string` | optional | Referenced-object override for the picker search; omitted → resolved from the field definition (`referenceTo`). |
238+
| **object** | `string` | optional | Referenced-object override for the picker search; omitted → resolved from the `reference` key on the field definition. |
239239

240240
### Nested Shape: `FormField.keyField`
241241

@@ -262,7 +262,7 @@ Public-lookup opt-in: enables GET /forms/:slug/lookup/:field for this field on a
262262
| **displayFields** | `string[]` | optional | Fields projected into each picker result (with `id`); the visitor's search matches `contains` on the first entry. At most 5 (the route projects no more); omitted → ['name']. |
263263
| **maxResults** | `integer` | optional | Maximum rows a lookup returns (default 20, hard ceiling 50 — the route clamps; anonymous visitors cannot paginate past it). |
264264
| **filter** | `{ field: string; operator: Enum<'equals' \| 'not_equals' \| 'contains' \| 'not_contains' \| 'icontains' \| …>; value?: string \| number \| boolean \| null \| (string \| number)[] }[]` | optional | Static pre-filter rows ANDed ahead of the visitor's search (e.g. only active records are searchable). Same `{ field, operator, value }` dialect as list-view filters. |
265-
| **object** | `string` | optional | Referenced-object override for the picker search; omitted → resolved from the field definition (`referenceTo`). |
265+
| **object** | `string` | optional | Referenced-object override for the picker search; omitted → resolved from the `reference` key on the field definition. |
266266

267267
### Nested Shape: `FormFieldPublicPicker.filter[number]`
268268

packages/spec/src/ui/view.zod.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,12 +1907,17 @@ export const FormFieldPublicPickerSchema = lazySchema(() => strictObject({
19071907
),
19081908
/**
19091909
* Referenced-object override. Omitted, the route resolves the target from
1910-
* the field definition on the parent object (`referenceTo`); set it only
1911-
* when that resolution is wrong for this form.
1910+
* the field definition on the parent object (`reference`); set it only when
1911+
* that resolution is wrong for this form.
1912+
*
1913+
* `reference` is the key `FieldSchema` accepts — `referenceTo` is only a
1914+
* rejected alias it lists so a failed parse can offer a rename hint, so an
1915+
* author following the old spelling of this sentence had their whole object
1916+
* metadata refused at parse.
19121917
*/
19131918
object: z.string().optional().describe(
1914-
'Referenced-object override for the picker search; omitted → resolved from the field '
1915-
+ 'definition (`referenceTo`).',
1919+
'Referenced-object override for the picker search; omitted → resolved from the `reference` '
1920+
+ 'key on the field definition.',
19161921
),
19171922
}).describe('Public-lookup opt-in: enables GET /forms/:slug/lookup/:field for this field on an anonymous public form (without it the route answers 403 LOOKUP_NOT_PUBLIC).'));
19181923

0 commit comments

Comments
 (0)