File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -69,6 +69,14 @@ export const serverEnvSchema = clientEnvSchema.extend({
6969 . int ( )
7070 . positive ( )
7171 . default ( 60 * 60 * 1000 ) ,
72+
73+ // Dev-only override: when 'true', force free-mode requests to the 'limited'
74+ // access tier so the limited UX (single DeepSeek Flash model) can be
75+ // exercised on localhost. Ignored unless NEXT_PUBLIC_CB_ENVIRONMENT === 'dev'.
76+ FREEBUFF_DEV_FORCE_LIMITED : z
77+ . enum ( [ 'true' , 'false' ] )
78+ . default ( 'false' )
79+ . transform ( ( v ) => v === 'true' ) ,
7280} )
7381export const serverEnvVars = serverEnvSchema . keyof ( ) . options
7482export type ServerEnvVar = ( typeof serverEnvVars ) [ number ]
@@ -131,4 +139,5 @@ export const serverProcessEnv: ServerInput = {
131139 // Freebuff waiting room
132140 FREEBUFF_WAITING_ROOM_ENABLED : process . env . FREEBUFF_WAITING_ROOM_ENABLED ,
133141 FREEBUFF_SESSION_LENGTH_MS : process . env . FREEBUFF_SESSION_LENGTH_MS ,
142+ FREEBUFF_DEV_FORCE_LIMITED : process . env . FREEBUFF_DEV_FORCE_LIMITED ,
134143}
Original file line number Diff line number Diff line change @@ -332,6 +332,9 @@ export async function postChatCompletions(params: {
332332 ipinfoToken : env . IPINFO_TOKEN ,
333333 ipHashSecret : env . NEXTAUTH_SECRET ,
334334 allowLocalhost : env . NEXT_PUBLIC_CB_ENVIRONMENT === 'dev' ,
335+ forceLimited :
336+ env . NEXT_PUBLIC_CB_ENVIRONMENT === 'dev' &&
337+ env . FREEBUFF_DEV_FORCE_LIMITED ,
335338 } )
336339 freebuffAccessTier = getFreeModeAccessTier ( countryAccess )
337340
Original file line number Diff line number Diff line change @@ -37,6 +37,9 @@ async function getCountryAccess(
3737 ipinfoToken : env . IPINFO_TOKEN ,
3838 ipHashSecret : env . NEXTAUTH_SECRET ,
3939 allowLocalhost : env . NEXT_PUBLIC_CB_ENVIRONMENT === 'dev' ,
40+ forceLimited :
41+ env . NEXT_PUBLIC_CB_ENVIRONMENT === 'dev' &&
42+ env . FREEBUFF_DEV_FORCE_LIMITED ,
4043 } ,
4144 } )
4245 )
Original file line number Diff line number Diff line change @@ -146,7 +146,7 @@ export async function getCachedFreeModeCountryAccess(params: {
146146 const clientIp = extractClientIp ( req )
147147 const clientIpHash = hashClientIp ( clientIp , options . ipHashSecret )
148148
149- if ( clientIpHash ) {
149+ if ( clientIpHash && ! options . forceLimited ) {
150150 try {
151151 const cached = await cacheStore . get ( {
152152 userId,
Original file line number Diff line number Diff line change @@ -73,6 +73,12 @@ export type FreeModeCountryAccessOptions = {
7373 ipinfoToken : string
7474 ipHashSecret ?: string
7575 allowLocalhost ?: boolean
76+ /** Dev-only escape hatch: when true (and `allowLocalhost` is also true),
77+ * the localhost bypass returns `allowed: false` so callers exercise the
78+ * limited Freebuff tier instead of full. Cache writes/reads are skipped
79+ * for these requests (clientIpHash is nulled) so flipping the flag takes
80+ * effect on the next request without manual cache eviction. */
81+ forceLimited ?: boolean
7682}
7783
7884const LOCALHOST_IPS = new Set ( [ '::1' , '::ffff:127.0.0.1' ] )
@@ -216,6 +222,20 @@ export async function getFreeModeCountryAccess(
216222 ! cfCountry &&
217223 ( ! clientIp || isLocalhostIp ( clientIp ) )
218224 ) {
225+ if ( options . forceLimited ) {
226+ return {
227+ allowed : false ,
228+ countryCode : 'US' ,
229+ blockReason : 'country_not_allowed' ,
230+ cfCountry : null ,
231+ geoipCountry : null ,
232+ ipPrivacy : { signals : [ ] } ,
233+ hasClientIp : Boolean ( clientIp ) ,
234+ // Null hash skips the country-access cache so toggling the env var
235+ // takes effect immediately without evicting prior allowed=true rows.
236+ clientIpHash : null ,
237+ }
238+ }
219239 return {
220240 allowed : true ,
221241 countryCode : 'US' ,
You can’t perform that action at this time.
0 commit comments