docs(route-authority): record v1/v2 economy URL prefix contract
Accepted prefixes /ut/game/<sku>/ and /ut/v2/game/<sku>/ for every economy route; StoreBuy accepts store/transaction and store/transaction/<txn-id>.
This commit is contained in:
@@ -12,6 +12,38 @@ entitlements (`unopenedPackIds`). `points` has **no** writer (read-only). EASFC
|
|||||||
Legend: **R** = Rust/Core authoritative, **P** = Python proxied (oracle).
|
Legend: **R** = Rust/Core authoritative, **P** = Python proxied (oracle).
|
||||||
Evidence lines refer to `fifa17-recon/tools/{utas_server.py,fut_store.py}`.
|
Evidence lines refer to `fifa17-recon/tools/{utas_server.py,fut_store.py}`.
|
||||||
|
|
||||||
|
|
||||||
|
## Accepted URL prefixes (v1 + v2) — S2 fix
|
||||||
|
|
||||||
|
The retail FIFA 17 client issues the **Store family** under a `/ut/v2/game/<sku>/`
|
||||||
|
prefix (live-observed `PUT /ut/v2/game/fifa17/store/transaction/0`), while other
|
||||||
|
routes use `/ut/game/<sku>/`. `classify_economy` normalizes BOTH prefixes to the
|
||||||
|
same tail (`ut_tail`), so economy ownership is prefix-agnostic. This closes the
|
||||||
|
S2 live-staging defect where the v2 Store BUY escaped to Python.
|
||||||
|
|
||||||
|
| Route | Accepted method + path shapes (both prefixes) | Economy route |
|
||||||
|
|---|---|---|
|
||||||
|
| Credits | `GET (/ut/game\|/ut/v2/game)/<sku>/user/credits` | `Credits` |
|
||||||
|
| Store catalogue | `GET …/store/purchasegroup[/…]` | `PurchaseGroup` |
|
||||||
|
| **Store BUY** | `PUT …/store/transaction` **and** `PUT …/store/transaction/<txn-id>` (numeric, e.g. `…/store/transaction/0`) | `StoreBuy` |
|
||||||
|
| Pack open | `POST …/purchased` | `PackOpen` |
|
||||||
|
| Pack reveal | `GET …/purchased` | `PackReveal` |
|
||||||
|
| Quick-sell (path) | `DELETE …/item/<digits>` | `QuickSellPath` |
|
||||||
|
| Quick-sell (body) | `POST (/ut/delete/game\|/ut/v2/delete/game)/<sku>/item` | `QuickSellBody` |
|
||||||
|
| Move | `PUT …/item` | `MoveItems` |
|
||||||
|
| Match end | `POST (/ut/delete/game\|/ut/v2/delete/game)/<sku>/match` | `MatchEnd` |
|
||||||
|
| Market list | `POST …/auctionhouse` \| `…/transfermarket` | `MarketList` |
|
||||||
|
| Market query | `GET …/tradePile` | `MarketQuery` |
|
||||||
|
| Market buy | `…/trade/<id>` | `MarketBuy` |
|
||||||
|
| Market cancel | `DELETE (/ut/delete/game\|/ut/v2/delete/game)/<sku>/trade/<id>` | `MarketCancel` |
|
||||||
|
|
||||||
|
`store/transaction` matching is BOUNDED to a single all-digit id segment — it
|
||||||
|
never absorbs `store/transactions`, `store/transactionfoo`, or
|
||||||
|
`store/transaction/<id>/extra` (those proxy to Python as non-economy). Audit
|
||||||
|
basis: Python route table `utas_server.py:1420` matches the store family
|
||||||
|
"regardless of /ut/game vs /ut/v2/game prefix"; all other economy routes are
|
||||||
|
`G = /ut/game/[^/]+`-prefixed (v1-only) and the retail client uses v1 for them.
|
||||||
|
|
||||||
## E1 — CUTOVER READY (barrier `93a46d4`, superproject source-ready; NOT deployed)
|
## E1 — CUTOVER READY (barrier `93a46d4`, superproject source-ready; NOT deployed)
|
||||||
|
|
||||||
The economy authority barrier is committed: `Server::handle_with_ip` dispatches
|
The economy authority barrier is committed: `Server::handle_with_ip` dispatches
|
||||||
|
|||||||
Reference in New Issue
Block a user