Skip to content

Commit 6befd51

Browse files
committed
Allow team@codebuff.com to bypass waiting room
1 parent 21d5dd3 commit 6befd51

File tree

5 files changed

+81
-9
lines changed

5 files changed

+81
-9
lines changed

web/src/app/api/v1/chat/completions/_post.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,11 @@ export async function postChatCompletions(params: {
413413
if (isFreeModeRequest) {
414414
const claimedInstanceId =
415415
typedBody.codebuff_metadata?.freebuff_instance_id
416-
const gate = await checkSession({ userId, claimedInstanceId })
416+
const gate = await checkSession({
417+
userId,
418+
userEmail: userInfo.email,
419+
claimedInstanceId,
420+
})
417421
if (!gate.ok) {
418422
trackEvent({
419423
event: AnalyticsEvent.CHAT_COMPLETIONS_VALIDATION_ERROR,

web/src/app/api/v1/freebuff/session/_handlers.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ export interface FreebuffSessionDeps {
2222
sessionDeps?: SessionDeps
2323
}
2424

25-
type AuthResult = { error: NextResponse } | { userId: string }
25+
type AuthResult =
26+
| { error: NextResponse }
27+
| { userId: string; userEmail: string | null }
2628

2729
async function resolveUser(req: NextRequest, deps: FreebuffSessionDeps): Promise<AuthResult> {
2830
const apiKey = extractApiKeyFromHeader(req)
@@ -39,7 +41,7 @@ async function resolveUser(req: NextRequest, deps: FreebuffSessionDeps): Promise
3941
}
4042
const userInfo = await deps.getUserInfoFromApiKey({
4143
apiKey,
42-
fields: ['id'],
44+
fields: ['id', 'email'],
4345
logger: deps.logger,
4446
})
4547
if (!userInfo?.id) {
@@ -50,7 +52,7 @@ async function resolveUser(req: NextRequest, deps: FreebuffSessionDeps): Promise
5052
),
5153
}
5254
}
53-
return { userId: String(userInfo.id) }
55+
return { userId: String(userInfo.id), userEmail: userInfo.email ?? null }
5456
}
5557

5658
function serverError(
@@ -96,6 +98,7 @@ export async function postFreebuffSession(
9698
try {
9799
const state = await requestSession({
98100
userId: auth.userId,
101+
userEmail: auth.userEmail,
99102
deps: deps.sessionDeps,
100103
})
101104
return NextResponse.json(state, { status: 200 })
@@ -118,6 +121,7 @@ export async function getFreebuffSession(
118121
const claimedInstanceId = req.headers.get(FREEBUFF_INSTANCE_HEADER) ?? undefined
119122
const state = await getSessionState({
120123
userId: auth.userId,
124+
userEmail: auth.userEmail,
121125
claimedInstanceId,
122126
deps: deps.sessionDeps,
123127
})
@@ -142,7 +146,11 @@ export async function deleteFreebuffSession(
142146
if ('error' in auth) return auth.error
143147

144148
try {
145-
await endUserSession({ userId: auth.userId, deps: deps.sessionDeps })
149+
await endUserSession({
150+
userId: auth.userId,
151+
userEmail: auth.userEmail,
152+
deps: deps.sessionDeps,
153+
})
146154
return NextResponse.json({ status: 'ended' }, { status: 200 })
147155
} catch (error) {
148156
return serverError(deps, 'DELETE', auth.userId, error)

web/src/server/free-session/__tests__/public-api.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,29 @@ describe('checkSessionAdmissible', () => {
281281
expect(result.code).toBe('waiting_room_required')
282282
})
283283

284+
test('bypassed email (team@codebuff.com) → ok with reason=disabled, no DB read', async () => {
285+
const result = await checkSessionAdmissible({
286+
userId: 'u1',
287+
userEmail: 'team@codebuff.com',
288+
claimedInstanceId: undefined,
289+
deps,
290+
})
291+
expect(result.ok).toBe(true)
292+
if (!result.ok) throw new Error('unreachable')
293+
expect(result.reason).toBe('disabled')
294+
expect(deps.rows.size).toBe(0)
295+
})
296+
297+
test('bypassed email is case-insensitive', async () => {
298+
const result = await checkSessionAdmissible({
299+
userId: 'u1',
300+
userEmail: 'Team@Codebuff.COM',
301+
claimedInstanceId: undefined,
302+
deps,
303+
})
304+
expect(result.ok).toBe(true)
305+
})
306+
284307
test('queued session → waiting_room_queued', async () => {
285308
await requestSession({ userId: 'u1', deps })
286309
const result = await checkSessionAdmissible({

web/src/server/free-session/config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ export function isWaitingRoomEnabled(): boolean {
1616
return env.FREEBUFF_WAITING_ROOM_ENABLED
1717
}
1818

19+
/** Per-account override on top of the global kill switch. The internal
20+
* `team@codebuff.com` account drives e2e tests in CI; landing it in the
21+
* queue would make those tests flake whenever the waiting room is warm.
22+
* Bypassed users behave exactly as if the waiting room were disabled. */
23+
const WAITING_ROOM_BYPASS_EMAILS = new Set<string>(['team@codebuff.com'])
24+
export function isWaitingRoomBypassedForEmail(
25+
email: string | null | undefined,
26+
): boolean {
27+
if (!email) return false
28+
return WAITING_ROOM_BYPASS_EMAILS.has(email.toLowerCase())
29+
}
30+
1931
export function getSessionLengthMs(): number {
2032
return env.FREEBUFF_SESSION_LENGTH_MS
2133
}

web/src/server/free-session/public-api.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
getSessionGraceMs,
3+
isWaitingRoomBypassedForEmail,
34
isWaitingRoomEnabled,
45
} from './config'
56
import {
@@ -79,10 +80,16 @@ async function viewForRow(
7980
*/
8081
export async function requestSession(params: {
8182
userId: string
83+
userEmail?: string | null | undefined
8284
deps?: SessionDeps
8385
}): Promise<SessionStateResponse> {
8486
const deps = params.deps ?? defaultDeps
85-
if (!deps.isWaitingRoomEnabled()) return { status: 'disabled' }
87+
if (
88+
!deps.isWaitingRoomEnabled() ||
89+
isWaitingRoomBypassedForEmail(params.userEmail)
90+
) {
91+
return { status: 'disabled' }
92+
}
8693

8794
const row = await deps.joinOrTakeOver({ userId: params.userId, now: nowOf(deps) })
8895
const view = await viewForRow(params.userId, deps, row)
@@ -109,11 +116,17 @@ export async function requestSession(params: {
109116
*/
110117
export async function getSessionState(params: {
111118
userId: string
119+
userEmail?: string | null | undefined
112120
claimedInstanceId?: string | null | undefined
113121
deps?: SessionDeps
114122
}): Promise<FreebuffSessionServerResponse> {
115123
const deps = params.deps ?? defaultDeps
116-
if (!deps.isWaitingRoomEnabled()) return { status: 'disabled' }
124+
if (
125+
!deps.isWaitingRoomEnabled() ||
126+
isWaitingRoomBypassedForEmail(params.userEmail)
127+
) {
128+
return { status: 'disabled' }
129+
}
117130
const row = await deps.getSessionRow(params.userId)
118131
if (!row) return { status: 'none' }
119132

@@ -132,10 +145,16 @@ export async function getSessionState(params: {
132145

133146
export async function endUserSession(params: {
134147
userId: string
148+
userEmail?: string | null | undefined
135149
deps?: SessionDeps
136150
}): Promise<void> {
137151
const deps = params.deps ?? defaultDeps
138-
if (!deps.isWaitingRoomEnabled()) return
152+
if (
153+
!deps.isWaitingRoomEnabled() ||
154+
isWaitingRoomBypassedForEmail(params.userEmail)
155+
) {
156+
return
157+
}
139158
await deps.endSession(params.userId)
140159
}
141160

@@ -169,11 +188,17 @@ export type SessionGateResult =
169188
*/
170189
export async function checkSessionAdmissible(params: {
171190
userId: string
191+
userEmail?: string | null | undefined
172192
claimedInstanceId: string | null | undefined
173193
deps?: SessionDeps
174194
}): Promise<SessionGateResult> {
175195
const deps = params.deps ?? defaultDeps
176-
if (!deps.isWaitingRoomEnabled()) return { ok: true, reason: 'disabled' }
196+
if (
197+
!deps.isWaitingRoomEnabled() ||
198+
isWaitingRoomBypassedForEmail(params.userEmail)
199+
) {
200+
return { ok: true, reason: 'disabled' }
201+
}
177202

178203
// Pre-waiting-room CLIs never send a freebuff_instance_id. Classify that up
179204
// front so the caller gets a distinct code (→ 426 Upgrade Required) and the

0 commit comments

Comments
 (0)