@@ -50,7 +50,7 @@ export interface FreebuffSessionDeps {
5050
5151type AuthResult =
5252 | { error : NextResponse }
53- | { userId : string ; userEmail : string | null }
53+ | { userId : string ; userEmail : string | null ; userBanned : boolean }
5454
5555async function resolveUser ( req : NextRequest , deps : FreebuffSessionDeps ) : Promise < AuthResult > {
5656 const apiKey = extractApiKeyFromHeader ( req )
@@ -67,7 +67,7 @@ async function resolveUser(req: NextRequest, deps: FreebuffSessionDeps): Promise
6767 }
6868 const userInfo = await deps . getUserInfoFromApiKey ( {
6969 apiKey,
70- fields : [ 'id' , 'email' ] ,
70+ fields : [ 'id' , 'email' , 'banned' ] ,
7171 logger : deps . logger ,
7272 } )
7373 if ( ! userInfo ?. id ) {
@@ -78,7 +78,11 @@ async function resolveUser(req: NextRequest, deps: FreebuffSessionDeps): Promise
7878 ) ,
7979 }
8080 }
81- return { userId : String ( userInfo . id ) , userEmail : userInfo . email ?? null }
81+ return {
82+ userId : String ( userInfo . id ) ,
83+ userEmail : userInfo . email ?? null ,
84+ userBanned : Boolean ( userInfo . banned ) ,
85+ }
8286}
8387
8488function serverError (
@@ -130,13 +134,16 @@ export async function postFreebuffSession(
130134 const state = await requestSession ( {
131135 userId : auth . userId ,
132136 userEmail : auth . userEmail ,
137+ userBanned : auth . userBanned ,
133138 model : requestedModel ,
134139 deps : deps . sessionDeps ,
135140 } )
136141 // model_locked is a 409 so it's distinguishable from a normal queued/active
137- // response on the client. The CLI translates it into a "switch model?"
138- // confirmation prompt.
139- const status = state . status === 'model_locked' ? 409 : 200
142+ // response on the client. banned is a 403 (terminal, mirrors country_blocked)
143+ // so older CLIs that don't know the status fall into their `!resp.ok` error
144+ // path and back off instead of tight-polling on the unrecognized 200 body.
145+ const status =
146+ state . status === 'model_locked' ? 409 : state . status === 'banned' ? 403 : 200
140147 return NextResponse . json ( state , { status } )
141148 } catch ( error ) {
142149 return serverError ( deps , 'POST' , auth . userId , error )
@@ -161,6 +168,7 @@ export async function getFreebuffSession(
161168 const state = await getSessionState ( {
162169 userId : auth . userId ,
163170 userEmail : auth . userEmail ,
171+ userBanned : auth . userBanned ,
164172 claimedInstanceId,
165173 deps : deps . sessionDeps ,
166174 } )
@@ -174,7 +182,10 @@ export async function getFreebuffSession(
174182 { status : 200 } ,
175183 )
176184 }
177- return NextResponse . json ( state , { status : 200 } )
185+ // banned is terminal; 403 for the same reason as country_blocked — older
186+ // CLIs that don't know this status treat it as a generic error.
187+ const status = state . status === 'banned' ? 403 : 200
188+ return NextResponse . json ( state , { status } )
178189 } catch ( error ) {
179190 return serverError ( deps , 'GET' , auth . userId , error )
180191 }
0 commit comments