This commit is contained in:
Devin Zuczek
2026-08-14 00:57:56 -04:00
committed by devin
parent 7430116339
commit dda18b0d2c
8 changed files with 198 additions and 20 deletions
+12 -7
View File
@@ -106,14 +106,15 @@ const NULL_CONNECTION_INFO = {
/**
* The Photon applications the client connects to (`GET /player/connection-info`).
* Temporary placeholders — move them to wrangler vars before they need to differ per
* environment. `photonRegion` matches the value `roomInstanceFromRoom` stamps on every
* Hardcoded temporarily — move them to wrangler vars before they need to differ per
* environment (they are per-deployment ids, not secrets: the client receives all three
* in the clear). `photonRegion` matches the value `roomInstanceFromRoom` stamps on every
* instance, so the two can't disagree ('us' resolves to us-east1 for QoS).
*/
const PHOTON_APPS = {
photonRealtimeAppId: '',
photonVoiceAppId: '',
photonChatAppId: '',
photonRealtimeAppId: 'rf-8f322bdb',
photonVoiceAppId: 'rf-6b4682e1',
photonChatAppId: 'rf-55fae86e',
photonRegion: 'us',
} as const
@@ -1768,8 +1769,12 @@ const app = new Hono<App>()
photonAuthToken,
...PHOTON_APPS,
photonRoomId,
voiceConnectionInfo: null,
voiceServerId: null,
// Empty strings rather than null: there's no separate voice server either
// way, and the client's decoder is likelier to accept a missing-value string
// than a null on a string field. The presence payload's
// NULL_CONNECTION_INFO keeps its nulls — that one never carries credentials.
voiceConnectionInfo: '',
voiceServerId: '',
experiments: PHOTON_EXPERIMENTS,
},
error: null,
+2 -2
View File
@@ -206,8 +206,8 @@ export const ConnectionInfo = z.object({
photonChatAppId: z.string().describe('Photon Chat application id'),
photonRegion: z.string().describe('Region id, matching a room instances `photonRegion`'),
photonRoomId: z.string().describe('The callers current instance; empty when theyre in none'),
voiceConnectionInfo: z.null().describe('Null — no separate voice server'),
voiceServerId: z.null().describe('Null — no separate voice server'),
voiceConnectionInfo: z.literal('').describe('Empty — no separate voice server'),
voiceServerId: z.literal('').describe('Empty — no separate voice server'),
experiments: ConnectionExperiments,
})
+11 -8
View File
@@ -935,16 +935,18 @@ describe('auth-gated endpoints', () => {
value: {
// A signed JWT, not an opaque id — three base64url segments.
photonAuthToken: expect.stringMatching(/^[\w-]+\.[\w-]+\.[\w-]+$/),
photonRealtimeAppId: '',
photonVoiceAppId: '',
photonChatAppId: '',
photonRealtimeAppId: 'rf-8f322bdb',
photonVoiceAppId: 'rf-6b4682e1',
photonChatAppId: 'rf-55fae86e',
// Matches the region every room instance is stamped with.
photonRegion: 'us',
// The room the client is told to join has to be the one matchmaking placed
// them in, or they end up alone in a room of their own.
photonRoomId: matchmaked.roomInstance.photonRoomId,
voiceConnectionInfo: null,
voiceServerId: null,
// Empty strings, not nulls — unlike the presence payload's connection fields,
// which stay null (they never carry credentials).
voiceConnectionInfo: '',
voiceServerId: '',
experiments: {
networkTransformSyncInterval: 10,
shouldUseUnreliableOnChange: false,
@@ -976,9 +978,10 @@ describe('auth-gated endpoints', () => {
'rn.env': string
}
expect(claims.sub).toBe('961')
// Scoped to the realtime app the same response hands out — a placeholder empty
// string until PHOTON_APPS moves to wrangler vars, so assert the two agree rather
// than pinning the placeholder itself.
// Scoped to the realtime app the same response hands out. Asserted as agreement
// rather than a pinned literal: PHOTON_APPS is hardcoded until it moves to wrangler
// vars, and a token minted for a different app than the client is handed is the bug
// worth catching here.
expect(claims.aud).toBe(body.value.photonRealtimeAppId)
expect(claims.exp).toBeGreaterThan(Math.floor(Date.now() / 1000))
// The client is built against prod regardless of which environment we run in.