Skip to content

Gap — Surface-B server ranking (the recorded fallback for client-side ranking) ​

A record, not a proposal. Spec 035 moved legendary ranking into the browser (Wave 3 of the gw2.app alignment epic) and retired the server-side legendaries/ranking.service.ts account-scan path. This file records the fallback that spec deliberately left out of scope, so a future session starts from the decision instead of rediscovering it.

What was decided ​

Ranking is computed client-side: for each of the 21 Gen-1 legendaries the browser fetches the Surface-A priceless tree, prices it browser→ArenaNet, and folds it through the shared @gw2priory/recipe-graph engine against a browser-built four-source owned-items map. No server ranking endpoint exists; the AI layer (assistant + MCP) is stateless-per-request and holds no key at rest.

The fallback, and when it triggers ​

If client-side ranking is ever measured too heavy on a mid-range device — the realistic tail is an account with a very large character count (the owned scan fans out one request per character) or a cold Surface-A tree cache — the upgrade path is a Surface-B server ranking endpoint:

  • Per-request only: it receives the caller's API key or a precomputed account snapshot per call, computes, returns, and persists nothing. Response private, no-store. The key never lands at rest, in a log, or in a cache.
  • It does not reintroduce the retired always-on account scan or any per-user caching — that would break the epic invariant (anything per-user is stateless and never cached).
  • The retired ranking.service.ts logic (resolve 21 graphs → price the deduped union in one call → fold through the shared engine) is the reference; git history at spec 035's parent (a14d4bb) has it.

Evidence this is a tail, not the common case (spec 035 research V1) ​

  • ArenaNet is CORS-open and rate-limited per source IP (x-rate-limit-limit: 600); the browser spends the user's own budget with no 5 req/s self-throttle (unlike our origin's token bucket).
  • Per-request latency ~0.1–0.8s (CLI probe), and the 4 + N-character account requests multiplex concurrently over HTTP/2 → a few seconds wall-clock for typical and even 19-character accounts, well under the 31s the throttled server path measured (mcp.tools.ts:239).
  • So the fallback is an insurance policy for the pathological tail, not an expected need.

Status ​

Not built. Trigger: a measured client-ranking run past an interactive budget on a real mid-range device / large account. Until then, YAGNI — the browser path stands.