Skip to content

finding: the list-query normalizer's where arity note still says a repeated ?filter= is refused by isFilterAST failing #8003

Description

@hotlong

Observation-class finding, split out of #7390 while implementing it. Unassigned, filed per Prime Directive #10. Comment-only drift — no runtime behaviour is wrong.

The sentence

packages/metadata-protocol/src/protocol.ts, in the docblock above ARRAY_VALUED_QUERY_SLOTS (the #7321 arity survey), the where row reads:

where — a FILTER AST is an array (['status','=','open']), so a blanket arity refusal here would reject the AST body form outright. A repeated ?filter= is still refused, one block down, by isFilterAST failing to read it.

The first sentence is correct and load-bearing — it is exactly why #7386's arity gate skips this slot, and #7390 quotes the same reasoning.

The last sentence has two problems, one of them older than #7390:

  1. It was always describing the defect as if it were the answer. isFilterAST failing produces malformedFilterArrayError — a 400 telling a caller whose filters were each well-formed that their filter is malformed, listing the AST operator vocabulary. That is finding: a repeated ?filter= on GET /data/:object cannot be told from a filter AST, so it is diagnosed as a malformed filter (and, rarely, succeeds) #7390's entire finding: the refusal is correct, the diagnosis is not. "Still refused" reads as handled.
  2. It is now stale for the route it describes. finding: a repeated ?filter= on GET /data/:object cannot be told from a filter AST, so it is diagnosed as a malformed filter (and, rarely, succeeds) #7390 moves the arity judgement for this slot to the REST querystring ingress (packages/rest, assertFilterParamSuppliedOnce), which is the only layer that can make it — on a querystring an array is a repetition and can be nothing else. A repeated ?filter= on GET /data/:object no longer reaches this block at all.

It also does not mention the second shape at all: ?filter=status&filter=%3D&filter=open spelled a valid AST and succeeded with a filter nobody expressed, which is the sharper half of #7390.

Why it matters more than a typo

This docblock is the survey a future author reads to decide whether a slot needs arity treatment. A reader who takes "still refused, one block down" at face value concludes the filter slot is covered and stops — which is roughly how the gap survived from #7321 to #7390. The sentence should say that arity for this slot is judged at the querystring ingress and name #7390, so the next reader is told which layer owns it.

Deliberately not fixed in #7390's PR: that card's ruling put the enforcement in packages/rest and explicitly kept it out of packages/metadata-protocol, and protocol.ts is a hot shared file. Same handling as #7707 / #7874, which corrected stale comments in their own PRs.

Dedup

Searched open issues for ARRAY_VALUED_QUERY_SLOTS, isFilterAST, malformedFilterArrayError, stale comment, and arity survey. Hits: #7390 (the parent), #7321 / #7386 (the arity gate, both closed) — none covers this comment.


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

Labels

documentationImprovements or additions to documentationpm:dispatchedskip-changesetPR has no user-facing published change; bypasses the changeset gate

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions