testing generic deploy

This commit is contained in:
Devin Zuczek
2026-06-29 21:52:50 -04:00
parent 3affabd280
commit 69b89e2dc4
79 changed files with 399 additions and 307 deletions
+10 -10
View File
@@ -1,6 +1,6 @@
# econ
Economy Worker served at `econ.rec.djdevin.net`. Hosts the avatar/economy
Economy Worker served on the `econ` subdomain. Hosts the avatar/economy
endpoints the game client calls on the `econ` service (distinct from the main
`api` worker). DB-backed data is stubbed for now — no bindings yet.
@@ -8,21 +8,21 @@ endpoints the game client calls on the `econ` service (distinct from the main
- `GET /api/avatar/v1/defaultunlocked` — default-unlocked avatar items, served
from the bundled `static/default-avatar-items.json` catalog.
- `GET /api/avatar/v1/defaultbaseavataritems` — default base avatar items. The C#
reads the same source file as `defaultunlocked`, so it returns the identical
- `GET /api/avatar/v1/defaultbaseavataritems` — default base avatar items. Reads
the same source file as `defaultunlocked`, so it returns the identical
catalog.
- `GET /api/avatar/v4/items``[Authorize]`. The player's avatar items: owned
items concatenated with the default catalog. No DB binding yet, so owned is
empty and this returns just the catalog.
- `GET /api/avatar/v2``[Authorize]`. The player's avatar. No DB binding yet,
so it returns the default `{ OutfitSelections, FaceFeatures, SkinColor,
HairColor }` the C# seeds for a new player.
HairColor }` seeded for a new player.
- `GET /econ/customAvatarItems/v1/owned` — the player's owned custom avatar
items. No auth (matching the C#); returns `{ items: [] }` with no DB binding.
items. No auth; returns `{ items: [] }` with no DB binding.
The client requests this when custom-item creation is allowed, so a missing
route here shows up as "Failed to download unlocked avatar items".
- `GET /api/objectives/v1/myprogress` — objectives progress. No auth (matching
the C#, which serves a static JSON file verbatim); returns the bundled
- `GET /api/objectives/v1/myprogress` — objectives progress. No auth (serves a
static JSON file verbatim); returns the bundled
`static/my-progress.json` default for all players until a DB binding exists.
- `GET /api/avatar/v3/saved``[Authorize]`. Saved outfits; `[]` without a DB.
- `GET /api/avatar/v2/gifts``[Authorize]`. Pending gifts; `[]` without a DB.
@@ -33,15 +33,15 @@ HairColor }` the C# seeds for a new player.
- `GET /api/storefronts/v3/giftdropstore/3` — gift-drop storefront, served from
the bundled `static/storefronts-v3-giftdropstore-3.json`.
- `GET /api/challenge/v2/getCurrent` — current weekly challenge, served from the
bundled `static/weekly-challenge.json` (the C#'s `JSON/weeklychallenge.json`).
bundled `static/weekly-challenge.json`.
- `GET /api/gamerewards/v1/pending` — pending rewards; `[]`.
- `GET /api/roomkeys/v1/mine` — the player's room keys; `[]`.
- `POST /api/CampusCard/v1/UpdateAndGetSubscription` — subscription lookup;
`{ subscription: null, platformAccountSubscribedPlayerId: null }`.
- Not in CannedNet (stubbed): `GET /api/roomconsumables/v1/roomConsumable/room/:id`
- Stubbed: `GET /api/roomconsumables/v1/roomConsumable/room/:id`
and `GET /api/roomcurrencies/v1/currencies` both return `[]`.
These EconController routes are also served by the `api` worker; they're
These economy routes are also served by the `api` worker; they're
duplicated here because the client calls them on the `econ` host.
## TODO before production
+20 -20
View File
@@ -59,8 +59,8 @@ const app = new Hono<App>()
// Default-unlocked avatar items, served from the bundled static JSON.
.get('/api/avatar/v1/defaultunlocked', (c) => c.json(defaultAvatarItems))
// Default base avatar items. The C# reads the same JSON/defaultAvatarItems.json
// file as defaultunlocked, so it returns the identical catalog.
// Default base avatar items. Reads the same source file as defaultunlocked,
// so it returns the identical catalog.
.get('/api/avatar/v1/defaultbaseavataritems', (c) => c.json(defaultAvatarItems))
// The player's avatar items — owned items concatenated with the default
@@ -72,18 +72,18 @@ const app = new Hono<App>()
return c.json(defaultAvatarItems)
})
// The player's owned custom avatar items. No auth in the C#, which returns
// `{ items: [] }`. The client downloads these when custom-item creation is
// The player's owned custom avatar items. No auth; returns `{ items: [] }`.
// The client downloads these when custom-item creation is
// allowed; a 404 here surfaces as "Failed to download unlocked avatar items".
.get('/econ/customAvatarItems/v1/owned', (c) => c.json({ items: [] }))
// The player's objectives progress. The C# serves a static JSON file
// (JSON/tempmyprogress.json) verbatim with no auth — same default for everyone
// until there's a DB binding to track per-player progress.
// The player's objectives progress. Serves a static JSON file verbatim with
// no auth — same default for everyone until there's a DB binding to track
// per-player progress.
.get('/api/objectives/v1/myprogress', (c) => c.json(myProgress))
// The player's avatar. No DB binding yet, so it always returns the default
// the C# seeds for a player with no PlayerAvatar row.
// for a player with no PlayerAvatar row.
.get('/api/avatar/v2', async (c) => {
const id = await authedId(c)
if (id === null) return unauthorized(c)
@@ -117,18 +117,18 @@ const app = new Hono<App>()
return c.json([])
})
// Unlocked equipment. The C# returns "[]" with no auth.
// Unlocked equipment. Returns "[]" with no auth.
.get('/api/equipment/v2/getUnlocked', (c) => c.json([]))
// Not in CannedNet — room consumables/currencies for a given room. Stubbed
// as empty lists so the client doesn't 404.
// Room consumables/currencies for a given room. Stubbed as empty lists so the
// client doesn't 404.
.get('/api/roomconsumables/v1/roomConsumable/room/:roomId', (c) => c.json([]))
.get('/api/roomconsumables/v1/roomConsumable/room/:roomId/me', (c) => c.json([]))
.get('/api/roomcurrencies/v1/currencies', (c) => c.json([]))
.get('/api/roomcurrencies/v1/getAllBalances', (c) => c.json([]))
// Persist player settings. [Authorize]; the C# replaces the player's settings
// and returns Ok(). No DB binding yet, so accept-and-ack.
// Persist player settings. [Authorize]; would replace the player's settings.
// No DB binding yet, so accept-and-ack.
.post('/api/settings/v2/set', async (c) => {
const id = await authedId(c)
if (id === null) return unauthorized(c)
@@ -152,23 +152,23 @@ const app = new Hono<App>()
return c.json([])
})
// Gift-drop storefront. The C# falls back to JSON/storefront3.json when no
// storefront row exists; that's the bundled static catalog here.
// Gift-drop storefront. Falls back to the bundled static catalog when no
// storefront row exists.
.get('/api/storefronts/v3/giftdropstore/3', (c) => c.json(storefrontGiftDrop3))
// Current weekly challenge. Served from the bundled static JSON (the C#'s
// JSON/weeklychallenge.json) until per-rotation challenge data is wired up.
// Current weekly challenge. Served from the bundled static JSON until
// per-rotation challenge data is wired up.
.get('/api/challenge/v2/getCurrent', (c) => c.json(weeklyChallenge))
// Pending game rewards. The C# returns "[]".
// Pending game rewards. Returns "[]".
.get('/api/gamerewards/v1/pending', (c) => c.json([]))
// The player's room keys. The C# returns "[]".
// The player's room keys. Returns "[]".
.get('/api/roomkeys/v1/mine', (c) => c.json([]))
// Room keys for a given room (client calls this on the econ host). [] with no DB.
.get('/api/roomkeys/v1/room', (c) => c.json([]))
// Subscription lookup. The C# returns both fields null with no auth.
// Subscription lookup. Returns both fields null with no auth.
.post('/api/CampusCard/v1/UpdateAndGetSubscription', (c) =>
c.json({ subscription: null, platformAccountSubscribedPlayerId: null })
)
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* Minimal HS256 JWT validation, mirroring the C# `JwtTokenService.ValidateAndGetAccountId`.
* Minimal HS256 JWT validation.
*
* Uses the same placeholder dev secret as the `auth` worker (`apps/auth/src/jwt.ts`).
* Swap both for a shared secret binding before this is used for anything real.
+1 -1
View File
@@ -3,7 +3,7 @@ import { describe, expect, test } from 'vitest'
import '../../econ.app'
const ORIGIN = 'https://econ.rec.djdevin.net'
const ORIGIN = 'https://example.com'
// Mint a token the way the `auth` worker does, using the same dev secret.
const DEV_SECRET = 'dev-insecure-signing-key-change-me'
+1 -1
View File
@@ -6,7 +6,7 @@
"compatibility_flags": ["nodejs_compat"],
"routes": [
{
"pattern": "econ.rec.djdevin.net",
"pattern": "econ.rec.example.com",
"custom_domain": true
}
],