You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(objectql): strip the hidden __search companion from every record body (#7642) (#7868)
The `__search` search-normalization companion (#2486) is declared invisible to
clients — `hidden` + `readonly` + `system` + `searchable: false` — and every one
of those flags does something real: the column stays out of auto-views, out of
the `$search` auto-default, and a `$searchFields` override naming it is refused
with a 400 ("is hidden"). None of them is a PROJECTION rule. A query that names
no `fields` reaches the driver with `ast.fields` undefined, drivers answer that
with `SELECT *`, and the column rode back in the four record bodies QA measured
(#7629): query results, GET by id, `/search` hits, and the 201 create body.
The strip runs at the engine, the producer all four surfaces share — `/search`
hits are `engine.find` rows verbatim, the create body is `engine.insert`'s
return verbatim, so fixing consumers one at a time would have left three of the
four broken. Covered: `find`, `findOne`, the nested records `expand` produces,
the create response and the update response. The update response is not one of
the four reported surfaces but is the same column in the same response shape;
leaving it out would make POST and PATCH on one object disagree about whether a
client-invisible column is visible. A predicate update resolves to a count and
is unaffected.
Two shaping details, both from the report:
- Not gated on the schema declaring the column. The symptom survived a restart
with `OS_SEARCH_PINYIN_ENABLED=false`: with the switch off the registry stops
DECLARING the field, but the physical column and its values remain (ADR-0045
migrations are additive) and `SELECT *` keeps returning them. A strip that
asked `schema.fields.__search` first would be silent in exactly the deployment
that filed the bug.
- One caller keeps its read. `plugin-pinyin-search`'s backfill projects
`['id', ...sources, '__search']` under a system context and compares the
stored blob against a recomputed one; stripping it unconditionally would make
the walk rewrite every row of every object on every pass. A SYSTEM caller that
names the column still gets it — a non-system caller does not, even by name,
since `select` only gates on whether a field is KNOWN and `?select=__search`
would otherwise be a documented way straight through the strip.
Scope is this one column. Hidden system columns do come back generally
(`organization_id` and its siblings), but they are load-bearing in client
payloads today; removing them is a contract decision, not a defect fix.
The new suite is a MATRIX over every record-returning door rather than a test
for the door that was fixed, in both provisioning states — one contract, five
places that can break it independently is the shape that rots one door at a
time. Reverse-checked: 17 of its 24 cases fail on the unfixed engine.
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments