Skip to content

finding: the wire-only filter alias spellings (filters / $filter) are now declared in two packages, with no gate reconciling them #8002

Description

@hotlong

Observation-class finding, split out of #7390 while implementing it. Unassigned, filed per Prime Directive #10. Nothing a user hits today — this is a drift seam, not a live defect.

What the seam is

The filter slot has four wire spellings, and they are declared in two places with different ownership:

  • where and filter come from RPC_QUERY_ALIAS_SLOTS (packages/spec/src/data/data-engine.zod.ts), which its own docblock calls "the ONE place the alias to canonical mapping is declared".
  • filters and $filter are wire-only — no schema declares them. packages/metadata-protocol extends the spec table with them locally (WIRE_QUERY_ALIAS_SLOTS).

#7390 added a third reader: packages/rest now gates the filter slot's arity at the querystring ingress, and needs the same four spellings to do it. It derives where / filter from the spec table, but cannot derive filters / $filter@objectstack/metadata-protocol is a dev-only dependency of @objectstack/rest, so no runtime import of that table exists. They are named literally in packages/rest/src/query-multiplicity.ts (FILTER_SLOT_QUERY_PARAMS).

The consequence

A new wire-only alias for the filter slot, added to metadata-protocol's table, would fold correctly in the normalizer and be silently ungated at the ingress — repetition on that spelling would fall back to the misdiagnosis #7390 exists to remove. Nothing fails: the spelling works, the gate simply does not see it.

Half of it is already pinned: rest-server-repeated-filter-param.test.ts §5 asserts the derived set composes to exactly the four spellings, so a spec-table change goes red. The wire-only half has no such backstop, because the package holding the truth is not on the runtime graph.

Symmetric note: WIRE_DOLLAR_ALIASES in the same normalizer already carries a comment about exactly this class of mistake — "Adding a $ alias in one place and not the other is exactly how a parameter ends up folded but unchecked." That sentence is now true across a package boundary as well as within one.

Options

  1. Hoist the wire-only spellings into @objectstack/spec — e.g. a WIRE_ONLY_QUERY_ALIASES export beside RPC_QUERY_ALIAS_SLOTS — so both metadata-protocol and rest read one table. Cleanest, and the only option that removes the seam rather than watching it. It touches the spec's public export surface (check:api-surface regeneration), and whether the wire vocabulary belongs in the spec at all is a genuine question: these spellings exist precisely because no schema declares them.
  2. A cross-package consistency gate — a check: script asserting rest's literal set equals the normalizer's derived set. No dependency-graph change; adds a script whose only job is to watch two lists.
  3. Leave it, documented. The set has been stable at four spellings for a long time, and the drift only bites if someone adds a fifth.

Recommendation is (1) if the spec seat wants the wire vocabulary declared at all, else (2). Both are cheap; neither is urgent.

Dedup

Searched open issues for WIRE_QUERY_ALIAS_SLOTS, RPC_QUERY_ALIAS_SLOTS, wire alias, $filter, filters plural, and query-alias drift. Hits: #7390 (the parent), #4436, #3774 — none covers the two-package declaration of the wire-only spellings.


Generated by Claude Code

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions