Repository navigation
Commit a2a3777
docs(search): name the empty-search-set refusal on the pages that describe the data read route's search (#24361)
Fixes #24355
Clause-②: no
## What
This PR adds the empty-search-set refusal to every hand-written page
that describes the data read route's `search` and did not mention it
yet. Since `ec749fbb44` (PR #24320), a non-blank `search` over an object
whose search set comes out empty is refused with `400 INVALID_FIELD`
instead of answering every row. Until now these pages described field
resolution only.
| page | where | change |
|---|---|---|
| `content/docs/protocol/kernel/error-handling.mdx` | `INVALID_FIELD`,
the read-axis parenthesis in the catalog pointer | `search` added beside
`searchFields` |
| `content/docs/api/data-api.mdx` | `GET /data/:object` parameter table,
`search` row | one sentence: when the set is empty, a non-blank term is
`400 INVALID_FIELD`, never every row |
| same | the request/result table under "Neither is a search narrowing,
a grouping, or an aggregation" | one row: `?search=alpha` on an object
with no searchable field gives `400 INVALID_FIELD` |
| same | the `searchFields` bullet under that table | now names both
`search` and `searchFields`. The bullet called `searchFields` "the only
parameter whose failure changed which rows came back", and the new row
would make that untrue. One sentence says what a bare `search` used to
do |
| `content/docs/data-modeling/queries.mdx` | Full-Text Search, opening
paragraph | one sentence, engine calls included |
| `content/docs/protocol/objectql/query-syntax.mdx` | field-resolution
paragraph | the sentence about internal callers keeping the tolerant
intersection now also says what they do not keep: the engine itself
refuses on `find` / `findOne` / `count` / `aggregate` (`param:
'search'`) |
| `content/docs/data-modeling/schema-design.mdx` | Global search |
outside the card's four (see Enumeration). One sentence: list search is
refused, global search skips the object, mirror the title |
| `content/docs/ui/views.mdx` | Toolbar search runtime table | outside
the card's four. The runtime cell of the "key omitted" row gains "`400
INVALID_FIELD` when that set is empty" |
No new section. `content/docs/references/**`, `content/docs/releases/**`
and `content/docs/api/error-catalog.mdx` are untouched.
## The producer, read from the code (base `e4bcced0b4`)
- `emptySearchSetError` and its single call site,
`ObjectQL.expandSearchOnAst` (`packages/objectql/src/engine.ts`). It
throws when the term is non-blank (`normalizeSearch(raw).query.trim()`)
and `expandSearchToFilter` returned `null`. The thrown error carries
`status`/`httpStatus` 400, `code: 'INVALID_FIELD'`, `object` and `param:
'search'`. It has no `field`.
- The set comes from `resolveSearchFieldResolution`
(`packages/spec/src/data/search-fields.ts`). A declared entry counts
when it names a field that exists and is not virtual (`formula`). If no
entry counts, the auto-default applies: text / email / phone / url /
autonumber / textarea / markdown / select, minus hidden and system
columns. `internal: true` fields are removed from the map before
resolution.
- Verbs: `find` and `findOne` call `expandSearchOnAst` directly; `count`
and `aggregate` reach it through `expandSearchOnOptions`. All four live
in the engine, so a caller of `engine.find()` meets the refusal too.
That is why query-syntax's sentence about internal callers keeping the
tolerant intersection is kept and narrowed, not deleted: the tolerant
half, `resolveSearchFields` dropping unknown requested names, has not
changed.
- One door still answers `200`. Global search (`searchAll`,
`packages/metadata-protocol/src/protocol.ts`) skips an object whose set
is empty before it queries. That is stated on schema-design, the only
page here that describes global search.
- The REST pages say `400 INVALID_FIELD` and leave out `param`. The flat
`/data` arm (the `INVALID_FIELD` arm in
`packages/types/src/data-error-classification.ts`) sends `error`,
`code`, `field` and `object`, not `param`. Only query-syntax, which
describes the engine's thrown error, names `param: 'search'`.
Sister sentence: the `### INVALID_FIELD` sentence that PR #24353 adds to
`error-catalog.mdx`, read at its head `d87f5a77ff`. Each page reuses its
terms: resolved search set is empty, no `searchableFields` entry names a
stored field, the default search scans none, `internal: true` fields
never count, mirror the composed title onto a stored text field. The
error-handling parenthesis says the catalog entry lists `search`. That
is only true once #24353 lands, so the two should land together or
#24353 first.
## Enumeration
`git grep -lE 'searchableFields|searchFields' e4bcced --
content/docs`, minus `references/` and `releases/`, gives 8 pages. I
read each once.
| page | describes the data read route's `search`? | disposition |
|---|---|---|
| `api/data-api.mdx` | yes | edited |
| `data-modeling/queries.mdx` | yes | edited |
| `protocol/kernel/error-handling.mdx` | yes (the `INVALID_FIELD` read
axes) | edited |
| `protocol/objectql/query-syntax.mdx` | yes | edited |
| `data-modeling/schema-design.mdx` | yes: `?search=apollo`, `$search`,
the auto-default fallback | edited (outside the card's four) |
| `ui/views.mdx` | yes: the toolbar search's runtime answers are the
data door's | edited (outside the card's four) |
| `api/error-catalog.mdx` | yes | left: PR #24353 covers it |
| `kernel/contracts/data-engine.mdx` | no: the `EngineQueryOptions` type
listing and the predicate rule for `findOne`, neither of which describes
the route | read and left |
## Line budget
The card's four pages: +16 / -6, net +10 (budget +16). The two outside
them: schema-design +4 / -1, views +1 / -1. All six: +21 / -8.
## Verification (HEAD `d0e954f51`, after merging `origin/main` at
`d1f082d94`)
Docs-only: no package is touched, so no build closure and no package
tests are owed. The gate list is the 41 commands from `node
scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (merge base `d1f082d94`). Each ran with its
exit code captured before any pipe:
- 40 exited 0. They include `pnpm check:doc-authoring`,
`check:doc-anchors`, `check:error-status-conformance`, `check:nul-bytes`
and `check:corpus-claim-drift`. Four of them ran after building
`@objectstack/lint...` (lint, formula, sdui-parser, spec) under the
verify lock (held 117 s): `pnpm --filter @objectstack/spec run
check:docs`, `pnpm check:docs-transcript-drift`, and `pnpm --filter
@objectstack/lint run check:doc-formula-expressions` /
`check:doc-security-posture`.
- 1 NOT MEASURED: `pnpm --filter @objectstack/spec run
check:skill-examples` exited 3, PREREQUISITE NOT MET, because
`packages/client-react/dist` holds no `.d.ts`. Building it means a
37-package closure. Declared narrowing: none of the eight hunks is
inside a fenced code block (checked per hunk), so no marked example
changed. CI runs the gate.
- `--ran` reconciliation: "41 derived famil(ies) accounted for — 40 run,
1 NOT-MEASURED".
- Left to CI, not run locally: the path-scheduled `Build Docs` job and
the type-check lanes.
- Control-byte scan of the six files: no hit.
## Acceptance notes
- `ui/views.mdx`, under "What the object allows": the allowed set for a
declaring object is described as "that list, verbatim — whatever the
field types are". In the code, `resolveSearchFieldResolution` drops
entries that name no field or a `formula` field. The last table row in
the same section does refuse the formula case. Docs drift, not filed, no
carrier.
- `kernel/contracts/data-engine.mdx`: the `EngineQueryOptions` comment
for `search` does not mention the refusal. The engine-caller statement
is on query-syntax. Read and left (see above).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent c4526a7 commit a2a3777
6 files changed
Lines changed: 21 additions & 8 deletions
File tree
- content/docs
- api
- data-modeling
- protocol
- kernel
- objectql
- ui
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
| 26 | + | |
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| |||
156 | 156 | | |
157 | 157 | | |
158 | 158 | | |
| 159 | + | |
159 | 160 | | |
160 | 161 | | |
161 | 162 | | |
162 | 163 | | |
163 | 164 | | |
164 | 165 | | |
165 | | - | |
166 | | - | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
167 | 170 | | |
168 | 171 | | |
169 | 172 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
477 | 477 | | |
478 | 478 | | |
479 | 479 | | |
480 | | - | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
481 | 484 | | |
482 | 485 | | |
483 | 486 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
102 | 102 | | |
103 | 103 | | |
104 | 104 | | |
105 | | - | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
106 | 109 | | |
107 | 110 | | |
108 | 111 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
624 | 624 | | |
625 | 625 | | |
626 | 626 | | |
627 | | - | |
| 627 | + | |
628 | 628 | | |
629 | 629 | | |
630 | 630 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1124 | 1124 | | |
1125 | 1125 | | |
1126 | 1126 | | |
1127 | | - | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
1128 | 1132 | | |
1129 | 1133 | | |
1130 | 1134 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
157 | | - | |
| 157 | + | |
158 | 158 | | |
159 | 159 | | |
160 | 160 | | |
| |||
0 commit comments