From b7a1e8f5cfb119f70cffe9a58c899faa561f2844 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Mon, 8 Dec 2025 20:04:21 -0800 Subject: [PATCH] fix(pre-proc-checks): deployed checks should precede cost/ratelimit increments" (#2250) --- apps/sim/app/api/chat/[identifier]/route.test.ts | 2 +- apps/sim/app/api/webhooks/test/[id]/route.ts | 6 +++++- apps/sim/background/webhook-execution.ts | 2 +- apps/sim/lib/execution/preprocessing.ts | 16 ++++------------ apps/sim/lib/webhooks/processor.ts | 9 +++++++-- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/apps/sim/app/api/chat/[identifier]/route.test.ts b/apps/sim/app/api/chat/[identifier]/route.test.ts index 7e119786b..e1f7ea0f4 100644 --- a/apps/sim/app/api/chat/[identifier]/route.test.ts +++ b/apps/sim/app/api/chat/[identifier]/route.test.ts @@ -364,7 +364,7 @@ describe('Chat Identifier API Route', () => { error: { message: 'Workflow is not deployed', statusCode: 403, - logCreated: true, + logCreated: false, }, }) diff --git a/apps/sim/app/api/webhooks/test/[id]/route.ts b/apps/sim/app/api/webhooks/test/[id]/route.ts index 68f37a279..d66d69f40 100644 --- a/apps/sim/app/api/webhooks/test/[id]/route.ts +++ b/apps/sim/app/api/webhooks/test/[id]/route.ts @@ -69,7 +69,11 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ let preprocessError: NextResponse | null = null try { - preprocessError = await checkWebhookPreprocessing(foundWorkflow, foundWebhook, requestId) + // Test webhooks skip deployment check but still enforce rate limits and usage limits + // They run on live/draft state to allow testing before deployment + preprocessError = await checkWebhookPreprocessing(foundWorkflow, foundWebhook, requestId, { + isTestMode: true, + }) if (preprocessError) { return preprocessError } diff --git a/apps/sim/background/webhook-execution.ts b/apps/sim/background/webhook-execution.ts index 07bab96df..6d4accc90 100644 --- a/apps/sim/background/webhook-execution.ts +++ b/apps/sim/background/webhook-execution.ts @@ -134,7 +134,7 @@ async function executeWebhookJobInternal( const loggingSession = new LoggingSession( payload.workflowId, executionId, - payload.provider || 'webhook', + payload.provider, requestId ) diff --git a/apps/sim/lib/execution/preprocessing.ts b/apps/sim/lib/execution/preprocessing.ts index 7cdd2ae7b..b44fb99d7 100644 --- a/apps/sim/lib/execution/preprocessing.ts +++ b/apps/sim/lib/execution/preprocessing.ts @@ -228,26 +228,18 @@ export async function preprocessExecution( const workspaceId = workflowRecord.workspaceId || providedWorkspaceId || '' // ========== STEP 2: Check Deployment Status ========== + // If workflow is not deployed and deployment is required, reject without logging. + // No log entry or cost should be created for calls to undeployed workflows + // since the workflow was never intended to run. if (checkDeployment && !workflowRecord.isDeployed) { logger.warn(`[${requestId}] Workflow not deployed: ${workflowId}`) - await logPreprocessingError({ - workflowId, - executionId, - triggerType, - requestId, - userId: workflowRecord.userId || userId, - workspaceId, - errorMessage: 'Workflow is not deployed. Please deploy the workflow before triggering it.', - loggingSession: providedLoggingSession, - }) - return { success: false, error: { message: 'Workflow is not deployed', statusCode: 403, - logCreated: true, + logCreated: false, }, } } diff --git a/apps/sim/lib/webhooks/processor.ts b/apps/sim/lib/webhooks/processor.ts index 6b762821b..8f0fd8cad 100644 --- a/apps/sim/lib/webhooks/processor.ts +++ b/apps/sim/lib/webhooks/processor.ts @@ -494,12 +494,17 @@ export async function verifyProviderAuth( /** * Run preprocessing checks for webhook execution * This replaces the old checkRateLimits and checkUsageLimits functions + * + * @param isTestMode - If true, skips deployment check (for test webhooks that run on live/draft state) */ export async function checkWebhookPreprocessing( foundWorkflow: any, foundWebhook: any, - requestId: string + requestId: string, + options?: { isTestMode?: boolean } ): Promise { + const { isTestMode = false } = options || {} + try { const executionId = uuidv4() @@ -510,7 +515,7 @@ export async function checkWebhookPreprocessing( executionId, requestId, checkRateLimit: true, // Webhooks need rate limiting - checkDeployment: true, // Webhooks require deployed workflows + checkDeployment: !isTestMode, // Test webhooks skip deployment check (run on live state) workspaceId: foundWorkflow.workspaceId, })