From 63e36de830125e52d8b4d2a01928874ad06156cd Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Sat, 19 Sep 2026 12:36:32 -0700 Subject: [PATCH] fix(chat): return 403 for inactive chats without writing an execution log --- .../app/api/chat/[identifier]/route.test.ts | 21 ++++++++++ apps/sim/app/api/chat/[identifier]/route.ts | 40 +------------------ 2 files changed, 22 insertions(+), 39 deletions(-) diff --git a/apps/sim/app/api/chat/[identifier]/route.test.ts b/apps/sim/app/api/chat/[identifier]/route.test.ts index d6aa709cd63..c52623c9278 100644 --- a/apps/sim/app/api/chat/[identifier]/route.test.ts +++ b/apps/sim/app/api/chat/[identifier]/route.test.ts @@ -453,6 +453,27 @@ describe('Chat Identifier API Route', () => { }) }) + it('should return 403 for an inactive chat without loading the workflow or writing a log', async () => { + dbChainMockFns.select.mockImplementation(() => ({ + from: vi.fn().mockReturnValue({ + where: vi.fn().mockReturnValue({ + limit: vi.fn().mockReturnValue([{ ...mockChatResult[0], isActive: false }]), + }), + }), + })) + const req = createMockNextRequest('POST', { input: 'x' }) + + const response = await POST(req, { params: Promise.resolve({ identifier: 'paused-chat' }) }) + + expect(response.status).toBe(403) + const data = await response.json() + expect(data).toHaveProperty('message', 'This chat is currently unavailable') + expect(dbChainMockFns.select).toHaveBeenCalledTimes(1) + expect(loggingSessionMockFns.mockSafeStart).not.toHaveBeenCalled() + expect(loggingSessionMockFns.mockSafeCompleteWithError).not.toHaveBeenCalled() + expect(mockValidateChatAuth).not.toHaveBeenCalled() + }) + it('should return 400 for requests without input', async () => { const req = createMockNextRequest('POST', {}) const params = Promise.resolve({ identifier: 'test-chat' }) diff --git a/apps/sim/app/api/chat/[identifier]/route.ts b/apps/sim/app/api/chat/[identifier]/route.ts index ec5abdec4cc..e83a6c0a632 100644 --- a/apps/sim/app/api/chat/[identifier]/route.ts +++ b/apps/sim/app/api/chat/[identifier]/route.ts @@ -1,5 +1,5 @@ import { db } from '@sim/db' -import { chat, workflow } from '@sim/db/schema' +import { chat } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { generateId } from '@sim/utils/id' import { and, eq, isNull } from 'drizzle-orm' @@ -156,44 +156,6 @@ export const POST = withRouteHandler( if (!deployment.isActive) { logger.warn(`[${requestId}] Chat is not active: ${identifier}`) - - const [workflowRecord] = await db - .select({ workspaceId: workflow.workspaceId }) - .from(workflow) - .where(and(eq(workflow.id, deployment.workflowId), isNull(workflow.archivedAt))) - .limit(1) - - const workspaceId = workflowRecord?.workspaceId - if (!workspaceId) { - logger.warn( - `[${requestId}] Cannot log: workflow ${deployment.workflowId} has no workspace` - ) - return createErrorResponse('This chat is currently unavailable', 403) - } - - const executionId = generateId() - const loggingSession = new LoggingSession( - deployment.workflowId, - executionId, - 'chat', - requestId - ) - - await loggingSession.safeStart({ - userId: deployment.userId, - workspaceId, - variables: {}, - }) - - await loggingSession.safeCompleteWithError({ - error: { - message: 'This chat is currently unavailable. The chat has been disabled.', - stackTrace: undefined, - }, - traceSpans: [], - skipCost: true, - }) - return createErrorResponse('This chat is currently unavailable', 403) }