Skip to content

Gaps — spec 034 key-transport supersession & shared-gw2 follow-ups ​

Records from spec 034 — client-direct ArenaNet and its research. Observations/decisions already made during 034, parked here rather than acted on further — nothing below is a proposal.


1 — stack.md's key-transport claim is superseded for prices + account/materials/wallet ​

docs/architecture/stack.md (Authentication) documents the key travelling as Authorization: Bearer from the browser to our api, which forwards it to GW2. Spec 034 (the gw2.app-alignment epic) supersedes this for prices and account/materials/wallet only: those now go browser → ArenaNet directly, with the key as ?access_token= — the Authorization header is CORS-blocked from a browser (research 034 V1: a cross-origin fetch with an Authorization header never leaves the browser, TypeError: Failed to fetch; ?access_token= is a "simple" request and reaches the server).

Ranking and the assistant (Wave 3 / Spec 5) are untouched by 034 and still send the key to our origin — stack.md's description holds for those flows. stack.md itself is unedited by 034 (spec status is a plan.md concern, not this record's); it should be updated to note the split when a later spec next touches it.

2 — GW2 CORS / rate-limit facts worth graduating into gw2-api.md ​

From research 034 (V1, V2, V3, V6), not yet in docs/architecture/gw2-api.md:

  • The /v2 API is CORS-open (access-control-allow-origin: *) for GETs.
  • A cross-origin Authorization header is CORS-blocked (fails preflight); ?access_token= works (no preflight — a "simple" request).
  • The rate limit (gw2-api.md already documents 300 burst / 5-per-sec) is per IP, confirmed against the wiki. Browser-direct calls therefore spend each user's own budget, not our shared origin's — the whole justification for 034's move. gw2-api.md documents the limit itself but not this browser-direct consequence.
  • The response body is readable cross-origin despite a minimal access-control-expose-headers: expose-headers gates response headers, not the body. cache-control is readable (it's a CORS-safelisted response header, needs no expose-headers entry); access-control-allow-origin itself reads as null in JS (consumed by the browser, never exposed) — that null is not a CORS failure signal.

3 — Stale "types-only @gw2priory/recipe-graph" comments (broader sweep deferred) ​

Several apps/api comments say to import only types from @gw2priory/recipe-graph, but both apps now runtime-import it: apps/web already did (mergeOwnVsNeed/aggregateNeed), apps/api's ranking.service.ts already did (mergeOwnVsNeed, needRows), and 034 added priceGraph (recipe-graph.service.ts). Spec 034 corrected the comments in the files it edited; one stale pair remains untouched — recipe-graph.schema.ts:1,7 — since 034 didn't edit that file. A broader sweep is deferred.

4 — Orphaned models-zod/*.zod.ts after orval regen ​

apps/web's Orval api-zod client-generator entry runs with clean: false, so regenerating the API client leaves unreferenced *.zod.ts files on disk for endpoints that no longer exist. Spec 034 dropped /account* and /commerce/*, and confirmed the pattern on both the newly-orphaned files (materialListDtoOutput.zod.ts, walletListDtoOutput.zod.ts, commercePriceListDtoOutput*.zod.ts, …) and a pre-existing case (recipeTreeDtoOutput*.zod.ts, orphaned since the recipe-tree route was replaced by recipe-graph). All are import type-only from present sibling files, unreferenced by the generated barrel, and lint-clean after pnpm format — harmless dead files, not a build or lint hazard. A later cleanup could set clean: true on the orval config or prune them by hand; out of scope here.