Replay claim values the parsers accept in the route snapshot

What does this MR do and why?

GitLab's route snapshot substitutes foo and john.doe for every path parameter. Those values stress the router's path matching, which is why the generator picks them, but no numeric claim parser accepts them. Every rule classifying a *_ID variable therefore recorded a BigInt error instead of a claim:

  [
    "/-/autocomplete/users/:id",
    "/-/autocomplete/users/foo",
    "/-/autocomplete/users/:USER_ID/*",
    "claim-parse-error (falls back to session routing): Cannot convert foo to a BigInt",
  ],

The package variables were quieter but no better: :CONAN_PACKAGE_USERNAME and :SCOPED_NPM_PACKAGE recorded { route: "foo" }, exercising neither the + split nor the @scope one.

This MR adds SAMPLE_VALUES, a value each parser accepts per routing variable, and replays one extra URL for each route whose matched rule classifies such a variable. The snapshot now records the claim the rule sends in production:

  [
    "/-/autocomplete/users/:id",
    "/-/autocomplete/users/42",
    "/-/autocomplete/users/:USER_ID/*",
    {
      "user_id": 42n,
    },
  ],

The existing rows are unchanged (1010 insertions, 0 deletions). They pin which rule wins for a dotted or format-suffixed value, which the new rows cannot cover: catchall is /*, so every URL matches something and the snapshot's value is the identity of the matched rule. Those rows are also the only place a future digit constraint on a rule (:USER_ID{\d+}) would become visible.

Finding: a format suffix defeats the numeric parsers

The new rows surface 11 parse failures on production-shaped URLs, for example:

  [
    "/-/autocomplete/users/:id",
    "/-/autocomplete/users/42.json",
    "/-/autocomplete/users/:USER_ID/*",
    "claim-parse-error (falls back to session routing): Cannot convert 42.json to a BigInt",
  ],

Same for /-/g/42.json, /-/p/42.json, /-/snippets/42.json and /unsubscribes/<base64>.json. GitLab serves these paths (their templates carry acceptsFormat), and BigInt("42.json") throws, so the request falls back to session routing instead of being claim-routed. Only the bare :id variant is affected: /-/snippets/42/raw.json parses fine because the suffix lands on a later segment.

Fixing it means either stripping a trailing format suffix the way UsernameWithSuffix strips .keys / .gpg, or constraining those rules to digits. No production code is changed in this MR - it only makes the behaviour visible.

References

How to set up and validate locally

  1. npm test -- routes.spec.ts - passes against the committed snapshot.
  2. npm test - full suite, 343 tests.
  3. To confirm the snapshot is reproducible rather than hand-edited: npm test -- routes.spec.ts -u && git diff --exit-code test/routes/__snapshots__/routes.spec.ts.snap
  4. To read the new rows: git show --stat shows insertions only, and git diff main -- test/routes/__snapshots__/routes.spec.ts.snap | grep '^+.*"user_id"' | head shows the claims that replaced the BigInt errors.

🤖 Generated with Claude Code

Edited by Marco Gregorius

Merge request reports

Loading
Loading