diff --git a/apps/sim/app/api/workflows/[id]/log/route.test.ts b/apps/sim/app/api/workflows/[id]/log/route.test.ts deleted file mode 100644 index 4523b538298..00000000000 --- a/apps/sim/app/api/workflows/[id]/log/route.test.ts +++ /dev/null @@ -1,300 +0,0 @@ -import { authMockFns, dbChainMockFns, resetDbChainMock } from '@sim/testing' -import { createRouteContext } from '@sim/testing/helpers/http' -import { - billingAttributionMock, - billingAttributionMockFns, -} from '@sim/testing/mocks/billing-attribution.mock' -import { loggingSessionMock, loggingSessionMockFns } from '@sim/testing/mocks/logging-session.mock' -import { createMockRequest } from '@sim/testing/mocks/request.mock' -import { - workspacesUtilsMock, - workspacesUtilsMockFns, -} from '@sim/testing/mocks/workspaces-utils.mock' -import { beforeEach, describe, expect, it, vi } from 'vitest' - -const { mockValidateWorkflowAccess } = vi.hoisted(() => ({ - mockValidateWorkflowAccess: vi.fn(), -})) - -vi.mock('@/app/api/workflows/middleware', () => ({ - validateWorkflowAccess: mockValidateWorkflowAccess, -})) - -vi.mock('@/lib/workspaces/utils', () => workspacesUtilsMock) - -vi.mock('@/lib/billing/core/attribution', () => billingAttributionMock) - -vi.mock('@/lib/logs/execution/logging-session', () => loggingSessionMock) - -vi.mock('@/lib/logs/execution/trace-spans/trace-spans', () => ({ - buildTraceSpans: vi.fn().mockReturnValue({ traceSpans: [], totalDuration: 0 }), -})) - -import { POST } from '@/app/api/workflows/[id]/log/route' - -const { mockGetWorkspaceBilledAccountUserId } = workspacesUtilsMockFns -const { mockResolveBillingAttribution } = billingAttributionMockFns -const { mockStart, mockSetResolvedSecretTraceRegistry, mockSafeComplete } = loggingSessionMockFns - -const makeRequest = (workflowId: string, body: unknown) => - createMockRequest({ - method: 'POST', - url: `http://localhost/api/workflows/${workflowId}/log`, - body, - }) - -const validResult = { success: true, output: { value: 42 } } - -const storedBillingAttribution = { - actorUserId: 'user-1', - workspaceId: 'workspace-1', - organizationId: 'org-original', - billedAccountUserId: 'owner-original', - billingEntity: { type: 'organization', id: 'org-original' }, - billingPeriod: { - start: '2026-07-01T00:00:00.000Z', - end: '2026-08-01T00:00:00.000Z', - }, - payerSubscription: null, -} - -describe('POST /api/workflows/[id]/log completion attribution', () => { - const OWNER_WORKFLOW_ID = 'wf-owner' - const ATTACKER_WORKFLOW_ID = 'wf-attacker' - const VICTIM_EXECUTION_ID = 'exec-victim-uuid' - - beforeEach(() => { - resetDbChainMock() - authMockFns.mockGetSession.mockResolvedValue({ user: { id: 'user-1' } }) - mockValidateWorkflowAccess.mockResolvedValue({ - workflow: { - id: OWNER_WORKFLOW_ID, - userId: 'owner-1', - workspaceId: 'workspace-1', - }, - auth: { - success: true, - userId: 'user-1', - authType: 'session', - }, - }) - mockGetWorkspaceBilledAccountUserId.mockResolvedValue('owner-1') - mockResolveBillingAttribution.mockResolvedValue({ - actorUserId: 'user-1', - workspaceId: 'workspace-1', - organizationId: 'org-1', - billedAccountUserId: 'owner-1', - billingEntity: { type: 'organization', id: 'org-1' }, - billingPeriod: { - start: '2026-07-01T00:00:00.000Z', - end: '2026-08-01T00:00:00.000Z', - }, - payerSubscription: null, - }) - dbChainMockFns.limit.mockResolvedValue([]) - }) - - it('returns 404 when executionId belongs to a different workflow', async () => { - dbChainMockFns.limit.mockResolvedValueOnce([ - { - workflowId: OWNER_WORKFLOW_ID, - workspaceId: 'workspace-1', - executionData: { billingAttribution: storedBillingAttribution }, - }, - ]) - - const res = await POST( - makeRequest(ATTACKER_WORKFLOW_ID, { - executionId: VICTIM_EXECUTION_ID, - result: validResult, - }), - createRouteContext({ id: ATTACKER_WORKFLOW_ID }) - ) - - expect(res.status).toBe(404) - const body = await res.json() - expect(body.error).toBe('Execution not found') - }) - - it('fails closed when a completion has no persisted execution row', async () => { - dbChainMockFns.limit.mockResolvedValueOnce([]) - - const res = await POST( - makeRequest(OWNER_WORKFLOW_ID, { - executionId: 'missing-execution-id', - result: validResult, - }), - createRouteContext({ id: OWNER_WORKFLOW_ID }) - ) - - expect(res.status).toBe(404) - expect(await res.json()).toMatchObject({ error: 'Execution not found' }) - expect(mockGetWorkspaceBilledAccountUserId).not.toHaveBeenCalled() - expect(mockResolveBillingAttribution).not.toHaveBeenCalled() - expect(mockStart).not.toHaveBeenCalled() - expect(mockSafeComplete).not.toHaveBeenCalled() - }) - - it('rejects a completion from an actor other than the persisted execution actor', async () => { - dbChainMockFns.limit.mockResolvedValueOnce([ - { - workflowId: OWNER_WORKFLOW_ID, - workspaceId: 'workspace-1', - executionData: { - billingAttribution: { - ...storedBillingAttribution, - actorUserId: 'different-user', - }, - }, - }, - ]) - - const res = await POST( - makeRequest(OWNER_WORKFLOW_ID, { - executionId: 'actor-mismatch-execution-id', - result: validResult, - }), - createRouteContext({ id: OWNER_WORKFLOW_ID }) - ) - - expect(res.status).toBe(403) - expect(mockGetWorkspaceBilledAccountUserId).not.toHaveBeenCalled() - expect(mockResolveBillingAttribution).not.toHaveBeenCalled() - expect(mockStart).not.toHaveBeenCalled() - }) - - it('rejects a persisted attribution snapshot bound to another workspace', async () => { - dbChainMockFns.limit.mockResolvedValueOnce([ - { - workflowId: OWNER_WORKFLOW_ID, - workspaceId: 'workspace-1', - executionData: { - billingAttribution: { - ...storedBillingAttribution, - workspaceId: 'workspace-other', - }, - }, - }, - ]) - - const res = await POST( - makeRequest(OWNER_WORKFLOW_ID, { - executionId: 'workspace-mismatch-execution-id', - result: validResult, - }), - createRouteContext({ id: OWNER_WORKFLOW_ID }) - ) - - expect(res.status).toBe(500) - expect(mockGetWorkspaceBilledAccountUserId).not.toHaveBeenCalled() - expect(mockResolveBillingAttribution).not.toHaveBeenCalled() - expect(mockStart).not.toHaveBeenCalled() - }) - - it('uses the persisted attribution after a workflow transfer and payer change', async () => { - mockValidateWorkflowAccess.mockResolvedValueOnce({ - workflow: { - id: OWNER_WORKFLOW_ID, - userId: 'owner-current', - workspaceId: 'workspace-current', - }, - auth: { - success: true, - userId: 'user-1', - authType: 'session', - }, - }) - dbChainMockFns.limit.mockResolvedValueOnce([ - { - workflowId: OWNER_WORKFLOW_ID, - workspaceId: 'workspace-1', - executionData: { billingAttribution: storedBillingAttribution }, - }, - ]) - - const res = await POST( - makeRequest(OWNER_WORKFLOW_ID, { - executionId: 'existing-execution-id', - result: validResult, - }), - createRouteContext({ id: OWNER_WORKFLOW_ID }) - ) - - expect(res.status).toBe(200) - expect(mockGetWorkspaceBilledAccountUserId).not.toHaveBeenCalled() - expect(mockResolveBillingAttribution).not.toHaveBeenCalled() - expect(mockStart).toHaveBeenCalledWith({ - userId: 'user-1', - actorUserId: 'user-1', - billingAttribution: storedBillingAttribution, - workspaceId: 'workspace-1', - variables: {}, - skipLogCreation: true, - }) - }) - - it('restores trusted Secrets provenance before projecting legacy completion traces', async () => { - const trustedExecutionState = { - blockStates: { 'function-1': { output: { result: 'raw-secret-value' } } }, - executedBlocks: ['function-1'], - blockLogs: [], - decisions: { router: {}, condition: {} }, - completedLoops: [], - activeExecutionPath: ['function-1'], - resolvedSecretTraceProvenance: { version: 1, complete: true, entries: [] }, - } - dbChainMockFns.limit.mockResolvedValueOnce([ - { - workflowId: OWNER_WORKFLOW_ID, - workspaceId: 'workspace-1', - executionData: { - billingAttribution: storedBillingAttribution, - executionState: trustedExecutionState, - }, - }, - ]) - - const res = await POST( - makeRequest(OWNER_WORKFLOW_ID, { - executionId: 'trusted-provenance-execution-id', - result: validResult, - }), - createRouteContext({ id: OWNER_WORKFLOW_ID }) - ) - - expect(res.status).toBe(200) - const registry = mockSetResolvedSecretTraceRegistry.mock.calls[0]?.[0] - expect(registry?.isComplete()).toBe(true) - expect(registry?.exportProvenance()).toEqual({ - version: 1, - complete: true, - entries: [], - scope: { userId: 'user-1', workspaceId: 'workspace-1' }, - }) - expect(mockSafeComplete).toHaveBeenCalledWith( - expect.objectContaining({ executionState: trustedExecutionState }) - ) - }) - - it('forces structural-only traces when trusted stored provenance is unavailable', async () => { - dbChainMockFns.limit.mockResolvedValueOnce([ - { - workflowId: OWNER_WORKFLOW_ID, - workspaceId: 'workspace-1', - executionData: { billingAttribution: storedBillingAttribution }, - }, - ]) - - const res = await POST( - makeRequest(OWNER_WORKFLOW_ID, { - executionId: 'legacy-no-provenance-execution-id', - result: validResult, - }), - createRouteContext({ id: OWNER_WORKFLOW_ID }) - ) - - expect(res.status).toBe(200) - const registry = mockSetResolvedSecretTraceRegistry.mock.calls[0]?.[0] - expect(registry?.isComplete()).toBe(false) - }) -}) diff --git a/apps/sim/app/api/workflows/[id]/log/route.ts b/apps/sim/app/api/workflows/[id]/log/route.ts deleted file mode 100644 index 1ce42a892ae..00000000000 --- a/apps/sim/app/api/workflows/[id]/log/route.ts +++ /dev/null @@ -1,212 +0,0 @@ -import { db } from '@sim/db' -import { workflowExecutionLogs } from '@sim/db/schema' -import { createLogger } from '@sim/logger' -import { eq } from 'drizzle-orm' -import type { NextRequest } from 'next/server' -import { workflowLogContract } from '@/lib/api/contracts/workflows' -import { parseRequest } from '@/lib/api/server' -import { - assertBillingAttributionSnapshot, - type BillingAttributionSnapshot, -} from '@/lib/billing/core/attribution' -import { generateRequestId } from '@/lib/core/utils/request' -import { withRouteHandler } from '@/lib/core/utils/with-route-handler' -import { LoggingSession } from '@/lib/logs/execution/logging-session' -import { buildTraceSpans } from '@/lib/logs/execution/trace-spans/trace-spans' -import { materializeExecutionData } from '@/lib/logs/execution/trace-store' -import { validateWorkflowAccess } from '@/app/api/workflows/middleware' -import { createCodedErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' -import type { SerializableExecutionState } from '@/executor/execution/types' -import type { ExecutionResult } from '@/executor/types' -import { ResolvedSecretTraceRegistry } from '@/executor/utils/resolved-secret-trace-registry' - -const logger = createLogger('WorkflowLogAPI') - -export const dynamic = 'force-dynamic' - -export const POST = withRouteHandler( - async (request: NextRequest, context: { params: Promise<{ id: string }> }) => { - const requestId = generateRequestId() - const { id } = await context.params - - try { - const accessValidation = await validateWorkflowAccess(request, id, false) - if (accessValidation.error) { - logger.warn( - `[${requestId}] Workflow access validation failed: ${accessValidation.error.message}` - ) - return createCodedErrorResponse( - accessValidation.error.message, - accessValidation.error.status - ) - } - - const parsed = await parseRequest(workflowLogContract, request, context) - if (!parsed.success) return parsed.response - - const { logs, executionId, result } = parsed.data.body - - if (result) { - if (!executionId) { - logger.warn(`[${requestId}] Missing executionId for result logging`) - return createCodedErrorResponse('executionId is required when logging results', 400) - } - - const [existingLog] = await db - .select({ - workflowId: workflowExecutionLogs.workflowId, - workspaceId: workflowExecutionLogs.workspaceId, - executionData: workflowExecutionLogs.executionData, - }) - .from(workflowExecutionLogs) - .where(eq(workflowExecutionLogs.executionId, executionId)) - .limit(1) - - if (!existingLog) { - logger.warn(`[${requestId}] No persisted start found for execution ${executionId}`) - return createCodedErrorResponse('Execution not found', 404) - } - - if (existingLog.workflowId !== id) { - logger.warn( - `[${requestId}] executionId ${executionId} belongs to workflow ${existingLog.workflowId}, not ${id}` - ) - return createCodedErrorResponse('Execution not found', 404) - } - - const storedBillingAttributionValue = - existingLog.executionData && - typeof existingLog.executionData === 'object' && - 'billingAttribution' in existingLog.executionData && - existingLog.executionData.billingAttribution - ? existingLog.executionData.billingAttribution - : undefined - if (!storedBillingAttributionValue) { - logger.error( - `[${requestId}] Existing execution ${executionId} is missing immutable billing attribution` - ) - return createCodedErrorResponse('Execution billing attribution is unavailable', 500) - } - - let billingAttribution: BillingAttributionSnapshot - try { - billingAttribution = assertBillingAttributionSnapshot(storedBillingAttributionValue) - } catch (error) { - logger.error( - `[${requestId}] Existing execution ${executionId} has invalid immutable billing attribution`, - { error } - ) - return createCodedErrorResponse('Execution billing attribution is unavailable', 500) - } - - if ( - !existingLog.workspaceId || - billingAttribution.workspaceId !== existingLog.workspaceId - ) { - logger.error( - `[${requestId}] Existing execution ${executionId} has inconsistent workspace attribution` - ) - return createCodedErrorResponse('Execution billing attribution is unavailable', 500) - } - - const actorUserId = accessValidation.auth?.userId - if (!actorUserId || actorUserId !== billingAttribution.actorUserId) { - logger.warn( - `[${requestId}] Authenticated actor does not match execution ${executionId} attribution` - ) - return createCodedErrorResponse('Execution is not authorized for this caller', 403) - } - - logger.info(`[${requestId}] Persisting execution result for workflow: ${id}`, { - executionId, - success: result.success, - }) - - const isChatExecution = result.metadata?.source === 'chat' - const triggerType = isChatExecution ? 'chat' : 'manual' - const loggingSession = new LoggingSession(id, executionId, triggerType, requestId) - const resolvedSecretTraceRegistry = new ResolvedSecretTraceRegistry([], { - userId: actorUserId, - workspaceId: existingLog.workspaceId, - }) - const trustedExecutionData = await materializeExecutionData( - existingLog.executionData as Record, - { - workspaceId: existingLog.workspaceId, - workflowId: existingLog.workflowId, - executionId, - } - ) - const trustedExecutionState = - trustedExecutionData.executionState && - typeof trustedExecutionData.executionState === 'object' && - !Array.isArray(trustedExecutionData.executionState) - ? (trustedExecutionData.executionState as SerializableExecutionState) - : undefined - const trustedProvenance = trustedExecutionState?.resolvedSecretTraceProvenance - if (trustedProvenance === undefined) { - resolvedSecretTraceRegistry.markIncomplete('restored-provenance-untrusted') - } else { - await resolvedSecretTraceRegistry.importProvenance(trustedProvenance, { - trusted: true, - origin: 'workflowLogRoute.trustedProvenance', - }) - } - loggingSession.setResolvedSecretTraceRegistry(resolvedSecretTraceRegistry) - - await loggingSession.start({ - userId: actorUserId, - actorUserId, - billingAttribution, - workspaceId: existingLog.workspaceId, - variables: {}, - skipLogCreation: true, - }) - - const resultWithOutput = { - ...result, - output: result.output ?? {}, - } - - const { traceSpans, totalDuration } = buildTraceSpans(resultWithOutput as ExecutionResult) - - if (result.success === false) { - const message = result.error || 'Workflow run failed' - await loggingSession.safeCompleteWithError({ - endedAt: new Date().toISOString(), - totalDurationMs: totalDuration || result.metadata?.duration || 0, - error: { message }, - traceSpans, - executionState: trustedExecutionState, - }) - } else { - await loggingSession.safeComplete({ - endedAt: new Date().toISOString(), - totalDurationMs: totalDuration || result.metadata?.duration || 0, - finalOutput: result.output || {}, - traceSpans, - executionState: trustedExecutionState, - }) - } - - return createSuccessResponse({ - message: 'Run logs persisted successfully', - }) - } - - if (!logs || !Array.isArray(logs) || logs.length === 0) { - logger.warn(`[${requestId}] No logs provided for workflow: ${id}`) - return createCodedErrorResponse('No logs provided', 400) - } - - logger.info(`[${requestId}] Persisting ${logs.length} logs for workflow: ${id}`, { - executionId, - }) - - return createSuccessResponse({ message: 'Logs persisted successfully' }) - } catch (error: any) { - logger.error(`[${requestId}] Error persisting logs for workflow: ${id}`, error) - return createCodedErrorResponse(error.message || 'Failed to persist logs', 500) - } - } -) diff --git a/apps/sim/app/api/workflows/middleware.test.ts b/apps/sim/app/api/workflows/middleware.test.ts index 28eb7114cee..6f8ef626c36 100644 --- a/apps/sim/app/api/workflows/middleware.test.ts +++ b/apps/sim/app/api/workflows/middleware.test.ts @@ -22,7 +22,7 @@ import { WORKSPACE_KEY_SCOPE_DENIED } from '@/lib/api-key/policy-messages' import { validateWorkflowAccess } from '@/app/api/workflows/middleware' function makeRequest() { - return new NextRequest(new URL('https://example.com/api/workflows/wf-1/log')) + return new NextRequest(new URL('https://example.com/api/workflows/wf-1')) } describe('validateWorkflowAccess (requireDeployment=false)', () => { diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.test.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.test.tsx index b174c1ab8b1..f43bd82446f 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.test.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.test.tsx @@ -139,14 +139,9 @@ vi.mock('@/lib/mothership/tools/client/run-tool-execution', () => ({ vi.mock('@/lib/api/contracts/workflows', () => ({ cancelWorkflowExecutionContract: {}, - workflowLogContract: {}, workflowStateSchema: { parse: (value: unknown) => value }, })) -vi.mock('@/lib/logs/execution/trace-spans/trace-spans', () => ({ - buildTraceSpans: () => ({ traceSpans: [], totalDuration: 0 }), -})) - vi.mock('@/lib/tokenization', () => ({ processStreamingBlockLogs: () => 0, })) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts index da0e81193d4..ab83c2f062d 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts @@ -15,13 +15,8 @@ import { toolCallKey, } from '@/components/agent-stream/tool-call-lifecycle' import { requestJson } from '@/lib/api/client/request' -import { - cancelWorkflowExecutionContract, - workflowLogContract, - workflowStateSchema, -} from '@/lib/api/contracts/workflows' +import { cancelWorkflowExecutionContract, workflowStateSchema } from '@/lib/api/contracts/workflows' import type { SecretSafeBlockLog } from '@/lib/logs/execution/display-types' -import { buildTraceSpans } from '@/lib/logs/execution/trace-spans/trace-spans' import { isRunToolActiveForWorkflow, subscribeToRunToolRelease, @@ -605,7 +600,7 @@ export function useWorkflowExecution() { * Handles debug session completion */ const handleDebugSessionComplete = useCallback( - async ( + ( result: ExecutionResult, workflowId: string, persistenceExecution: ConsolePersistenceExecution | undefined @@ -613,9 +608,6 @@ export function useWorkflowExecution() { if (!ownsScopedPersistenceExecution(workflowId, persistenceExecution)) return logger.info('Debug session complete') setExecutionResult(result) - - await persistLogs(workflowId, generateId(), result) - resetOwnedDebugState(workflowId, persistenceExecution) }, [resetOwnedDebugState] @@ -649,7 +641,7 @@ export function useWorkflowExecution() { * Handles debug execution errors */ const handleDebugExecutionError = useCallback( - async ( + ( error: any, operation: string, workflowId: string, @@ -667,62 +659,11 @@ export function useWorkflowExecution() { } setExecutionResult(errorResult) - - await persistLogs(workflowId, generateId(), errorResult) - resetOwnedDebugState(workflowId, persistenceExecution) }, [debugContext, resetOwnedDebugState] ) - const persistLogs = async ( - workflowId: string, - executionId: string, - result: ExecutionResult, - streamContent?: string - ) => { - try { - const { traceSpans, totalDuration } = buildTraceSpans(result) - - const enrichedResult = { - ...result, - traceSpans, - totalDuration, - } - - if (streamContent && result.output && typeof streamContent === 'string') { - enrichedResult.output.content = streamContent - - if (enrichedResult.logs) { - const streamingBlockId = (result.metadata as any)?.streamingBlockId || null - - for (const log of enrichedResult.logs) { - const isStreamingBlock = streamingBlockId && log.blockId === streamingBlockId - if ( - isStreamingBlock && - (log.blockType === 'agent' || log.blockType === 'router') && - log.output - ) - log.output.content = streamContent - } - } - } - - await requestJson(workflowLogContract, { - params: { id: workflowId }, - body: { - executionId, - result: enrichedResult, - }, - }) - - return executionId - } catch (error) { - logger.error('Error persisting logs:', error) - return executionId - } - } - const handleRunWorkflow = useCallback( async (workflowInput?: unknown, enableDebug = false) => { if (!activeWorkflowId) return @@ -1742,12 +1683,12 @@ export function useWorkflowExecution() { logger.info('Debug step execution result:', result) if (isDebugSessionComplete(result)) { - await handleDebugSessionComplete(result, activeWorkflowId, persistenceExecution) + handleDebugSessionComplete(result, activeWorkflowId, persistenceExecution) } else { handleDebugSessionContinuation(result, activeWorkflowId, persistenceExecution) } } catch (error: any) { - await handleDebugExecutionError(error, 'step', activeWorkflowId, persistenceExecution) + handleDebugExecutionError(error, 'step', activeWorkflowId, persistenceExecution) } }, [ executor, @@ -1843,9 +1784,9 @@ export function useWorkflowExecution() { success: currentResult.success, }) - await handleDebugSessionComplete(currentResult, activeWorkflowId, persistenceExecution) + handleDebugSessionComplete(currentResult, activeWorkflowId, persistenceExecution) } catch (error: any) { - await handleDebugExecutionError(error, 'resume', activeWorkflowId, persistenceExecution) + handleDebugExecutionError(error, 'resume', activeWorkflowId, persistenceExecution) } }, [ executor, diff --git a/apps/sim/lib/api/contracts/workflows.ts b/apps/sim/lib/api/contracts/workflows.ts index 26a56fb29bd..e9aa60fca3c 100644 --- a/apps/sim/lib/api/contracts/workflows.ts +++ b/apps/sim/lib/api/contracts/workflows.ts @@ -490,25 +490,6 @@ export const workflowDeploymentVersionParamSchema = z.union([ ]) export type WorkflowDeploymentVersionParam = z.output -export const workflowLogResultSchema = z.object({ - success: z.boolean(), - error: z.string().optional(), - output: z.any(), - metadata: z - .object({ - source: z.string().optional(), - duration: z.number().optional(), - }) - .optional(), -}) - -export const workflowLogBodySchema = z.object({ - logs: z.array(z.any()).optional(), - executionId: requiredFieldSchema('Execution ID is required').optional(), - result: workflowLogResultSchema.optional(), -}) -export type WorkflowLogBody = z.input - export const importWorkflowAsSuperuserBodySchema = z.object({ workflowId: workflowIdSchema, targetWorkspaceId: requiredFieldSchema('Target workspace ID is required'), @@ -547,10 +528,6 @@ const workflowAutoLayoutResponseSchema = z.object({ }), }) -const workflowLogResponseSchema = z.object({ - message: z.string(), -}) - const workflowVariablesResponseSchema = z.object({ success: z.literal(true), }) @@ -898,17 +875,6 @@ export const workflowAutoLayoutContract = defineRouteContract({ }, }) -export const workflowLogContract = defineRouteContract({ - method: 'POST', - path: '/api/workflows/[id]/log', - params: workflowIdParamsSchema, - body: workflowLogBodySchema, - response: { - mode: 'json', - schema: workflowLogResponseSchema, - }, -}) - export const workflowVariablesContract = defineRouteContract({ method: 'POST', path: '/api/workflows/[id]/variables', diff --git a/scripts/check-explicit-any.baseline.json b/scripts/check-explicit-any.baseline.json index ca15838f317..74afcf28358 100644 --- a/scripts/check-explicit-any.baseline.json +++ b/scripts/check-explicit-any.baseline.json @@ -26,7 +26,6 @@ "apps/sim/app/api/webhooks/route.ts": 7, "apps/sim/app/api/workflows/[id]/execute/route.ts": 11, "apps/sim/app/api/workflows/[id]/executions/[executionId]/stream/route.ts": 1, - "apps/sim/app/api/workflows/[id]/log/route.ts": 1, "apps/sim/app/api/workflows/[id]/state/route.ts": 1, "apps/sim/app/api/workflows/middleware.ts": 1, "apps/sim/app/api/workflows/route.ts": 1, @@ -68,7 +67,7 @@ "apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-node-utilities.ts": 1, "apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-scroll-management.ts": 1, "apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-wand.ts": 1, - "apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts": 20, + "apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts": 19, "apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/workflow-execution-store.test.ts": 7, "apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/workflow-execution.test.ts": 6, "apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/workflow-execution.ts": 8, diff --git a/scripts/check-source-conventions.baseline.json b/scripts/check-source-conventions.baseline.json index 84203fe59fe..1e344f1c09e 100644 --- a/scripts/check-source-conventions.baseline.json +++ b/scripts/check-source-conventions.baseline.json @@ -674,7 +674,6 @@ "apps/sim/app/api/webhooks/agentmail/route.ts": 1, "apps/sim/app/api/webhooks/route.ts": 2, "apps/sim/app/api/workflows/[id]/execute/route.ts": 2, - "apps/sim/app/api/workflows/[id]/log/route.ts": 2, "apps/sim/app/api/workflows/[id]/state/route.ts": 2, "apps/sim/app/api/workflows/[id]/variables/route.ts": 2, "apps/sim/app/api/workflows/reorder/route.ts": 2, diff --git a/scripts/check-unused-exports.baseline.json b/scripts/check-unused-exports.baseline.json index ee3fbf375e6..1ed84b49437 100644 --- a/scripts/check-unused-exports.baseline.json +++ b/scripts/check-unused-exports.baseline.json @@ -3891,7 +3891,6 @@ "apps/sim/lib/api/contracts/workflows.ts#UpdateWorkflowBody", "apps/sim/lib/api/contracts/workflows.ts#WorkflowAutoLayoutBody", "apps/sim/lib/api/contracts/workflows.ts#WorkflowDeploymentVersionParam", - "apps/sim/lib/api/contracts/workflows.ts#WorkflowLogBody", "apps/sim/lib/api/contracts/workflows.ts#WorkflowStateWirePayload", "apps/sim/lib/api/contracts/workflows.ts#WorkflowVariablesBody", "apps/sim/lib/api/contracts/workflows.ts#cleanedWorkflowStateSchema", @@ -3913,8 +3912,6 @@ "apps/sim/lib/api/contracts/workflows.ts#workflowExecutionParamsSchema", "apps/sim/lib/api/contracts/workflows.ts#workflowExecutionStreamQuerySchema", "apps/sim/lib/api/contracts/workflows.ts#workflowListItemSchema", - "apps/sim/lib/api/contracts/workflows.ts#workflowLogBodySchema", - "apps/sim/lib/api/contracts/workflows.ts#workflowLogResultSchema", "apps/sim/lib/api/contracts/workflows.ts#workflowScopeSchema", "apps/sim/lib/api/contracts/workflows.ts#workflowStateResponseSchema", "apps/sim/lib/api/contracts/workflows.ts#workflowVariableReadSchema",