Skip to content

finding(metadata-protocol): repeatedQueryParamError's docblock says its wording is packages/rest's "verbatim" so one caller is told "the same thing twice" — measured, the two sentences differ, and the reason the copy exists is now half gone #17813

Description

@os-sales

Filed out of PR work on #17672 (domain:cli dev seat, branch claude/issue-17672-repeated-version-400-reachability). ⛔ Not graded, no domain:*, no priority, no assignee — that is triage's. ⛔ Not fixed there: it is a second module, a second wire code, and a dependency-direction question, none of which is #17672's declared surface.

The declared contract, quoted

packages/metadata-protocol/src/protocol.ts, the docblock over repeatedQueryParamError (locate from the symbol; ~:3134:3165 on origin/main @ 43df8db3a):

… the same rule #6307 / #6877 landed in packages/rest (readSingleQueryValue); the wording below is theirs verbatim so a caller who repeats a parameter on two different routes is told the same thing twice, not two things once.

That sentence is the whole stated justification for hand-copying the text rather than referring to it, so it is load-bearing prose rather than decoration — the same shape as the header line #17672's second half exists to correct.

The measurement

Both producers driven with the same (name, count) pair, on origin/main @ 43df8db3a:

rest              The "top" query parameter was supplied 2 times. Supply it at most once — this
                  endpoint will not choose between conflicting values.

metadata-protocol The 'top' query parameter was supplied 2 times. Supply it at most once — this
                  endpoint will not choose between conflicting values. It was NOT applied as a
                  list: a single-valued parameter given an array coerces to a value nobody asked
                  for (Number(['1','2']) is NaN), which the driver then answers under a 200.

identical prefix? false

Two differences, and only one of them is additive:

  1. The parameter name is quoted differentlypackages/rest writes The "top", metadata-protocol writes The 'top'. So the sentences are not the same sentence, not even in their shared span, and "verbatim" is false at the first quoted character.
  2. The appended It was NOT applied as a list: … clause. Additive rather than contradictory, but it is also part of why the leading claim cannot be read as "the shared prefix is verbatim".

⚠️ ⛔ Not a claim that the two routes must answer the same CODE. The same docblock is explicit that they do not and why (INVALID_REQUEST here, VALIDATION_ERROR in packages/rest, VALIDATION_FAILED in the runtime layer — each package's registered catalog member for a 400), and that "the RULE and the status are what have to agree across the three, and do". This card is only about the sentence the docblock says is shared and is not.

Why it is worth a card now rather than a note

The copy's other justification was reachability, and half of it has just gone. PR on #17672 publishes repeatedQueryParamMessage from @objectstack/rest's entry, so the message that module owns is now importable by a sibling package for the first time.

⚠️ It is only HALF gone, which is why this is a finding and not a one-line fix:

  • @objectstack/metadata-protocol's dependencies are @objectstack/core, @objectstack/formula, @objectstack/lint, @objectstack/metadata, @objectstack/metadata-core, @objectstack/spec, @objectstack/types, zod@objectstack/rest is in neither its dependencies nor its devDependencies (measured on the manifest).
  • The arrow currently points the other way: @objectstack/rest carries @objectstack/metadata-protocol as a dev dependency, and query-multiplicity.ts's own header records that as the reason it cannot derive the filter-slot spellings from that package at runtime.

⇒ Whoever fixes this decides where the sentence should live for three consumers, not two. ⛔ That is a layering decision and is deliberately not made here.

What a fix would decide (⛔ not decided here)

  1. Correct the docblock only — say the wording is modelled on packages/rest's rather than verbatim, and state the two deltas. ⚠️ Cheapest, and leaves two spellings on the wire for one rule.
  2. Make the two sentences actually identical — align the quoting and keep the appended clause as a documented extension of the shared prefix. ⚠️ Still a hand-kept copy, so the claim is true the day it lands and unenforced afterwards; would want a pin that compares the two producers.
  3. Move the message to a package all three layers already depend on (@objectstack/spec or @objectstack/types are the two both sides can see) and have packages/rest, metadata-protocol and the dispatcher domain call it. ⚠️ This is the shape The direct-mount REST package door answers 500 INTERNAL_ERROR for coded 4xx errors the dispatcher twin maps correctly #8016 already used for resolveThrownHttpError when two package doors had to agree on a rule neither could import from the other — precedent exists, but it moves a published surface and is a Clause-② act.

Not duplicates (checked; the search channel returned 10 on-topic hits, so the zero for a duplicate is a reading)

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions