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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions