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
- Follows up on !1290 (merged), which added the adversarial examples and the claim column.
/api/:version/internal/*is still absent from both snapshots: gitlab-com/gl-infra/tenant-scale/cells-infrastructure/team#786 (closed).
How to set up and validate locally
npm test -- routes.spec.ts- passes against the committed snapshot.npm test- full suite, 343 tests.- 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 - To read the new rows:
git show --statshows insertions only, andgit diff main -- test/routes/__snapshots__/routes.spec.ts.snap | grep '^+.*"user_id"' | headshows the claims that replaced theBigInterrors.