From 53de6f6c09f3f9617b8e34c7c4c41d1882854345 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Sun, 10 May 2026 00:05:54 -0700 Subject: [PATCH 1/4] Allow France in free mode country gate --- .../api/v1/freebuff/session/__tests__/session.test.ts | 10 +++++----- web/src/server/__tests__/free-mode-country.test.ts | 8 +++++--- web/src/server/free-mode-country.ts | 1 + 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts b/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts index af77ac8f5..26393814f 100644 --- a/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts +++ b/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts @@ -230,7 +230,7 @@ describe('POST /api/v1/freebuff/session', () => { test('returns country_blocked without joining the queue for disallowed country', async () => { const sessionDeps = makeSessionDeps() const resp = await postFreebuffSession( - makeReq('ok', { cfCountry: 'FR' }), + makeReq('ok', { cfCountry: 'ES' }), makeDeps(sessionDeps, 'u1'), ) // 403 (not 200) so older CLIs that don't know `country_blocked` fall into @@ -238,7 +238,7 @@ describe('POST /api/v1/freebuff/session', () => { expect(resp.status).toBe(403) const body = await resp.json() expect(body.status).toBe('country_blocked') - expect(body.countryCode).toBe('FR') + expect(body.countryCode).toBe('ES') expect(body.countryBlockReason).toBe('country_not_allowed') expect(sessionDeps.rows.size).toBe(0) }) @@ -326,13 +326,13 @@ describe('GET /api/v1/freebuff/session', () => { test('returns country_blocked for disallowed country on GET', async () => { const sessionDeps = makeSessionDeps() const resp = await getFreebuffSession( - makeReq('ok', { cfCountry: 'FR' }), + makeReq('ok', { cfCountry: 'ES' }), makeDeps(sessionDeps, 'u1'), ) expect(resp.status).toBe(403) const body = await resp.json() expect(body.status).toBe('country_blocked') - expect(body.countryCode).toBe('FR') + expect(body.countryCode).toBe('ES') expect(body.countryBlockReason).toBe('country_not_allowed') }) @@ -358,7 +358,7 @@ describe('GET /api/v1/freebuff/session', () => { }) let countryChecks = 0 const resp = await getFreebuffSession( - makeReq('ok', { cfCountry: 'FR' }), + makeReq('ok', { cfCountry: 'ES' }), makeDeps(sessionDeps, 'u1', { getCountryAccess: async (req) => { countryChecks++ diff --git a/web/src/server/__tests__/free-mode-country.test.ts b/web/src/server/__tests__/free-mode-country.test.ts index 2166f49c9..4d946518f 100644 --- a/web/src/server/__tests__/free-mode-country.test.ts +++ b/web/src/server/__tests__/free-mode-country.test.ts @@ -29,6 +29,8 @@ describe('free mode country access', () => { ['SG', 'SG'], ['MT', 'MT'], ['IL', 'IL'], + ['FR', 'FR'], + ['BE', 'BE'], ])('allows allowlisted Cloudflare country %s', async (header, expected) => { const access = await getFreeModeCountryAccess( makeReq({ @@ -44,11 +46,11 @@ describe('free mode country access', () => { test('blocks countries outside the allowlist', async () => { const access = await getFreeModeCountryAccess( - makeReq({ 'cf-ipcountry': 'FR' }), + makeReq({ 'cf-ipcountry': 'ES' }), noAnonymousNetwork, ) expect(access.allowed).toBe(false) - expect(access.countryCode).toBe('FR') + expect(access.countryCode).toBe('ES') expect(access.blockReason).toBe('country_not_allowed') }) @@ -295,7 +297,7 @@ describe('free mode country access', () => { test('allowLocalhost does not bypass when cf-ipcountry is set', async () => { const access = await getFreeModeCountryAccess( - makeReq({ 'cf-ipcountry': 'FR' }), + makeReq({ 'cf-ipcountry': 'ES' }), { ipinfoToken: 'test-token', allowLocalhost: true, diff --git a/web/src/server/free-mode-country.ts b/web/src/server/free-mode-country.ts index 4e5457dd4..94d28298e 100644 --- a/web/src/server/free-mode-country.ts +++ b/web/src/server/free-mode-country.ts @@ -19,6 +19,7 @@ export const FREE_MODE_ALLOWED_COUNTRIES = new Set([ 'NL', 'DK', 'DE', + 'FR', 'FI', 'BE', 'LU', From 269bcb79af486a03e341a41449287c2aa8bd2002 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Sun, 10 May 2026 00:08:51 -0700 Subject: [PATCH 2/4] Allow Italy and Spain in free mode country gate --- .../api/v1/freebuff/session/__tests__/session.test.ts | 10 +++++----- web/src/server/__tests__/free-mode-country.test.ts | 8 +++++--- web/src/server/free-mode-country.ts | 2 ++ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts b/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts index 26393814f..6a54a390a 100644 --- a/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts +++ b/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts @@ -230,7 +230,7 @@ describe('POST /api/v1/freebuff/session', () => { test('returns country_blocked without joining the queue for disallowed country', async () => { const sessionDeps = makeSessionDeps() const resp = await postFreebuffSession( - makeReq('ok', { cfCountry: 'ES' }), + makeReq('ok', { cfCountry: 'PT' }), makeDeps(sessionDeps, 'u1'), ) // 403 (not 200) so older CLIs that don't know `country_blocked` fall into @@ -238,7 +238,7 @@ describe('POST /api/v1/freebuff/session', () => { expect(resp.status).toBe(403) const body = await resp.json() expect(body.status).toBe('country_blocked') - expect(body.countryCode).toBe('ES') + expect(body.countryCode).toBe('PT') expect(body.countryBlockReason).toBe('country_not_allowed') expect(sessionDeps.rows.size).toBe(0) }) @@ -326,13 +326,13 @@ describe('GET /api/v1/freebuff/session', () => { test('returns country_blocked for disallowed country on GET', async () => { const sessionDeps = makeSessionDeps() const resp = await getFreebuffSession( - makeReq('ok', { cfCountry: 'ES' }), + makeReq('ok', { cfCountry: 'PT' }), makeDeps(sessionDeps, 'u1'), ) expect(resp.status).toBe(403) const body = await resp.json() expect(body.status).toBe('country_blocked') - expect(body.countryCode).toBe('ES') + expect(body.countryCode).toBe('PT') expect(body.countryBlockReason).toBe('country_not_allowed') }) @@ -358,7 +358,7 @@ describe('GET /api/v1/freebuff/session', () => { }) let countryChecks = 0 const resp = await getFreebuffSession( - makeReq('ok', { cfCountry: 'ES' }), + makeReq('ok', { cfCountry: 'PT' }), makeDeps(sessionDeps, 'u1', { getCountryAccess: async (req) => { countryChecks++ diff --git a/web/src/server/__tests__/free-mode-country.test.ts b/web/src/server/__tests__/free-mode-country.test.ts index 4d946518f..489e6cb9b 100644 --- a/web/src/server/__tests__/free-mode-country.test.ts +++ b/web/src/server/__tests__/free-mode-country.test.ts @@ -31,6 +31,8 @@ describe('free mode country access', () => { ['IL', 'IL'], ['FR', 'FR'], ['BE', 'BE'], + ['IT', 'IT'], + ['ES', 'ES'], ])('allows allowlisted Cloudflare country %s', async (header, expected) => { const access = await getFreeModeCountryAccess( makeReq({ @@ -46,11 +48,11 @@ describe('free mode country access', () => { test('blocks countries outside the allowlist', async () => { const access = await getFreeModeCountryAccess( - makeReq({ 'cf-ipcountry': 'ES' }), + makeReq({ 'cf-ipcountry': 'PT' }), noAnonymousNetwork, ) expect(access.allowed).toBe(false) - expect(access.countryCode).toBe('ES') + expect(access.countryCode).toBe('PT') expect(access.blockReason).toBe('country_not_allowed') }) @@ -297,7 +299,7 @@ describe('free mode country access', () => { test('allowLocalhost does not bypass when cf-ipcountry is set', async () => { const access = await getFreeModeCountryAccess( - makeReq({ 'cf-ipcountry': 'ES' }), + makeReq({ 'cf-ipcountry': 'PT' }), { ipinfoToken: 'test-token', allowLocalhost: true, diff --git a/web/src/server/free-mode-country.ts b/web/src/server/free-mode-country.ts index 94d28298e..ef6d7392a 100644 --- a/web/src/server/free-mode-country.ts +++ b/web/src/server/free-mode-country.ts @@ -20,6 +20,8 @@ export const FREE_MODE_ALLOWED_COUNTRIES = new Set([ 'DK', 'DE', 'FR', + 'IT', + 'ES', 'FI', 'BE', 'LU', From 216268f358143aaece438fb16024fb64e17f64b5 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Sun, 10 May 2026 00:10:56 -0700 Subject: [PATCH 3/4] Allow Portugal in free mode country gate --- .../api/v1/freebuff/session/__tests__/session.test.ts | 10 +++++----- web/src/server/__tests__/free-mode-country.test.ts | 7 ++++--- web/src/server/free-mode-country.ts | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts b/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts index 6a54a390a..edc852f6e 100644 --- a/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts +++ b/web/src/app/api/v1/freebuff/session/__tests__/session.test.ts @@ -230,7 +230,7 @@ describe('POST /api/v1/freebuff/session', () => { test('returns country_blocked without joining the queue for disallowed country', async () => { const sessionDeps = makeSessionDeps() const resp = await postFreebuffSession( - makeReq('ok', { cfCountry: 'PT' }), + makeReq('ok', { cfCountry: 'JP' }), makeDeps(sessionDeps, 'u1'), ) // 403 (not 200) so older CLIs that don't know `country_blocked` fall into @@ -238,7 +238,7 @@ describe('POST /api/v1/freebuff/session', () => { expect(resp.status).toBe(403) const body = await resp.json() expect(body.status).toBe('country_blocked') - expect(body.countryCode).toBe('PT') + expect(body.countryCode).toBe('JP') expect(body.countryBlockReason).toBe('country_not_allowed') expect(sessionDeps.rows.size).toBe(0) }) @@ -326,13 +326,13 @@ describe('GET /api/v1/freebuff/session', () => { test('returns country_blocked for disallowed country on GET', async () => { const sessionDeps = makeSessionDeps() const resp = await getFreebuffSession( - makeReq('ok', { cfCountry: 'PT' }), + makeReq('ok', { cfCountry: 'JP' }), makeDeps(sessionDeps, 'u1'), ) expect(resp.status).toBe(403) const body = await resp.json() expect(body.status).toBe('country_blocked') - expect(body.countryCode).toBe('PT') + expect(body.countryCode).toBe('JP') expect(body.countryBlockReason).toBe('country_not_allowed') }) @@ -358,7 +358,7 @@ describe('GET /api/v1/freebuff/session', () => { }) let countryChecks = 0 const resp = await getFreebuffSession( - makeReq('ok', { cfCountry: 'PT' }), + makeReq('ok', { cfCountry: 'JP' }), makeDeps(sessionDeps, 'u1', { getCountryAccess: async (req) => { countryChecks++ diff --git a/web/src/server/__tests__/free-mode-country.test.ts b/web/src/server/__tests__/free-mode-country.test.ts index 489e6cb9b..badf04377 100644 --- a/web/src/server/__tests__/free-mode-country.test.ts +++ b/web/src/server/__tests__/free-mode-country.test.ts @@ -33,6 +33,7 @@ describe('free mode country access', () => { ['BE', 'BE'], ['IT', 'IT'], ['ES', 'ES'], + ['PT', 'PT'], ])('allows allowlisted Cloudflare country %s', async (header, expected) => { const access = await getFreeModeCountryAccess( makeReq({ @@ -48,11 +49,11 @@ describe('free mode country access', () => { test('blocks countries outside the allowlist', async () => { const access = await getFreeModeCountryAccess( - makeReq({ 'cf-ipcountry': 'PT' }), + makeReq({ 'cf-ipcountry': 'JP' }), noAnonymousNetwork, ) expect(access.allowed).toBe(false) - expect(access.countryCode).toBe('PT') + expect(access.countryCode).toBe('JP') expect(access.blockReason).toBe('country_not_allowed') }) @@ -299,7 +300,7 @@ describe('free mode country access', () => { test('allowLocalhost does not bypass when cf-ipcountry is set', async () => { const access = await getFreeModeCountryAccess( - makeReq({ 'cf-ipcountry': 'PT' }), + makeReq({ 'cf-ipcountry': 'JP' }), { ipinfoToken: 'test-token', allowLocalhost: true, diff --git a/web/src/server/free-mode-country.ts b/web/src/server/free-mode-country.ts index ef6d7392a..d586a55eb 100644 --- a/web/src/server/free-mode-country.ts +++ b/web/src/server/free-mode-country.ts @@ -22,6 +22,7 @@ export const FREE_MODE_ALLOWED_COUNTRIES = new Set([ 'FR', 'IT', 'ES', + 'PT', 'FI', 'BE', 'LU', From 617973f80aae015499dad5bdd91736aed50e4def Mon Sep 17 00:00:00 2001 From: James Grugett Date: Sun, 10 May 2026 00:13:10 -0700 Subject: [PATCH 4/4] Update Freebuff country FAQ --- freebuff/web/src/app/home-client.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freebuff/web/src/app/home-client.tsx b/freebuff/web/src/app/home-client.tsx index d191f8681..4721640f9 100644 --- a/freebuff/web/src/app/home-client.tsx +++ b/freebuff/web/src/app/home-client.tsx @@ -31,7 +31,7 @@ const faqs = [ { question: 'Which countries is Freebuff available in?', answer: - 'Freebuff is currently available in:\n\nUnited States, Canada, United Kingdom, Australia, New Zealand, Norway, Sweden, Netherlands, Denmark, Germany, Finland, Belgium, Luxembourg, Liechtenstein, Switzerland, Austria, Singapore, Malta, Israel, Ireland, and Iceland.', + 'Freebuff is currently available in:\n\nUnited States, Canada, United Kingdom, Australia, New Zealand, Norway, Sweden, Netherlands, Denmark, Germany, France, Italy, Spain, Portugal, Finland, Belgium, Luxembourg, Liechtenstein, Switzerland, Austria, Singapore, Malta, Israel, Ireland, and Iceland.', }, { question: 'Are you training on my data?',