From a6ca779677a49d01ced54929c2fd149532e82e44 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 22 May 2026 19:12:41 +0300 Subject: [PATCH 1/2] =?UTF-8?q?fix(auth):=20PR=20review=20fixes=20?= =?UTF-8?q?=E2=80=94=20SSE=20keepalive,=20error=20shape,=20test=20env=20is?= =?UTF-8?q?olation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add ping=15 to both EventSourceResponse calls so cloud LB idle timeouts don't drop long-running wiki generation / project recompute SSE streams - Return { error, message } in registration-disabled 403 responses so clients reading either field get the reason ([...all] and /register endpoints) - Replace process.env={...clone} with per-key save/restore in both route tests; full env replacement can leak state between test suites in Node Co-Authored-By: Claude Sonnet 4.6 --- backend/app/api/routes.py | 4 ++-- .../api/auth/[...all]/__tests__/route.test.ts | 13 +++++++++---- web/src/app/api/auth/[...all]/route.ts | 2 +- .../api/auth/config/__tests__/route.test.ts | 18 ++++++++++++++---- web/src/app/api/auth/register/route.ts | 2 +- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/backend/app/api/routes.py b/backend/app/api/routes.py index a09e133..74a80a3 100644 --- a/backend/app/api/routes.py +++ b/backend/app/api/routes.py @@ -307,7 +307,7 @@ async def event_generator(): data=event.model_dump_json(), ) - return EventSourceResponse(event_generator()) + return EventSourceResponse(event_generator(), ping=15) # --------------------------------------------------------------------------- @@ -1721,7 +1721,7 @@ async def event_generator(): data=evt.model_dump_json() if hasattr(evt, "model_dump_json") else _json.dumps(evt), ) - return EventSourceResponse(event_generator()) + return EventSourceResponse(event_generator(), ping=15) @router.get("/projects/{project_id}/search", response_model=ProjectSearchResponse) diff --git a/web/src/app/api/auth/[...all]/__tests__/route.test.ts b/web/src/app/api/auth/[...all]/__tests__/route.test.ts index 890c5d6..2c9727c 100644 --- a/web/src/app/api/auth/[...all]/__tests__/route.test.ts +++ b/web/src/app/api/auth/[...all]/__tests__/route.test.ts @@ -15,14 +15,18 @@ function makePost(pathname: string) { } describe('POST /api/auth/[...all] — registration guard', () => { - const originalEnv = process.env; + const WATCHED = ['ALLOW_REGISTRATION'] as const; + const saved: Partial> = {}; beforeEach(() => { - process.env = { ...originalEnv }; + for (const key of WATCHED) saved[key] = process.env[key]; }); - afterAll(() => { - process.env = originalEnv; + afterEach(() => { + for (const key of WATCHED) { + if (saved[key] === undefined) delete process.env[key]; + else process.env[key] = saved[key]; + } }); it('blocks /sign-up/email with 403 when ALLOW_REGISTRATION=false', async () => { @@ -32,6 +36,7 @@ describe('POST /api/auth/[...all] — registration guard', () => { expect(res.status).toBe(403); const body = await res.json(); + expect(body.error).toBe('Registration is disabled'); expect(body.message).toBe('Registration is disabled'); }); diff --git a/web/src/app/api/auth/[...all]/route.ts b/web/src/app/api/auth/[...all]/route.ts index 3cb2781..72f1b39 100644 --- a/web/src/app/api/auth/[...all]/route.ts +++ b/web/src/app/api/auth/[...all]/route.ts @@ -10,7 +10,7 @@ export const GET = handlers.GET; export async function POST(request: NextRequest, _context: { params: Promise<{ all: string[] }> }) { const url = new URL(request.url); if (process.env.ALLOW_REGISTRATION === 'false' && url.pathname === '/api/auth/sign-up/email') { - return NextResponse.json({ message: 'Registration is disabled' }, { status: 403 }); + return NextResponse.json({ error: 'Registration is disabled', message: 'Registration is disabled' }, { status: 403 }); } return handlers.POST(request); } diff --git a/web/src/app/api/auth/config/__tests__/route.test.ts b/web/src/app/api/auth/config/__tests__/route.test.ts index 99042bc..be04fb6 100644 --- a/web/src/app/api/auth/config/__tests__/route.test.ts +++ b/web/src/app/api/auth/config/__tests__/route.test.ts @@ -1,14 +1,24 @@ import { GET } from '../route'; describe('GET /api/auth/config', () => { - const originalEnv = process.env; + const WATCHED = [ + 'GITHUB_CLIENT_ID', + 'GITHUB_CLIENT_SECRET', + 'GOOGLE_CLIENT_ID', + 'GOOGLE_CLIENT_SECRET', + 'ALLOW_REGISTRATION', + ] as const; + const saved: Partial> = {}; beforeEach(() => { - process.env = { ...originalEnv }; + for (const key of WATCHED) saved[key] = process.env[key]; }); - afterAll(() => { - process.env = originalEnv; + afterEach(() => { + for (const key of WATCHED) { + if (saved[key] === undefined) delete process.env[key]; + else process.env[key] = saved[key]; + } }); it('returns github=true when both GitHub secrets are set', async () => { diff --git a/web/src/app/api/auth/register/route.ts b/web/src/app/api/auth/register/route.ts index 19da03d..4727c0f 100644 --- a/web/src/app/api/auth/register/route.ts +++ b/web/src/app/api/auth/register/route.ts @@ -3,7 +3,7 @@ import { auth } from '@/lib/auth'; export async function POST(request: Request) { if (process.env.ALLOW_REGISTRATION === 'false') { - return NextResponse.json({ error: 'Registration is disabled' }, { status: 403 }); + return NextResponse.json({ error: 'Registration is disabled', message: 'Registration is disabled' }, { status: 403 }); } let body: { username?: string; password?: string; email?: string }; From f4a824826b3272eaa8b43f793056f76ccbee4850 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 22 May 2026 20:32:16 +0300 Subject: [PATCH 2/2] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- web/src/app/api/auth/register/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/app/api/auth/register/route.ts b/web/src/app/api/auth/register/route.ts index 4727c0f..19da03d 100644 --- a/web/src/app/api/auth/register/route.ts +++ b/web/src/app/api/auth/register/route.ts @@ -3,7 +3,7 @@ import { auth } from '@/lib/auth'; export async function POST(request: Request) { if (process.env.ALLOW_REGISTRATION === 'false') { - return NextResponse.json({ error: 'Registration is disabled', message: 'Registration is disabled' }, { status: 403 }); + return NextResponse.json({ error: 'Registration is disabled' }, { status: 403 }); } let body: { username?: string; password?: string; email?: string };