diff --git a/.claude/rules/global.md b/.claude/rules/global.md index e749b67b286..b80c3695ce3 100644 --- a/.claude/rules/global.md +++ b/.claude/rules/global.md @@ -9,5 +9,26 @@ Use TSDoc for documentation. No `====` separators. No non-TSDoc comments. ## Styling Never update global styles. Keep all styling local to components. +## ID Generation +Never use `crypto.randomUUID()`, `nanoid`, or the `uuid` package directly. Use the utilities from `@/lib/core/utils/uuid`: + +- `generateId()` — UUID v4, use by default +- `generateShortId(size?)` — short URL-safe ID (default 21 chars), for compact identifiers + +Both use `crypto.getRandomValues()` under the hood and work in all contexts including non-secure (HTTP) browsers. + +```typescript +// ✗ Bad +import { nanoid } from 'nanoid' +import { v4 as uuidv4 } from 'uuid' +const id = crypto.randomUUID() + +// ✓ Good +import { generateId, generateShortId } from '@/lib/core/utils/uuid' +const uuid = generateId() +const shortId = generateShortId() +const tiny = generateShortId(8) +``` + ## Package Manager Use `bun` and `bunx`, not `npm` and `npx`. diff --git a/.cursor/rules/global.mdc b/.cursor/rules/global.mdc index b21c1577b61..af32f057955 100644 --- a/.cursor/rules/global.mdc +++ b/.cursor/rules/global.mdc @@ -16,5 +16,26 @@ Use TSDoc for documentation. No `====` separators. No non-TSDoc comments. ## Styling Never update global styles. Keep all styling local to components. +## ID Generation +Never use `crypto.randomUUID()`, `nanoid`, or the `uuid` package directly. Use the utilities from `@/lib/core/utils/uuid`: + +- `generateId()` — UUID v4, use by default +- `generateShortId(size?)` — short URL-safe ID (default 21 chars), for compact identifiers + +Both use `crypto.getRandomValues()` under the hood and work in all contexts including non-secure (HTTP) browsers. + +```typescript +// ✗ Bad +import { nanoid } from 'nanoid' +import { v4 as uuidv4 } from 'uuid' +const id = crypto.randomUUID() + +// ✓ Good +import { generateId, generateShortId } from '@/lib/core/utils/uuid' +const uuid = generateId() +const shortId = generateShortId() +const tiny = generateShortId(8) +``` + ## Package Manager Use `bun` and `bunx`, not `npm` and `npx`. diff --git a/AGENTS.md b/AGENTS.md index 004252ac6a4..bc54c6f912c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,6 +7,7 @@ You are a professional software engineer. All code must follow best practices: a - **Logging**: Import `createLogger` from `@sim/logger`. Use `logger.info`, `logger.warn`, `logger.error` instead of `console.log` - **Comments**: Use TSDoc for documentation. No `====` separators. No non-TSDoc comments - **Styling**: Never update global styles. Keep all styling local to components +- **ID Generation**: Never use `crypto.randomUUID()`, `nanoid`, or `uuid` package. Use `generateId()` (UUID v4) or `generateShortId()` (compact) from `@/lib/core/utils/uuid` - **Package Manager**: Use `bun` and `bunx`, not `npm` and `npx` ## Architecture diff --git a/CLAUDE.md b/CLAUDE.md index 004252ac6a4..bc54c6f912c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,6 +7,7 @@ You are a professional software engineer. All code must follow best practices: a - **Logging**: Import `createLogger` from `@sim/logger`. Use `logger.info`, `logger.warn`, `logger.error` instead of `console.log` - **Comments**: Use TSDoc for documentation. No `====` separators. No non-TSDoc comments - **Styling**: Never update global styles. Keep all styling local to components +- **ID Generation**: Never use `crypto.randomUUID()`, `nanoid`, or `uuid` package. Use `generateId()` (UUID v4) or `generateShortId()` (compact) from `@/lib/core/utils/uuid` - **Package Manager**: Use `bun` and `bunx`, not `npm` and `npx` ## Architecture diff --git a/apps/sim/app/api/a2a/agents/route.ts b/apps/sim/app/api/a2a/agents/route.ts index dee8bb59979..e1f82e81047 100644 --- a/apps/sim/app/api/a2a/agents/route.ts +++ b/apps/sim/app/api/a2a/agents/route.ts @@ -9,11 +9,11 @@ import { a2aAgent, workflow } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq, isNull, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { generateSkillsFromWorkflow } from '@/lib/a2a/agent-card' import { A2A_DEFAULT_CAPABILITIES } from '@/lib/a2a/constants' import { sanitizeAgentName } from '@/lib/a2a/utils' import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { captureServerEvent } from '@/lib/posthog/server' import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils' import { hasValidStartBlockInState } from '@/lib/workflows/triggers/trigger-utils' @@ -173,7 +173,7 @@ export async function POST(request: NextRequest) { skillTags ) - const agentId = uuidv4() + const agentId = generateId() const agentName = name || sanitizeAgentName(wf.name) const [agent] = await db diff --git a/apps/sim/app/api/a2a/serve/[agentId]/route.ts b/apps/sim/app/api/a2a/serve/[agentId]/route.ts index e944de26ed7..1186ec4909d 100644 --- a/apps/sim/app/api/a2a/serve/[agentId]/route.ts +++ b/apps/sim/app/api/a2a/serve/[agentId]/route.ts @@ -4,7 +4,6 @@ import { a2aAgent, a2aPushNotificationConfig, a2aTask, workflow } from '@sim/db/ import { createLogger } from '@sim/logger' import { and, eq, isNull } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { A2A_DEFAULT_TIMEOUT, A2A_MAX_HISTORY_LENGTH } from '@/lib/a2a/constants' import { notifyTaskStateChange } from '@/lib/a2a/push-notifications' import { @@ -18,6 +17,7 @@ import { acquireLock, getRedisClient, releaseLock } from '@/lib/core/config/redi import { validateUrlWithDNS } from '@/lib/core/security/input-validation.server' import { SSE_HEADERS } from '@/lib/core/utils/sse' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { markExecutionCancelled } from '@/lib/execution/cancellation' import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils' import { getWorkspaceBilledAccountUserId } from '@/lib/workspaces/utils' @@ -400,11 +400,11 @@ async function handleMessageSend( const message = params.message const taskId = message.taskId || generateTaskId() - const contextId = message.contextId || uuidv4() + const contextId = message.contextId || generateId() // Distributed lock to prevent concurrent task processing const lockKey = `a2a:task:${taskId}:lock` - const lockValue = uuidv4() + const lockValue = generateId() const acquired = await acquireLock(lockKey, lockValue, 60) if (!acquired) { @@ -628,12 +628,12 @@ async function handleMessageStream( } const message = params.message - const contextId = message.contextId || uuidv4() + const contextId = message.contextId || generateId() const taskId = message.taskId || generateTaskId() // Distributed lock to prevent concurrent task processing const lockKey = `a2a:task:${taskId}:lock` - const lockValue = uuidv4() + const lockValue = generateId() const acquired = await acquireLock(lockKey, lockValue, 300) if (!acquired) { @@ -1427,7 +1427,7 @@ async function handlePushNotificationSet( .where(eq(a2aPushNotificationConfig.id, existingConfig.id)) } else { await db.insert(a2aPushNotificationConfig).values({ - id: uuidv4(), + id: generateId(), taskId: params.id, url: config.url, token: config.token || null, diff --git a/apps/sim/app/api/a2a/serve/[agentId]/utils.ts b/apps/sim/app/api/a2a/serve/[agentId]/utils.ts index f46013343e2..e3fdd88f5ca 100644 --- a/apps/sim/app/api/a2a/serve/[agentId]/utils.ts +++ b/apps/sim/app/api/a2a/serve/[agentId]/utils.ts @@ -1,7 +1,7 @@ import type { Artifact, Message, PushNotificationConfig, Task, TaskState } from '@a2a-js/sdk' -import { v4 as uuidv4 } from 'uuid' import { generateInternalToken } from '@/lib/auth/internal' import { getInternalApiBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' /** A2A v0.3 JSON-RPC method names */ export const A2A_METHODS = { @@ -85,7 +85,7 @@ export function isJSONRPCRequest(obj: unknown): obj is JSONRPCRequest { } export function generateTaskId(): string { - return uuidv4() + return generateId() } export function createTaskStatus(state: TaskState): { state: TaskState; timestamp: string } { diff --git a/apps/sim/app/api/academy/certificates/route.ts b/apps/sim/app/api/academy/certificates/route.ts index b511e8b32b7..0164e1424e3 100644 --- a/apps/sim/app/api/academy/certificates/route.ts +++ b/apps/sim/app/api/academy/certificates/route.ts @@ -2,7 +2,6 @@ import { db } from '@sim/db' import { academyCertificate, user } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq } from 'drizzle-orm' -import { nanoid } from 'nanoid' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { getCourseById } from '@/lib/academy/content' @@ -10,6 +9,7 @@ import type { CertificateMetadata } from '@/lib/academy/types' import { getSession } from '@/lib/auth' import type { TokenBucketConfig } from '@/lib/core/rate-limiter' import { RateLimiter } from '@/lib/core/rate-limiter' +import { generateShortId } from '@/lib/core/utils/uuid' const logger = createLogger('AcademyCertificatesAPI') @@ -106,7 +106,7 @@ export async function POST(req: NextRequest) { const [certificate] = await db .insert(academyCertificate) .values({ - id: nanoid(), + id: generateShortId(), userId: session.user.id, courseId, status: 'active', @@ -211,5 +211,5 @@ export async function GET(req: NextRequest) { /** Generates a human-readable certificate number, e.g. SIM-2026-A3K9XZ2P */ function generateCertificateNumber(): string { const year = new Date().getFullYear() - return `SIM-${year}-${nanoid(8).toUpperCase()}` + return `SIM-${year}-${generateShortId(8).toUpperCase()}` } diff --git a/apps/sim/app/api/auth/shopify/authorize/route.ts b/apps/sim/app/api/auth/shopify/authorize/route.ts index daa6dfecf06..0607f7c8cfb 100644 --- a/apps/sim/app/api/auth/shopify/authorize/route.ts +++ b/apps/sim/app/api/auth/shopify/authorize/route.ts @@ -3,6 +3,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { getSession } from '@/lib/auth' import { env } from '@/lib/core/config/env' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' const logger = createLogger('ShopifyAuthorize') @@ -161,7 +162,7 @@ export async function GET(request: NextRequest) { const baseUrl = getBaseUrl() const redirectUri = `${baseUrl}/api/auth/oauth2/callback/shopify` - const state = crypto.randomUUID() + const state = generateId() const oauthUrl = `https://${cleanShop}/admin/oauth/authorize?` + diff --git a/apps/sim/app/api/chat/[identifier]/otp/route.ts b/apps/sim/app/api/chat/[identifier]/otp/route.ts index 4d2358fcf5b..2c0ccde08ee 100644 --- a/apps/sim/app/api/chat/[identifier]/otp/route.ts +++ b/apps/sim/app/api/chat/[identifier]/otp/route.ts @@ -1,4 +1,4 @@ -import { randomInt, randomUUID } from 'crypto' +import { randomInt } from 'crypto' import { db } from '@sim/db' import { chat, verification } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -10,6 +10,7 @@ import { getRedisClient } from '@/lib/core/config/redis' import { addCorsHeaders, isEmailAllowed } from '@/lib/core/security/deployment' import { getStorageMethod } from '@/lib/core/storage' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { sendEmail } from '@/lib/messaging/email/mailer' import { setChatAuthCookie } from '@/app/api/chat/utils' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' @@ -61,7 +62,7 @@ async function storeOTP(email: string, chatId: string, otp: string): Promise { await tx.delete(verification).where(eq(verification.identifier, identifier)) await tx.insert(verification).values({ - id: randomUUID(), + id: generateId(), identifier, value, expiresAt, diff --git a/apps/sim/app/api/chat/[identifier]/route.ts b/apps/sim/app/api/chat/[identifier]/route.ts index 024f5ff7e38..3f6e14a41f7 100644 --- a/apps/sim/app/api/chat/[identifier]/route.ts +++ b/apps/sim/app/api/chat/[identifier]/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { chat, workflow } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -7,6 +6,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { addCorsHeaders, validateAuthToken } from '@/lib/core/security/deployment' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { preprocessExecution } from '@/lib/execution/preprocessing' import { LoggingSession } from '@/lib/logs/execution/logging-session' import { ChatFiles } from '@/lib/uploads' @@ -103,7 +103,7 @@ export async function POST( ) } - const executionId = randomUUID() + const executionId = generateId() const loggingSession = new LoggingSession( deployment.workflowId, executionId, @@ -150,7 +150,7 @@ export async function POST( return addCorsHeaders(createErrorResponse('No input provided', 400), request) } - const executionId = randomUUID() + const executionId = generateId() const loggingSession = new LoggingSession(deployment.workflowId, executionId, 'chat', requestId) diff --git a/apps/sim/app/api/copilot/chat/route.ts b/apps/sim/app/api/copilot/chat/route.ts index 647f0058528..bc9f736f52b 100644 --- a/apps/sim/app/api/copilot/chat/route.ts +++ b/apps/sim/app/api/copilot/chat/route.ts @@ -27,6 +27,7 @@ import { createRequestTracker, createUnauthorizedResponse, } from '@/lib/copilot/request-helpers' +import { generateId } from '@/lib/core/utils/uuid' import { captureServerEvent } from '@/lib/posthog/server' import { authorizeWorkflowByWorkspacePermission, @@ -205,7 +206,7 @@ export async function POST(req: NextRequest) { } ) - const userMessageIdToUse = userMessageId || crypto.randomUUID() + const userMessageIdToUse = userMessageId || generateId() const reqLogger = logger.withMetadata({ requestId: tracker.requestId, messageId: userMessageIdToUse, @@ -406,8 +407,8 @@ export async function POST(req: NextRequest) { } if (stream) { - const executionId = crypto.randomUUID() - const runId = crypto.randomUUID() + const executionId = generateId() + const runId = generateId() const sseStream = createSSEStream({ requestPayload, userId: authenticatedUserId, @@ -437,7 +438,7 @@ export async function POST(req: NextRequest) { if (!result.success) return const assistantMessage: Record = { - id: crypto.randomUUID(), + id: generateId(), role: 'assistant' as const, content: result.content, timestamp: new Date().toISOString(), @@ -515,8 +516,8 @@ export async function POST(req: NextRequest) { return new Response(sseStream, { headers: SSE_RESPONSE_HEADERS }) } - const nsExecutionId = crypto.randomUUID() - const nsRunId = crypto.randomUUID() + const nsExecutionId = generateId() + const nsRunId = generateId() if (actualChatId) { await createRunSegment({ @@ -576,7 +577,7 @@ export async function POST(req: NextRequest) { } const assistantMessage = { - id: crypto.randomUUID(), + id: generateId(), role: 'assistant', content: responseData.content, timestamp: new Date().toISOString(), diff --git a/apps/sim/app/api/creators/route.ts b/apps/sim/app/api/creators/route.ts index 843c0aea494..6dedd133af1 100644 --- a/apps/sim/app/api/creators/route.ts +++ b/apps/sim/app/api/creators/route.ts @@ -3,10 +3,10 @@ import { member, templateCreators } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq, or } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { z } from 'zod' import { getSession } from '@/lib/auth' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import type { CreatorProfileDetails } from '@/app/_types/creator-profile' const logger = createLogger('CreatorProfilesAPI') @@ -147,7 +147,7 @@ export async function POST(request: NextRequest) { } // Create the profile - const profileId = uuidv4() + const profileId = generateId() const now = new Date() const details: CreatorProfileDetails = {} diff --git a/apps/sim/app/api/credential-sets/[id]/invite/route.ts b/apps/sim/app/api/credential-sets/[id]/invite/route.ts index 9fcf13d2127..cd5ebb53015 100644 --- a/apps/sim/app/api/credential-sets/[id]/invite/route.ts +++ b/apps/sim/app/api/credential-sets/[id]/invite/route.ts @@ -9,6 +9,7 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { hasCredentialSetsAccess } from '@/lib/billing' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { sendEmail } from '@/lib/messaging/email/mailer' const logger = createLogger('CredentialSetInvite') @@ -105,12 +106,12 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: const body = await req.json() const { email } = createInviteSchema.parse(body) - const token = crypto.randomUUID() + const token = generateId() const expiresAt = new Date() expiresAt.setDate(expiresAt.getDate() + 7) const invitation = { - id: crypto.randomUUID(), + id: generateId(), credentialSetId: id, email: email || null, token, diff --git a/apps/sim/app/api/credential-sets/[id]/members/route.ts b/apps/sim/app/api/credential-sets/[id]/members/route.ts index 2799feb784b..e6ffbaa6262 100644 --- a/apps/sim/app/api/credential-sets/[id]/members/route.ts +++ b/apps/sim/app/api/credential-sets/[id]/members/route.ts @@ -6,6 +6,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { hasCredentialSetsAccess } from '@/lib/billing' +import { generateId } from '@/lib/core/utils/uuid' import { syncAllWebhooksForCredentialSet } from '@/lib/webhooks/utils.server' const logger = createLogger('CredentialSetMembers') @@ -167,7 +168,7 @@ export async function DELETE(req: NextRequest, { params }: { params: Promise<{ i return NextResponse.json({ error: 'Member not found' }, { status: 404 }) } - const requestId = crypto.randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) // Use transaction to ensure member deletion + webhook sync are atomic await db.transaction(async (tx) => { diff --git a/apps/sim/app/api/credential-sets/invite/[token]/route.ts b/apps/sim/app/api/credential-sets/invite/[token]/route.ts index b85c65fed5a..656d39fdde1 100644 --- a/apps/sim/app/api/credential-sets/invite/[token]/route.ts +++ b/apps/sim/app/api/credential-sets/invite/[token]/route.ts @@ -10,6 +10,7 @@ import { and, eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { syncAllWebhooksForCredentialSet } from '@/lib/webhooks/utils.server' const logger = createLogger('CredentialSetInviteToken') @@ -125,11 +126,11 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ tok } const now = new Date() - const requestId = crypto.randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) await db.transaction(async (tx) => { await tx.insert(credentialSetMember).values({ - id: crypto.randomUUID(), + id: generateId(), credentialSetId: invitation.credentialSetId, userId: session.user.id, status: 'active', diff --git a/apps/sim/app/api/credential-sets/memberships/route.ts b/apps/sim/app/api/credential-sets/memberships/route.ts index 045d68ad1ba..aef704f7b9c 100644 --- a/apps/sim/app/api/credential-sets/memberships/route.ts +++ b/apps/sim/app/api/credential-sets/memberships/route.ts @@ -5,6 +5,7 @@ import { and, eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { syncAllWebhooksForCredentialSet } from '@/lib/webhooks/utils.server' const logger = createLogger('CredentialSetMemberships') @@ -60,7 +61,7 @@ export async function DELETE(req: NextRequest) { } try { - const requestId = crypto.randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) // Use transaction to ensure revocation + webhook sync are atomic await db.transaction(async (tx) => { diff --git a/apps/sim/app/api/credential-sets/route.ts b/apps/sim/app/api/credential-sets/route.ts index 1cfa30acf0a..b5166630af9 100644 --- a/apps/sim/app/api/credential-sets/route.ts +++ b/apps/sim/app/api/credential-sets/route.ts @@ -7,6 +7,7 @@ import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { hasCredentialSetsAccess } from '@/lib/billing' +import { generateId } from '@/lib/core/utils/uuid' const logger = createLogger('CredentialSets') @@ -150,7 +151,7 @@ export async function POST(req: Request) { const now = new Date() const newCredentialSet = { - id: crypto.randomUUID(), + id: generateId(), organizationId, name, description: description || null, diff --git a/apps/sim/app/api/credentials/[id]/members/route.ts b/apps/sim/app/api/credentials/[id]/members/route.ts index 11cee7f7177..c89657fe89f 100644 --- a/apps/sim/app/api/credentials/[id]/members/route.ts +++ b/apps/sim/app/api/credentials/[id]/members/route.ts @@ -5,6 +5,7 @@ import { and, eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' const logger = createLogger('CredentialMembersAPI') @@ -133,7 +134,7 @@ export async function POST(request: NextRequest, context: RouteContext) { } await db.insert(credentialMember).values({ - id: crypto.randomUUID(), + id: generateId(), credentialId, userId, role, diff --git a/apps/sim/app/api/credentials/[id]/route.ts b/apps/sim/app/api/credentials/[id]/route.ts index b86031bf2f3..14f2e73142b 100644 --- a/apps/sim/app/api/credentials/[id]/route.ts +++ b/apps/sim/app/api/credentials/[id]/route.ts @@ -6,6 +6,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { getSession } from '@/lib/auth' import { encryptSecret } from '@/lib/core/security/encryption' +import { generateId } from '@/lib/core/utils/uuid' import { getCredentialActorContext } from '@/lib/credentials/access' import { syncPersonalEnvCredentialsForUser, @@ -273,7 +274,7 @@ export async function DELETE( await db .insert(workspaceEnvironment) .values({ - id: workspaceRow?.id || crypto.randomUUID(), + id: workspaceRow?.id || generateId(), workspaceId: access.credential.workspaceId, variables: current, createdAt: workspaceRow?.createdAt || new Date(), diff --git a/apps/sim/app/api/credentials/draft/route.ts b/apps/sim/app/api/credentials/draft/route.ts index ac700f088ed..e00be23b0d0 100644 --- a/apps/sim/app/api/credentials/draft/route.ts +++ b/apps/sim/app/api/credentials/draft/route.ts @@ -5,6 +5,7 @@ import { and, eq, lt } from 'drizzle-orm' import { NextResponse } from 'next/server' import { z } from 'zod' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils' const logger = createLogger('CredentialDraftAPI') @@ -75,7 +76,7 @@ export async function POST(request: Request) { await db .insert(pendingCredentialDraft) .values({ - id: crypto.randomUUID(), + id: generateId(), userId, workspaceId, providerId, diff --git a/apps/sim/app/api/credentials/route.ts b/apps/sim/app/api/credentials/route.ts index 9242a620fa2..7d30b63d7b4 100644 --- a/apps/sim/app/api/credentials/route.ts +++ b/apps/sim/app/api/credentials/route.ts @@ -7,6 +7,7 @@ import { z } from 'zod' import { getSession } from '@/lib/auth' import { encryptSecret } from '@/lib/core/security/encryption' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { getWorkspaceMemberUserIds } from '@/lib/credentials/environment' import { syncWorkspaceOAuthCredentialsForUser } from '@/lib/credentials/oauth' import { getServiceConfigByProviderId } from '@/lib/oauth' @@ -536,7 +537,7 @@ export async function POST(request: NextRequest) { } const now = new Date() - const credentialId = crypto.randomUUID() + const credentialId = generateId() const [workspaceRow] = await db .select({ ownerId: workspace.ownerId }) .from(workspace) @@ -565,7 +566,7 @@ export async function POST(request: NextRequest) { if (workspaceUserIds.length > 0) { for (const memberUserId of workspaceUserIds) { await tx.insert(credentialMember).values({ - id: crypto.randomUUID(), + id: generateId(), credentialId, userId: memberUserId, role: @@ -582,7 +583,7 @@ export async function POST(request: NextRequest) { } } else { await tx.insert(credentialMember).values({ - id: crypto.randomUUID(), + id: generateId(), credentialId, userId: session.user.id, role: 'admin', diff --git a/apps/sim/app/api/environment/route.ts b/apps/sim/app/api/environment/route.ts index 39c91668f61..34195a055dd 100644 --- a/apps/sim/app/api/environment/route.ts +++ b/apps/sim/app/api/environment/route.ts @@ -8,6 +8,7 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { decryptSecret, encryptSecret } from '@/lib/core/security/encryption' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { syncPersonalEnvCredentialsForUser } from '@/lib/credentials/environment' import type { EnvironmentVariable } from '@/stores/settings/environment' @@ -42,7 +43,7 @@ export async function POST(req: NextRequest) { await db .insert(environment) .values({ - id: crypto.randomUUID(), + id: generateId(), userId: session.user.id, variables: encryptedVariables, updatedAt: new Date(), diff --git a/apps/sim/app/api/files/delete/route.test.ts b/apps/sim/app/api/files/delete/route.test.ts index 77582be7df0..85ea1913565 100644 --- a/apps/sim/app/api/files/delete/route.test.ts +++ b/apps/sim/app/api/files/delete/route.test.ts @@ -82,8 +82,12 @@ vi.mock('drizzle-orm', () => ({ sql: vi.fn((strings: unknown, ...values: unknown[]) => ({ type: 'sql', sql: strings, values })), })) -vi.mock('uuid', () => ({ - v4: vi.fn().mockReturnValue('test-uuid'), +vi.mock('@/lib/core/utils/uuid', () => ({ + generateId: vi.fn(() => 'test-uuid'), + generateShortId: vi.fn(() => 'mock-short-id'), + isValidUuid: vi.fn((v: string) => + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v) + ), })) vi.mock('@/lib/auth', () => ({ diff --git a/apps/sim/app/api/files/upload/route.test.ts b/apps/sim/app/api/files/upload/route.test.ts index 5b6a4455d0e..5f3d9064c9f 100644 --- a/apps/sim/app/api/files/upload/route.test.ts +++ b/apps/sim/app/api/files/upload/route.test.ts @@ -91,8 +91,12 @@ vi.mock('drizzle-orm', () => ({ sql: vi.fn((strings: unknown, ...values: unknown[]) => ({ type: 'sql', sql: strings, values })), })) -vi.mock('uuid', () => ({ - v4: vi.fn().mockReturnValue('test-uuid'), +vi.mock('@/lib/core/utils/uuid', () => ({ + generateId: vi.fn(() => 'test-uuid'), + generateShortId: vi.fn(() => 'mock-short-id'), + isValidUuid: vi.fn((v: string) => + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v) + ), })) vi.mock('@/lib/auth', () => ({ diff --git a/apps/sim/app/api/folders/[id]/duplicate/route.ts b/apps/sim/app/api/folders/[id]/duplicate/route.ts index e59cc943d15..be6cea9d429 100644 --- a/apps/sim/app/api/folders/[id]/duplicate/route.ts +++ b/apps/sim/app/api/folders/[id]/duplicate/route.ts @@ -7,6 +7,7 @@ import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { duplicateWorkflow } from '@/lib/workflows/persistence/duplicate' import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' @@ -67,7 +68,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: const targetWorkspaceId = workspaceId || sourceFolder.workspaceId const { newFolderId, folderMapping } = await db.transaction(async (tx) => { - const newFolderId = clientNewId || crypto.randomUUID() + const newFolderId = clientNewId || generateId() const now = new Date() const targetParentId = parentId ?? sourceFolder.parentId @@ -227,7 +228,7 @@ async function duplicateFolderStructure( ) for (const childFolder of childFolders) { - const newChildFolderId = crypto.randomUUID() + const newChildFolderId = generateId() folderMapping.set(childFolder.id, newChildFolderId) await tx.insert(workflowFolder).values({ diff --git a/apps/sim/app/api/folders/route.ts b/apps/sim/app/api/folders/route.ts index a8106463d06..bd33a93caf6 100644 --- a/apps/sim/app/api/folders/route.ts +++ b/apps/sim/app/api/folders/route.ts @@ -6,6 +6,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { captureServerEvent } from '@/lib/posthog/server' import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' @@ -92,7 +93,7 @@ export async function POST(request: NextRequest) { ) } - const id = clientId || crypto.randomUUID() + const id = clientId || generateId() const newFolder = await db.transaction(async (tx) => { let sortOrder: number diff --git a/apps/sim/app/api/form/[identifier]/route.ts b/apps/sim/app/api/form/[identifier]/route.ts index 986a77610d8..f69ab9e1886 100644 --- a/apps/sim/app/api/form/[identifier]/route.ts +++ b/apps/sim/app/api/form/[identifier]/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { form, workflow, workflowBlocks } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -7,6 +6,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { addCorsHeaders, validateAuthToken } from '@/lib/core/security/deployment' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { preprocessExecution } from '@/lib/execution/preprocessing' import { LoggingSession } from '@/lib/logs/execution/logging-session' import { normalizeInputFormatValue } from '@/lib/workflows/input-format' @@ -119,7 +119,7 @@ export async function POST( ) } - const executionId = randomUUID() + const executionId = generateId() const loggingSession = new LoggingSession( deployment.workflowId, executionId, @@ -165,7 +165,7 @@ export async function POST( return addCorsHeaders(createErrorResponse('No form data provided', 400), request) } - const executionId = randomUUID() + const executionId = generateId() const loggingSession = new LoggingSession(deployment.workflowId, executionId, 'form', requestId) const preprocessResult = await preprocessExecution({ diff --git a/apps/sim/app/api/form/route.ts b/apps/sim/app/api/form/route.ts index 3becf417a44..6512ba95808 100644 --- a/apps/sim/app/api/form/route.ts +++ b/apps/sim/app/api/form/route.ts @@ -3,13 +3,13 @@ import { form } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq, isNull } from 'drizzle-orm' import type { NextRequest } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { isDev } from '@/lib/core/config/feature-flags' import { encryptSecret } from '@/lib/core/security/encryption' import { getEmailDomain } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { deployWorkflow } from '@/lib/workflows/persistence/utils' import { checkWorkflowAccessForFormCreation, @@ -158,7 +158,7 @@ export async function POST(request: NextRequest) { encryptedPassword = encrypted } - const id = uuidv4() + const id = generateId() logger.info('Creating form deployment with values:', { workflowId, diff --git a/apps/sim/app/api/knowledge/[id]/connectors/route.ts b/apps/sim/app/api/knowledge/[id]/connectors/route.ts index 92bd8013ee9..b5e2cb86f46 100644 --- a/apps/sim/app/api/knowledge/[id]/connectors/route.ts +++ b/apps/sim/app/api/knowledge/[id]/connectors/route.ts @@ -9,6 +9,7 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' import { hasLiveSyncAccess } from '@/lib/billing/core/subscription' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { dispatchSync } from '@/lib/knowledge/connectors/sync-engine' import { allocateTagSlots } from '@/lib/knowledge/constants' import { createTagDefinition } from '@/lib/knowledge/tags/service' @@ -211,7 +212,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ } const now = new Date() - const connectorId = crypto.randomUUID() + const connectorId = generateId() const nextSyncAt = syncIntervalMinutes > 0 ? new Date(now.getTime() + syncIntervalMinutes * 60 * 1000) : null diff --git a/apps/sim/app/api/knowledge/[id]/documents/[documentId]/chunks/[chunkId]/route.ts b/apps/sim/app/api/knowledge/[id]/documents/[documentId]/chunks/[chunkId]/route.ts index aae50974041..b992ca4b4fe 100644 --- a/apps/sim/app/api/knowledge/[id]/documents/[documentId]/chunks/[chunkId]/route.ts +++ b/apps/sim/app/api/knowledge/[id]/documents/[documentId]/chunks/[chunkId]/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { deleteChunk, updateChunk } from '@/lib/knowledge/chunks/service' import { checkChunkAccess } from '@/app/api/knowledge/utils' @@ -17,7 +17,7 @@ export async function GET( req: NextRequest, { params }: { params: Promise<{ id: string; documentId: string; chunkId: string }> } ) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId, documentId, chunkId } = await params try { @@ -65,7 +65,7 @@ export async function PUT( req: NextRequest, { params }: { params: Promise<{ id: string; documentId: string; chunkId: string }> } ) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId, documentId, chunkId } = await params try { @@ -147,7 +147,7 @@ export async function DELETE( req: NextRequest, { params }: { params: Promise<{ id: string; documentId: string; chunkId: string }> } ) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId, documentId, chunkId } = await params try { diff --git a/apps/sim/app/api/knowledge/[id]/documents/[documentId]/tag-definitions/route.ts b/apps/sim/app/api/knowledge/[id]/documents/[documentId]/tag-definitions/route.ts index e228255cd90..b60638907b4 100644 --- a/apps/sim/app/api/knowledge/[id]/documents/[documentId]/tag-definitions/route.ts +++ b/apps/sim/app/api/knowledge/[id]/documents/[documentId]/tag-definitions/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { SUPPORTED_FIELD_TYPES } from '@/lib/knowledge/constants' import { cleanupUnusedTagDefinitions, @@ -34,7 +34,7 @@ export async function GET( req: NextRequest, { params }: { params: Promise<{ id: string; documentId: string }> } ) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId, documentId } = await params try { @@ -79,7 +79,7 @@ export async function POST( req: NextRequest, { params }: { params: Promise<{ id: string; documentId: string }> } ) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId, documentId } = await params try { @@ -160,7 +160,7 @@ export async function DELETE( req: NextRequest, { params }: { params: Promise<{ id: string; documentId: string }> } ) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId, documentId } = await params const { searchParams } = new URL(req.url) const action = searchParams.get('action') // 'cleanup' or 'all' diff --git a/apps/sim/app/api/knowledge/[id]/documents/route.ts b/apps/sim/app/api/knowledge/[id]/documents/route.ts index 183ac757125..83056e8f486 100644 --- a/apps/sim/app/api/knowledge/[id]/documents/route.ts +++ b/apps/sim/app/api/knowledge/[id]/documents/route.ts @@ -1,10 +1,10 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { bulkDocumentOperation, bulkDocumentOperationByFilter, @@ -66,7 +66,7 @@ const BulkUpdateDocumentsSchema = z }) export async function GET(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId } = await params try { @@ -164,7 +164,7 @@ export async function GET(req: NextRequest, { params }: { params: Promise<{ id: } export async function POST(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId } = await params try { @@ -398,7 +398,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: } export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId } = await params try { diff --git a/apps/sim/app/api/knowledge/[id]/documents/upsert/route.ts b/apps/sim/app/api/knowledge/[id]/documents/upsert/route.ts index 1b44c7a81fe..59be57cd610 100644 --- a/apps/sim/app/api/knowledge/[id]/documents/upsert/route.ts +++ b/apps/sim/app/api/knowledge/[id]/documents/upsert/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { document } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -7,6 +6,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createDocumentRecords, deleteDocument, @@ -35,7 +35,7 @@ const UpsertDocumentSchema = z.object({ }) export async function POST(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId } = await params try { diff --git a/apps/sim/app/api/knowledge/[id]/next-available-slot/route.ts b/apps/sim/app/api/knowledge/[id]/next-available-slot/route.ts index 54318d6f600..a2e5572f8bc 100644 --- a/apps/sim/app/api/knowledge/[id]/next-available-slot/route.ts +++ b/apps/sim/app/api/knowledge/[id]/next-available-slot/route.ts @@ -1,7 +1,7 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { getNextAvailableSlot, getTagDefinitions } from '@/lib/knowledge/tags/service' import { checkKnowledgeBaseAccess } from '@/app/api/knowledge/utils' @@ -9,7 +9,7 @@ const logger = createLogger('NextAvailableSlotAPI') // GET /api/knowledge/[id]/next-available-slot - Get the next available tag slot for a knowledge base and field type export async function GET(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId } = await params const { searchParams } = new URL(req.url) const fieldType = searchParams.get('fieldType') diff --git a/apps/sim/app/api/knowledge/[id]/tag-definitions/[tagId]/route.ts b/apps/sim/app/api/knowledge/[id]/tag-definitions/[tagId]/route.ts index 08b56be3e24..bb6f8d9b46e 100644 --- a/apps/sim/app/api/knowledge/[id]/tag-definitions/[tagId]/route.ts +++ b/apps/sim/app/api/knowledge/[id]/tag-definitions/[tagId]/route.ts @@ -1,7 +1,7 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { deleteTagDefinition } from '@/lib/knowledge/tags/service' import { checkKnowledgeBaseWriteAccess } from '@/app/api/knowledge/utils' @@ -14,7 +14,7 @@ export async function DELETE( req: NextRequest, { params }: { params: Promise<{ id: string; tagId: string }> } ) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId, tagId } = await params try { diff --git a/apps/sim/app/api/knowledge/[id]/tag-definitions/route.ts b/apps/sim/app/api/knowledge/[id]/tag-definitions/route.ts index f4e75b0f13c..57ad6c9fb2f 100644 --- a/apps/sim/app/api/knowledge/[id]/tag-definitions/route.ts +++ b/apps/sim/app/api/knowledge/[id]/tag-definitions/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { AuthType, checkSessionOrInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { SUPPORTED_FIELD_TYPES } from '@/lib/knowledge/constants' import { createTagDefinition, getTagDefinitions } from '@/lib/knowledge/tags/service' import { checkKnowledgeBaseWriteAccess } from '@/app/api/knowledge/utils' @@ -13,7 +13,7 @@ const logger = createLogger('KnowledgeBaseTagDefinitionsAPI') // GET /api/knowledge/[id]/tag-definitions - Get all tag definitions for a knowledge base export async function GET(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId } = await params try { @@ -53,7 +53,7 @@ export async function GET(req: NextRequest, { params }: { params: Promise<{ id: // POST /api/knowledge/[id]/tag-definitions - Create a new tag definition export async function POST(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId } = await params try { diff --git a/apps/sim/app/api/knowledge/[id]/tag-usage/route.ts b/apps/sim/app/api/knowledge/[id]/tag-usage/route.ts index 8b311143ffb..3ba49402445 100644 --- a/apps/sim/app/api/knowledge/[id]/tag-usage/route.ts +++ b/apps/sim/app/api/knowledge/[id]/tag-usage/route.ts @@ -1,7 +1,7 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { getTagUsage } from '@/lib/knowledge/tags/service' import { checkKnowledgeBaseAccess } from '@/app/api/knowledge/utils' @@ -11,7 +11,7 @@ const logger = createLogger('TagUsageAPI') // GET /api/knowledge/[id]/tag-usage - Get usage statistics for all tag definitions export async function GET(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const { id: knowledgeBaseId } = await params try { diff --git a/apps/sim/app/api/mcp/copilot/route.ts b/apps/sim/app/api/mcp/copilot/route.ts index b61dbc39806..f1377d5ad13 100644 --- a/apps/sim/app/api/mcp/copilot/route.ts +++ b/apps/sim/app/api/mcp/copilot/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'node:crypto' import { Server } from '@modelcontextprotocol/sdk/server/index.js' import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js' import { @@ -30,6 +29,7 @@ import { DIRECT_TOOL_DEFS, SUBAGENT_TOOL_DEFS } from '@/lib/copilot/tools/mcp/de import { env } from '@/lib/core/config/env' import { RateLimiter } from '@/lib/core/rate-limiter' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { authorizeWorkflowByWorkspacePermission, resolveWorkflowIdForUser, @@ -638,7 +638,7 @@ async function handleDirectToolCall( ) const toolCall = { - id: randomUUID(), + id: generateId(), name: toolDef.toolId, status: 'pending' as const, params: args as Record, @@ -715,7 +715,7 @@ async function handleBuildToolCall( } } - const chatId = randomUUID() + const chatId = generateId() const requestPayload = { message: requestText, @@ -724,12 +724,12 @@ async function handleBuildToolCall( model: DEFAULT_COPILOT_MODEL, mode: 'agent', commands: ['fast'], - messageId: randomUUID(), + messageId: generateId(), chatId, } - const executionId = crypto.randomUUID() - const runId = crypto.randomUUID() + const executionId = generateId() + const runId = generateId() const messageId = requestPayload.messageId as string await createRunSegment({ diff --git a/apps/sim/app/api/mcp/servers/route.ts b/apps/sim/app/api/mcp/servers/route.ts index 73c6f43fd56..054c7a3a2ca 100644 --- a/apps/sim/app/api/mcp/servers/route.ts +++ b/apps/sim/app/api/mcp/servers/route.ts @@ -4,6 +4,7 @@ import { createLogger } from '@sim/logger' import { and, eq, isNull } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' +import { generateId } from '@/lib/core/utils/uuid' import { McpDnsResolutionError, McpDomainNotAllowedError, @@ -102,7 +103,7 @@ export const POST = withMcpAuth('write')( throw e } - const serverId = body.url ? generateMcpServerId(workspaceId, body.url) : crypto.randomUUID() + const serverId = body.url ? generateMcpServerId(workspaceId, body.url) : generateId() const [existingServer] = await db .select({ id: mcpServers.id, deletedAt: mcpServers.deletedAt }) diff --git a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts index b0887aef1f8..1a4687b44fc 100644 --- a/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts +++ b/apps/sim/app/api/mcp/workflow-servers/[id]/tools/route.ts @@ -4,6 +4,7 @@ import { createLogger } from '@sim/logger' import { and, eq, isNull } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' +import { generateId } from '@/lib/core/utils/uuid' import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' import { mcpPubSub } from '@/lib/mcp/pubsub' import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' @@ -193,7 +194,7 @@ export const POST = withMcpAuth('write')( ? body.parameterSchema : await generateParameterSchemaForWorkflow(body.workflowId) - const toolId = crypto.randomUUID() + const toolId = generateId() const [tool] = await db .insert(workflowMcpTool) .values({ diff --git a/apps/sim/app/api/mcp/workflow-servers/route.ts b/apps/sim/app/api/mcp/workflow-servers/route.ts index 185c551b271..84d431fa423 100644 --- a/apps/sim/app/api/mcp/workflow-servers/route.ts +++ b/apps/sim/app/api/mcp/workflow-servers/route.ts @@ -4,6 +4,7 @@ import { createLogger } from '@sim/logger' import { and, eq, inArray, isNull, sql } from 'drizzle-orm' import type { NextRequest } from 'next/server' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' +import { generateId } from '@/lib/core/utils/uuid' import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware' import { mcpPubSub } from '@/lib/mcp/pubsub' import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils' @@ -112,7 +113,7 @@ export const POST = withMcpAuth('write')( ) } - const serverId = crypto.randomUUID() + const serverId = generateId() const [server] = await db .insert(workflowMcpServer) @@ -168,7 +169,7 @@ export const POST = withMcpAuth('write')( const parameterSchema = await generateParameterSchemaForWorkflow(workflowRecord.id) - const toolId = crypto.randomUUID() + const toolId = generateId() await db.insert(workflowMcpTool).values({ id: toolId, serverId, diff --git a/apps/sim/app/api/memory/route.ts b/apps/sim/app/api/memory/route.ts index c5a4638d7c4..82ffffe6963 100644 --- a/apps/sim/app/api/memory/route.ts +++ b/apps/sim/app/api/memory/route.ts @@ -5,6 +5,7 @@ import { and, eq, isNull, like } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { checkInternalAuth } from '@/lib/auth/hybrid' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils' const logger = createLogger('MemoryAPI') @@ -163,7 +164,7 @@ export async function POST(request: NextRequest) { const initialData = Array.isArray(data) ? data : [data] const now = new Date() - const id = `mem_${crypto.randomUUID().replace(/-/g, '')}` + const id = `mem_${generateId().replace(/-/g, '')}` const { sql } = await import('drizzle-orm') diff --git a/apps/sim/app/api/mothership/chat/route.ts b/apps/sim/app/api/mothership/chat/route.ts index 6accb899a1a..9f567244fb3 100644 --- a/apps/sim/app/api/mothership/chat/route.ts +++ b/apps/sim/app/api/mothership/chat/route.ts @@ -17,6 +17,7 @@ import { processContextsServer, resolveActiveResourceContext } from '@/lib/copil import { createRequestTracker, createUnauthorizedResponse } from '@/lib/copilot/request-helpers' import { taskPubSub } from '@/lib/copilot/task-events' import { generateWorkspaceContext } from '@/lib/copilot/workspace-context' +import { generateId } from '@/lib/core/utils/uuid' import { assertActiveWorkspaceAccess, getUserEntityPermissions, @@ -109,7 +110,7 @@ export async function POST(req: NextRequest) { userTimezone, } = MothershipMessageSchema.parse(body) - const userMessageId = providedMessageId || crypto.randomUUID() + const userMessageId = providedMessageId || generateId() userMessageIdForLogs = userMessageId const reqLogger = logger.withMetadata({ requestId: tracker.requestId, @@ -280,8 +281,8 @@ export async function POST(req: NextRequest) { } } - const executionId = crypto.randomUUID() - const runId = crypto.randomUUID() + const executionId = generateId() + const runId = generateId() const stream = createSSEStream({ requestPayload, userId: authenticatedUserId, @@ -310,7 +311,7 @@ export async function POST(req: NextRequest) { if (!result.success) return const assistantMessage: Record = { - id: crypto.randomUUID(), + id: generateId(), role: 'assistant' as const, content: result.content, timestamp: new Date().toISOString(), diff --git a/apps/sim/app/api/mothership/chat/stop/route.ts b/apps/sim/app/api/mothership/chat/stop/route.ts index 8eb5185ff1e..70dc1df7c87 100644 --- a/apps/sim/app/api/mothership/chat/stop/route.ts +++ b/apps/sim/app/api/mothership/chat/stop/route.ts @@ -7,6 +7,7 @@ import { z } from 'zod' import { getSession } from '@/lib/auth' import { releasePendingChatStream } from '@/lib/copilot/chat-streaming' import { taskPubSub } from '@/lib/copilot/task-events' +import { generateId } from '@/lib/core/utils/uuid' const logger = createLogger('MothershipChatStopAPI') @@ -71,7 +72,7 @@ export async function POST(req: NextRequest) { if (hasContent || hasBlocks) { const assistantMessage: Record = { - id: crypto.randomUUID(), + id: generateId(), role: 'assistant' as const, content, timestamp: new Date().toISOString(), diff --git a/apps/sim/app/api/mothership/execute/route.ts b/apps/sim/app/api/mothership/execute/route.ts index 0570a808e45..619e0135726 100644 --- a/apps/sim/app/api/mothership/execute/route.ts +++ b/apps/sim/app/api/mothership/execute/route.ts @@ -6,6 +6,7 @@ import { createRunSegment } from '@/lib/copilot/async-runs/repository' import { buildIntegrationToolSchemas } from '@/lib/copilot/chat-payload' import { orchestrateCopilotStream } from '@/lib/copilot/orchestrator' import { generateWorkspaceContext } from '@/lib/copilot/workspace-context' +import { generateId } from '@/lib/core/utils/uuid' import { assertActiveWorkspaceAccess, getUserEntityPermissions, @@ -50,8 +51,8 @@ export async function POST(req: NextRequest) { await assertActiveWorkspaceAccess(workspaceId, userId) - const effectiveChatId = chatId || crypto.randomUUID() - messageId = crypto.randomUUID() + const effectiveChatId = chatId || generateId() + messageId = generateId() const reqLogger = logger.withMetadata({ messageId }) const [workspaceContext, integrationTools, userPermission] = await Promise.all([ generateWorkspaceContext(workspaceId, userId), @@ -72,8 +73,8 @@ export async function POST(req: NextRequest) { ...(userPermission ? { userPermission } : {}), } - const executionId = crypto.randomUUID() - const runId = crypto.randomUUID() + const executionId = generateId() + const runId = generateId() await createRunSegment({ id: runId, diff --git a/apps/sim/app/api/notifications/poll/route.ts b/apps/sim/app/api/notifications/poll/route.ts index cbc0246096a..010f9ccffcc 100644 --- a/apps/sim/app/api/notifications/poll/route.ts +++ b/apps/sim/app/api/notifications/poll/route.ts @@ -1,8 +1,8 @@ import { createLogger } from '@sim/logger' -import { nanoid } from 'nanoid' import { type NextRequest, NextResponse } from 'next/server' import { verifyCronAuth } from '@/lib/auth/internal' import { acquireLock, releaseLock } from '@/lib/core/config/redis' +import { generateShortId } from '@/lib/core/utils/uuid' import { pollInactivityAlerts } from '@/lib/notifications/inactivity-polling' const logger = createLogger('InactivityAlertPoll') @@ -13,7 +13,7 @@ const LOCK_KEY = 'inactivity-alert-polling-lock' const LOCK_TTL_SECONDS = 120 export async function GET(request: NextRequest) { - const requestId = nanoid() + const requestId = generateShortId() logger.info(`Inactivity alert polling triggered (${requestId})`) let lockAcquired = false diff --git a/apps/sim/app/api/organizations/[id]/invitations/[invitationId]/route.ts b/apps/sim/app/api/organizations/[id]/invitations/[invitationId]/route.ts index e929765380e..f54e72b2701 100644 --- a/apps/sim/app/api/organizations/[id]/invitations/[invitationId]/route.ts +++ b/apps/sim/app/api/organizations/[id]/invitations/[invitationId]/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { invitation, @@ -27,6 +26,7 @@ import { isOrgPlan, sqlIsPro } from '@/lib/billing/plan-helpers' import { requireStripeClient } from '@/lib/billing/stripe-client' import { ENTITLED_SUBSCRIPTION_STATUSES } from '@/lib/billing/subscriptions/utils' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { syncWorkspaceEnvCredentials } from '@/lib/credentials/environment' import { sendEmail } from '@/lib/messaging/email/mailer' @@ -321,7 +321,7 @@ export async function PUT( if (status === 'accepted') { await tx.insert(member).values({ - id: randomUUID(), + id: generateId(), userId: session.user.id, organizationId, role: orgInvitation.role, @@ -423,7 +423,7 @@ export async function PUT( if (autoAddGroup) { await tx.insert(permissionGroupMember).values({ - id: randomUUID(), + id: generateId(), permissionGroupId: autoAddGroup.id, userId: session.user.id, assignedBy: null, @@ -497,7 +497,7 @@ export async function PUT( } } else { await tx.insert(permissions).values({ - id: randomUUID(), + id: generateId(), entityType: 'workspace', entityId: wsInvitation.workspaceId, userId: session.user.id, diff --git a/apps/sim/app/api/organizations/[id]/invitations/route.ts b/apps/sim/app/api/organizations/[id]/invitations/route.ts index 9b4b690711d..001184d98e7 100644 --- a/apps/sim/app/api/organizations/[id]/invitations/route.ts +++ b/apps/sim/app/api/organizations/[id]/invitations/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { invitation, @@ -24,6 +23,7 @@ import { validateSeatAvailability, } from '@/lib/billing/validation/seat-management' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { sendEmail } from '@/lib/messaging/email/mailer' import { quickValidateEmail } from '@/lib/messaging/email/validation' import { hasWorkspaceAdminAccess } from '@/lib/workspaces/permissions/utils' @@ -293,7 +293,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 7 days const invitationsToCreate = emailsToInvite.map((email: string) => ({ - id: randomUUID(), + id: generateId(), email, inviterId: session.user.id, organizationId, @@ -310,8 +310,8 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ for (const email of emailsToInvite) { const orgInviteForEmail = invitationsToCreate.find((inv) => inv.email === email) for (const wsInvitation of validWorkspaceInvitations) { - const wsInvitationId = randomUUID() - const token = randomUUID() + const wsInvitationId = generateId() + const token = generateId() await db.insert(workspaceInvitation).values({ id: wsInvitationId, diff --git a/apps/sim/app/api/organizations/[id]/members/route.ts b/apps/sim/app/api/organizations/[id]/members/route.ts index 6be21be8a06..3b15d34848e 100644 --- a/apps/sim/app/api/organizations/[id]/members/route.ts +++ b/apps/sim/app/api/organizations/[id]/members/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { invitation, member, organization, user, userStats } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -10,6 +9,7 @@ import { getSession } from '@/lib/auth' import { getUserUsageData } from '@/lib/billing/core/usage' import { validateSeatAvailability } from '@/lib/billing/validation/seat-management' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { sendEmail } from '@/lib/messaging/email/mailer' import { quickValidateEmail } from '@/lib/messaging/email/validation' @@ -231,7 +231,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ } // Create invitation - const invitationId = randomUUID() + const invitationId = generateId() const expiresAt = new Date() expiresAt.setDate(expiresAt.getDate() + 7) // 7 days expiry diff --git a/apps/sim/app/api/permission-groups/[id]/members/bulk/route.ts b/apps/sim/app/api/permission-groups/[id]/members/bulk/route.ts index c6e3faa2d28..f0be70d26b3 100644 --- a/apps/sim/app/api/permission-groups/[id]/members/bulk/route.ts +++ b/apps/sim/app/api/permission-groups/[id]/members/bulk/route.ts @@ -6,6 +6,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { getSession } from '@/lib/auth' import { hasAccessControlAccess } from '@/lib/billing' +import { generateId } from '@/lib/core/utils/uuid' const logger = createLogger('PermissionGroupBulkMembers') @@ -129,7 +130,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: } const newMembers = usersToAdd.map((userId) => ({ - id: crypto.randomUUID(), + id: generateId(), permissionGroupId: id, userId, assignedBy: session.user.id, diff --git a/apps/sim/app/api/permission-groups/[id]/members/route.ts b/apps/sim/app/api/permission-groups/[id]/members/route.ts index ec57c3689c6..5b5fdc65df7 100644 --- a/apps/sim/app/api/permission-groups/[id]/members/route.ts +++ b/apps/sim/app/api/permission-groups/[id]/members/route.ts @@ -7,6 +7,7 @@ import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { hasAccessControlAccess } from '@/lib/billing' +import { generateId } from '@/lib/core/utils/uuid' const logger = createLogger('PermissionGroupMembers') @@ -137,7 +138,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: } const memberData = { - id: crypto.randomUUID(), + id: generateId(), permissionGroupId: id, userId, assignedBy: session.user.id, diff --git a/apps/sim/app/api/permission-groups/route.ts b/apps/sim/app/api/permission-groups/route.ts index a1b6c25476a..b79f01ebc5f 100644 --- a/apps/sim/app/api/permission-groups/route.ts +++ b/apps/sim/app/api/permission-groups/route.ts @@ -7,6 +7,7 @@ import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { hasAccessControlAccess } from '@/lib/billing' +import { generateId } from '@/lib/core/utils/uuid' import { DEFAULT_PERMISSION_GROUP_CONFIG, type PermissionGroupConfig, @@ -181,7 +182,7 @@ export async function POST(req: Request) { const now = new Date() const newGroup = { - id: crypto.randomUUID(), + id: generateId(), organizationId, name, description: description || null, diff --git a/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts b/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts index f4247e7515d..194d9dfcdd0 100644 --- a/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts +++ b/apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { AuthType } from '@/lib/auth/hybrid' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { preprocessExecution } from '@/lib/execution/preprocessing' import { PauseResumeManager } from '@/lib/workflows/executor/human-in-the-loop-manager' import { getWorkspaceBilledAccountUserId } from '@/lib/workspaces/utils' @@ -60,7 +60,7 @@ export async function POST( userId = billedAccountUserId } - const resumeExecutionId = randomUUID() + const resumeExecutionId = generateId() const requestId = generateRequestId() logger.info(`[${requestId}] Preprocessing resume execution`, { diff --git a/apps/sim/app/api/schedules/execute/route.test.ts b/apps/sim/app/api/schedules/execute/route.test.ts index 80c59e537d1..12dd33097e1 100644 --- a/apps/sim/app/api/schedules/execute/route.test.ts +++ b/apps/sim/app/api/schedules/execute/route.test.ts @@ -132,8 +132,12 @@ vi.mock('@sim/db', () => ({ }, })) -vi.mock('uuid', () => ({ - v4: vi.fn().mockReturnValue('schedule-execution-1'), +vi.mock('@/lib/core/utils/uuid', () => ({ + generateId: vi.fn(() => 'schedule-execution-1'), + generateShortId: vi.fn(() => 'mock-short-id'), + isValidUuid: vi.fn((v: string) => + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v) + ), })) import { GET } from './route' diff --git a/apps/sim/app/api/schedules/execute/route.ts b/apps/sim/app/api/schedules/execute/route.ts index 2a4d4f89872..0d1e41a9e1f 100644 --- a/apps/sim/app/api/schedules/execute/route.ts +++ b/apps/sim/app/api/schedules/execute/route.ts @@ -2,11 +2,11 @@ import { db, workflowDeploymentVersion, workflowSchedule } from '@sim/db' import { createLogger } from '@sim/logger' import { and, eq, isNull, lt, lte, ne, not, or, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { verifyCronAuth } from '@/lib/auth/internal' import { getJobQueue, shouldExecuteInline } from '@/lib/core/async-jobs' import { createBullMQJobData, isBullMQEnabled } from '@/lib/core/bullmq' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { enqueueWorkspaceDispatch } from '@/lib/core/workspace-dispatch' import { executeJobInline, @@ -89,7 +89,7 @@ export async function GET(request: NextRequest) { const schedulePromises = dueSchedules.map(async (schedule) => { const queueTime = schedule.lastQueuedAt ?? queuedAt - const executionId = uuidv4() + const executionId = generateId() const correlation = { executionId, requestId, diff --git a/apps/sim/app/api/schedules/route.ts b/apps/sim/app/api/schedules/route.ts index 19fd78bb18f..da291cdcccc 100644 --- a/apps/sim/app/api/schedules/route.ts +++ b/apps/sim/app/api/schedules/route.ts @@ -5,6 +5,7 @@ import { and, eq, isNull, or } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { getSession } from '@/lib/auth' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { captureServerEvent } from '@/lib/posthog/server' import { validateCronExpression } from '@/lib/workflows/schedules/utils' import { authorizeWorkflowByWorkspacePermission } from '@/lib/workflows/utils' @@ -249,7 +250,7 @@ export async function POST(req: NextRequest) { } const now = new Date() - const id = crypto.randomUUID() + const id = generateId() await db.insert(workflowSchedule).values({ id, diff --git a/apps/sim/app/api/superuser/import-workflow/route.ts b/apps/sim/app/api/superuser/import-workflow/route.ts index e9e4f5bbe5e..960723d31ed 100644 --- a/apps/sim/app/api/superuser/import-workflow/route.ts +++ b/apps/sim/app/api/superuser/import-workflow/route.ts @@ -4,6 +4,7 @@ import { createLogger } from '@sim/logger' import { and, eq, isNull } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { verifyEffectiveSuperUser } from '@/lib/templates/permissions' import { parseWorkflowJson } from '@/lib/workflows/operations/import-export' import { @@ -118,7 +119,7 @@ export async function POST(request: NextRequest) { } // Create new workflow record - const newWorkflowId = crypto.randomUUID() + const newWorkflowId = generateId() const now = new Date() const dedupedName = await deduplicateWorkflowName( `[Debug Import] ${sourceWorkflow.name}`, diff --git a/apps/sim/app/api/table/import-csv/route.ts b/apps/sim/app/api/table/import-csv/route.ts index 414ea752a6f..f10074180c2 100644 --- a/apps/sim/app/api/table/import-csv/route.ts +++ b/apps/sim/app/api/table/import-csv/route.ts @@ -2,6 +2,7 @@ import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { batchInsertRows, createTable, @@ -225,7 +226,7 @@ export async function POST(request: NextRequest) { let inserted = 0 for (let i = 0; i < coerced.length; i += MAX_BATCH_SIZE) { const batch = coerced.slice(i, i + MAX_BATCH_SIZE) - const batchRequestId = crypto.randomUUID().slice(0, 8) + const batchRequestId = generateId().slice(0, 8) const result = await batchInsertRows( { tableId: table.id, rows: batch, workspaceId, userId: authResult.userId }, table, diff --git a/apps/sim/app/api/templates/[id]/star/route.ts b/apps/sim/app/api/templates/[id]/star/route.ts index bd8b2db0820..c57ba28eaf9 100644 --- a/apps/sim/app/api/templates/[id]/star/route.ts +++ b/apps/sim/app/api/templates/[id]/star/route.ts @@ -3,9 +3,9 @@ import { templateStars, templates } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { getSession } from '@/lib/auth' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' const logger = createLogger('TemplateStarAPI') @@ -86,7 +86,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ await db.transaction(async (tx) => { // Add the star record await tx.insert(templateStars).values({ - id: uuidv4(), + id: generateId(), userId: session.user.id, templateId: id, starredAt: new Date(), diff --git a/apps/sim/app/api/templates/[id]/use/route.ts b/apps/sim/app/api/templates/[id]/use/route.ts index ecbbb850dd3..a4c797381c1 100644 --- a/apps/sim/app/api/templates/[id]/use/route.ts +++ b/apps/sim/app/api/templates/[id]/use/route.ts @@ -3,10 +3,10 @@ import { templates, workflow, workflowDeploymentVersion } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { eq, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { getSession } from '@/lib/auth' import { generateRequestId } from '@/lib/core/utils/request' import { getInternalApiBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { canAccessTemplate, verifyTemplateOwnership } from '@/lib/templates/permissions' import { type RegenerateStateInput, @@ -93,7 +93,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ const templateData = template[0] // Create a new workflow ID - const newWorkflowId = uuidv4() + const newWorkflowId = generateId() const now = new Date() // Extract variables from the template state and remap to the new workflow @@ -104,7 +104,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ if (!templateVariables || typeof templateVariables !== 'object') return {} const mapped: Record = {} for (const [, variable] of Object.entries(templateVariables)) { - const newVarId = uuidv4() + const newVarId = generateId() mapped[newVarId] = { ...variable, id: newVarId, workflowId: newWorkflowId } } return mapped @@ -178,7 +178,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ // Create a deployment version for the new workflow if (templateData.state) { - const newDeploymentVersionId = uuidv4() + const newDeploymentVersionId = generateId() await tx.insert(workflowDeploymentVersion).values({ id: newDeploymentVersionId, workflowId: newWorkflowId, diff --git a/apps/sim/app/api/templates/route.ts b/apps/sim/app/api/templates/route.ts index e12cc47ad9a..c6424865c82 100644 --- a/apps/sim/app/api/templates/route.ts +++ b/apps/sim/app/api/templates/route.ts @@ -9,11 +9,11 @@ import { import { createLogger } from '@sim/logger' import { and, desc, eq, ilike, or, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { canAccessTemplate, verifyEffectiveSuperUser } from '@/lib/templates/permissions' import { extractRequiredCredentials, @@ -267,7 +267,7 @@ export async function POST(request: NextRequest) { return NextResponse.json({ error: permissionError || 'Access denied' }, { status: 403 }) } - const templateId = uuidv4() + const templateId = generateId() const now = new Date() // Get the active deployment version for the workflow to copy its state diff --git a/apps/sim/app/api/tools/a2a/send-message/route.ts b/apps/sim/app/api/tools/a2a/send-message/route.ts index f389abec948..c15d1921a31 100644 --- a/apps/sim/app/api/tools/a2a/send-message/route.ts +++ b/apps/sim/app/api/tools/a2a/send-message/route.ts @@ -6,6 +6,7 @@ import { createA2AClient, extractTextContent, isTerminalState } from '@/lib/a2a/ import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' import { validateUrlWithDNS } from '@/lib/core/security/input-validation.server' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' export const dynamic = 'force-dynamic' @@ -142,7 +143,7 @@ export async function POST(request: NextRequest) { const message: Message = { kind: 'message', - messageId: crypto.randomUUID(), + messageId: generateId(), role: 'user', parts, ...(validatedData.taskId && { taskId: validatedData.taskId }), diff --git a/apps/sim/app/api/tools/dynamodb/introspect/route.ts b/apps/sim/app/api/tools/dynamodb/introspect/route.ts index 6e55bde87b0..bad2d517ca7 100644 --- a/apps/sim/app/api/tools/dynamodb/introspect/route.ts +++ b/apps/sim/app/api/tools/dynamodb/introspect/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createRawDynamoDBClient, describeTable, listTables } from '@/app/api/tools/dynamodb/utils' const logger = createLogger('DynamoDBIntrospectAPI') @@ -15,7 +15,7 @@ const IntrospectSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mongodb/delete/route.ts b/apps/sim/app/api/tools/mongodb/delete/route.ts index 95dcf328cd0..5325aa57446 100644 --- a/apps/sim/app/api/tools/mongodb/delete/route.ts +++ b/apps/sim/app/api/tools/mongodb/delete/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createMongoDBConnection, sanitizeCollectionName, validateFilter } from '../utils' const logger = createLogger('MongoDBDeleteAPI') @@ -38,7 +38,7 @@ const DeleteSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let client = null const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mongodb/execute/route.ts b/apps/sim/app/api/tools/mongodb/execute/route.ts index 666d4a45069..9ae06a07871 100644 --- a/apps/sim/app/api/tools/mongodb/execute/route.ts +++ b/apps/sim/app/api/tools/mongodb/execute/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createMongoDBConnection, sanitizeCollectionName, validatePipeline } from '../utils' const logger = createLogger('MongoDBExecuteAPI') @@ -30,7 +30,7 @@ const ExecuteSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let client = null const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mongodb/insert/route.ts b/apps/sim/app/api/tools/mongodb/insert/route.ts index f7feafd615a..94957ae5630 100644 --- a/apps/sim/app/api/tools/mongodb/insert/route.ts +++ b/apps/sim/app/api/tools/mongodb/insert/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createMongoDBConnection, sanitizeCollectionName } from '../utils' const logger = createLogger('MongoDBInsertAPI') @@ -35,7 +35,7 @@ const InsertSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let client = null const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mongodb/introspect/route.ts b/apps/sim/app/api/tools/mongodb/introspect/route.ts index 67f281553e3..d6c4b6e5f7f 100644 --- a/apps/sim/app/api/tools/mongodb/introspect/route.ts +++ b/apps/sim/app/api/tools/mongodb/introspect/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createMongoDBConnection, executeIntrospect } from '../utils' const logger = createLogger('MongoDBIntrospectAPI') @@ -18,7 +18,7 @@ const IntrospectSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let client = null const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mongodb/query/route.ts b/apps/sim/app/api/tools/mongodb/query/route.ts index 06533e3a8f4..24829c660b1 100644 --- a/apps/sim/app/api/tools/mongodb/query/route.ts +++ b/apps/sim/app/api/tools/mongodb/query/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createMongoDBConnection, sanitizeCollectionName, validateFilter } from '../utils' const logger = createLogger('MongoDBQueryAPI') @@ -47,7 +47,7 @@ const QuerySchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let client = null const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mongodb/update/route.ts b/apps/sim/app/api/tools/mongodb/update/route.ts index e6c0f867f7e..47022203ee7 100644 --- a/apps/sim/app/api/tools/mongodb/update/route.ts +++ b/apps/sim/app/api/tools/mongodb/update/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createMongoDBConnection, sanitizeCollectionName, validateFilter } from '../utils' const logger = createLogger('MongoDBUpdateAPI') @@ -57,7 +57,7 @@ const UpdateSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let client = null const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mysql/delete/route.ts b/apps/sim/app/api/tools/mysql/delete/route.ts index 7a9e5c81c51..b1871cff38a 100644 --- a/apps/sim/app/api/tools/mysql/delete/route.ts +++ b/apps/sim/app/api/tools/mysql/delete/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { buildDeleteQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils' const logger = createLogger('MySQLDeleteAPI') @@ -19,7 +19,7 @@ const DeleteSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mysql/execute/route.ts b/apps/sim/app/api/tools/mysql/execute/route.ts index 5ab45b85a11..1e8e1685ba3 100644 --- a/apps/sim/app/api/tools/mysql/execute/route.ts +++ b/apps/sim/app/api/tools/mysql/execute/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils' const logger = createLogger('MySQLExecuteAPI') @@ -18,7 +18,7 @@ const ExecuteSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mysql/insert/route.ts b/apps/sim/app/api/tools/mysql/insert/route.ts index 4e9b3a953ca..862a3332c25 100644 --- a/apps/sim/app/api/tools/mysql/insert/route.ts +++ b/apps/sim/app/api/tools/mysql/insert/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { buildInsertQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils' const logger = createLogger('MySQLInsertAPI') @@ -40,7 +40,7 @@ const InsertSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mysql/introspect/route.ts b/apps/sim/app/api/tools/mysql/introspect/route.ts index 686705da404..792b012d126 100644 --- a/apps/sim/app/api/tools/mysql/introspect/route.ts +++ b/apps/sim/app/api/tools/mysql/introspect/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createMySQLConnection, executeIntrospect } from '@/app/api/tools/mysql/utils' const logger = createLogger('MySQLIntrospectAPI') @@ -17,7 +17,7 @@ const IntrospectSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mysql/query/route.ts b/apps/sim/app/api/tools/mysql/query/route.ts index 9237ab45427..5e1105053fc 100644 --- a/apps/sim/app/api/tools/mysql/query/route.ts +++ b/apps/sim/app/api/tools/mysql/query/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils' const logger = createLogger('MySQLQueryAPI') @@ -18,7 +18,7 @@ const QuerySchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/mysql/update/route.ts b/apps/sim/app/api/tools/mysql/update/route.ts index 5204d92a362..0eff371d83c 100644 --- a/apps/sim/app/api/tools/mysql/update/route.ts +++ b/apps/sim/app/api/tools/mysql/update/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { buildUpdateQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils' const logger = createLogger('MySQLUpdateAPI') @@ -38,7 +38,7 @@ const UpdateSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/neo4j/create/route.ts b/apps/sim/app/api/tools/neo4j/create/route.ts index c599b9c13e1..83c1b16c6d4 100644 --- a/apps/sim/app/api/tools/neo4j/create/route.ts +++ b/apps/sim/app/api/tools/neo4j/create/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { convertNeo4jTypesToJSON, createNeo4jDriver, @@ -23,7 +23,7 @@ const CreateSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let driver = null let session = null diff --git a/apps/sim/app/api/tools/neo4j/delete/route.ts b/apps/sim/app/api/tools/neo4j/delete/route.ts index 7a4ed7b315a..5b4c42d7da2 100644 --- a/apps/sim/app/api/tools/neo4j/delete/route.ts +++ b/apps/sim/app/api/tools/neo4j/delete/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createNeo4jDriver, validateCypherQuery } from '@/app/api/tools/neo4j/utils' const logger = createLogger('Neo4jDeleteAPI') @@ -20,7 +20,7 @@ const DeleteSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let driver = null let session = null diff --git a/apps/sim/app/api/tools/neo4j/execute/route.ts b/apps/sim/app/api/tools/neo4j/execute/route.ts index df4dc43b5aa..70eb498b5b2 100644 --- a/apps/sim/app/api/tools/neo4j/execute/route.ts +++ b/apps/sim/app/api/tools/neo4j/execute/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { convertNeo4jTypesToJSON, createNeo4jDriver, @@ -23,7 +23,7 @@ const ExecuteSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let driver = null let session = null diff --git a/apps/sim/app/api/tools/neo4j/introspect/route.ts b/apps/sim/app/api/tools/neo4j/introspect/route.ts index f463e153255..36604473fb6 100644 --- a/apps/sim/app/api/tools/neo4j/introspect/route.ts +++ b/apps/sim/app/api/tools/neo4j/introspect/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createNeo4jDriver } from '@/app/api/tools/neo4j/utils' import type { Neo4jNodeSchema, Neo4jRelationshipSchema } from '@/tools/neo4j/types' @@ -18,7 +18,7 @@ const IntrospectSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let driver = null let session = null diff --git a/apps/sim/app/api/tools/neo4j/merge/route.ts b/apps/sim/app/api/tools/neo4j/merge/route.ts index 839b98f3846..e4865aeabf4 100644 --- a/apps/sim/app/api/tools/neo4j/merge/route.ts +++ b/apps/sim/app/api/tools/neo4j/merge/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { convertNeo4jTypesToJSON, createNeo4jDriver, @@ -23,7 +23,7 @@ const MergeSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let driver = null let session = null diff --git a/apps/sim/app/api/tools/neo4j/query/route.ts b/apps/sim/app/api/tools/neo4j/query/route.ts index 1bb22ab9809..7c6d8983675 100644 --- a/apps/sim/app/api/tools/neo4j/query/route.ts +++ b/apps/sim/app/api/tools/neo4j/query/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { convertNeo4jTypesToJSON, createNeo4jDriver, @@ -23,7 +23,7 @@ const QuerySchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let driver = null let session = null diff --git a/apps/sim/app/api/tools/neo4j/update/route.ts b/apps/sim/app/api/tools/neo4j/update/route.ts index 828d6ef6f5b..5d90e17a568 100644 --- a/apps/sim/app/api/tools/neo4j/update/route.ts +++ b/apps/sim/app/api/tools/neo4j/update/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { convertNeo4jTypesToJSON, createNeo4jDriver, @@ -23,7 +23,7 @@ const UpdateSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) let driver = null let session = null diff --git a/apps/sim/app/api/tools/onedrive/files/route.ts b/apps/sim/app/api/tools/onedrive/files/route.ts index 4f6828c48cb..16baea2e23d 100644 --- a/apps/sim/app/api/tools/onedrive/files/route.ts +++ b/apps/sim/app/api/tools/onedrive/files/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { account } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -6,6 +5,7 @@ import { eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { getSession } from '@/lib/auth' import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation' +import { generateId } from '@/lib/core/utils/uuid' import { refreshAccessTokenIfNeeded, resolveOAuthAccountId } from '@/app/api/auth/oauth/utils' export const dynamic = 'force-dynamic' @@ -18,7 +18,7 @@ import type { MicrosoftGraphDriveItem } from '@/tools/onedrive/types' * Get files (not folders) from Microsoft OneDrive */ export async function GET(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) logger.info(`[${requestId}] OneDrive files request received`) try { diff --git a/apps/sim/app/api/tools/onedrive/folder/route.ts b/apps/sim/app/api/tools/onedrive/folder/route.ts index a4e80b66f9b..2ab90355b7c 100644 --- a/apps/sim/app/api/tools/onedrive/folder/route.ts +++ b/apps/sim/app/api/tools/onedrive/folder/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { account } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -6,6 +5,7 @@ import { eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { getSession } from '@/lib/auth' import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation' +import { generateId } from '@/lib/core/utils/uuid' import { refreshAccessTokenIfNeeded, resolveOAuthAccountId } from '@/app/api/auth/oauth/utils' export const dynamic = 'force-dynamic' @@ -13,7 +13,7 @@ export const dynamic = 'force-dynamic' const logger = createLogger('OneDriveFolderAPI') export async function GET(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const session = await getSession() diff --git a/apps/sim/app/api/tools/onedrive/folders/route.ts b/apps/sim/app/api/tools/onedrive/folders/route.ts index 271c4e69f7e..5cf6981f801 100644 --- a/apps/sim/app/api/tools/onedrive/folders/route.ts +++ b/apps/sim/app/api/tools/onedrive/folders/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { account } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -6,6 +5,7 @@ import { eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { getSession } from '@/lib/auth' import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation' +import { generateId } from '@/lib/core/utils/uuid' import { refreshAccessTokenIfNeeded, resolveOAuthAccountId } from '@/app/api/auth/oauth/utils' export const dynamic = 'force-dynamic' @@ -18,7 +18,7 @@ import type { MicrosoftGraphDriveItem } from '@/tools/onedrive/types' * Get folders from Microsoft OneDrive */ export async function GET(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const session = await getSession() diff --git a/apps/sim/app/api/tools/onepassword/create-item/route.ts b/apps/sim/app/api/tools/onepassword/create-item/route.ts index dae8cbffa57..497e71b1991 100644 --- a/apps/sim/app/api/tools/onepassword/create-item/route.ts +++ b/apps/sim/app/api/tools/onepassword/create-item/route.ts @@ -1,9 +1,9 @@ -import { randomUUID } from 'crypto' import type { ItemCreateParams } from '@1password/sdk' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { connectRequest, createOnePasswordClient, @@ -28,7 +28,7 @@ const CreateItemSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { @@ -55,7 +55,7 @@ export async function POST(request: NextRequest) { const parsedFields = params.fields ? (JSON.parse(params.fields) as Array>).map((f) => ({ - id: f.id || randomUUID().slice(0, 8), + id: f.id || generateId().slice(0, 8), title: f.label || f.title || '', fieldType: toSdkFieldType(f.type || 'STRING'), value: f.value || '', diff --git a/apps/sim/app/api/tools/onepassword/delete-item/route.ts b/apps/sim/app/api/tools/onepassword/delete-item/route.ts index 8909adf88fc..c2be6e8f1eb 100644 --- a/apps/sim/app/api/tools/onepassword/delete-item/route.ts +++ b/apps/sim/app/api/tools/onepassword/delete-item/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { connectRequest, createOnePasswordClient, resolveCredentials } from '../utils' const logger = createLogger('OnePasswordDeleteItemAPI') @@ -17,7 +17,7 @@ const DeleteItemSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/onepassword/get-item/route.ts b/apps/sim/app/api/tools/onepassword/get-item/route.ts index 63ac2906b4b..92065228e81 100644 --- a/apps/sim/app/api/tools/onepassword/get-item/route.ts +++ b/apps/sim/app/api/tools/onepassword/get-item/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { connectRequest, createOnePasswordClient, @@ -22,7 +22,7 @@ const GetItemSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/onepassword/get-vault/route.ts b/apps/sim/app/api/tools/onepassword/get-vault/route.ts index 16343134a5b..09b2b227fe2 100644 --- a/apps/sim/app/api/tools/onepassword/get-vault/route.ts +++ b/apps/sim/app/api/tools/onepassword/get-vault/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { connectRequest, createOnePasswordClient, @@ -21,7 +21,7 @@ const GetVaultSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/onepassword/list-items/route.ts b/apps/sim/app/api/tools/onepassword/list-items/route.ts index 0e9afabdcf9..6f4d4c6eb9d 100644 --- a/apps/sim/app/api/tools/onepassword/list-items/route.ts +++ b/apps/sim/app/api/tools/onepassword/list-items/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { connectRequest, createOnePasswordClient, @@ -22,7 +22,7 @@ const ListItemsSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/onepassword/list-vaults/route.ts b/apps/sim/app/api/tools/onepassword/list-vaults/route.ts index d1b08e781f8..e24d8567abc 100644 --- a/apps/sim/app/api/tools/onepassword/list-vaults/route.ts +++ b/apps/sim/app/api/tools/onepassword/list-vaults/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { connectRequest, createOnePasswordClient, @@ -21,7 +21,7 @@ const ListVaultsSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/onepassword/replace-item/route.ts b/apps/sim/app/api/tools/onepassword/replace-item/route.ts index 3fc198d62b3..48b84918b5f 100644 --- a/apps/sim/app/api/tools/onepassword/replace-item/route.ts +++ b/apps/sim/app/api/tools/onepassword/replace-item/route.ts @@ -1,9 +1,9 @@ -import { randomUUID } from 'crypto' import type { Item } from '@1password/sdk' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { connectRequest, createOnePasswordClient, @@ -26,7 +26,7 @@ const ReplaceItemSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { @@ -57,7 +57,7 @@ export async function POST(request: NextRequest) { vaultId: params.vaultId, fields: itemData.fields ? (itemData.fields as Array>).map((f) => ({ - id: f.id || randomUUID().slice(0, 8), + id: f.id || generateId().slice(0, 8), title: f.label || f.title || '', fieldType: toSdkFieldType(f.type || 'STRING'), value: f.value || '', diff --git a/apps/sim/app/api/tools/onepassword/resolve-secret/route.ts b/apps/sim/app/api/tools/onepassword/resolve-secret/route.ts index 408ac48c548..e327da13d68 100644 --- a/apps/sim/app/api/tools/onepassword/resolve-secret/route.ts +++ b/apps/sim/app/api/tools/onepassword/resolve-secret/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createOnePasswordClient, resolveCredentials } from '../utils' const logger = createLogger('OnePasswordResolveSecretAPI') @@ -16,7 +16,7 @@ const ResolveSecretSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/onepassword/update-item/route.ts b/apps/sim/app/api/tools/onepassword/update-item/route.ts index 543b5f052ee..1bfca62a68b 100644 --- a/apps/sim/app/api/tools/onepassword/update-item/route.ts +++ b/apps/sim/app/api/tools/onepassword/update-item/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { connectRequest, createOnePasswordClient, @@ -23,7 +23,7 @@ const UpdateItemSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/postgresql/delete/route.ts b/apps/sim/app/api/tools/postgresql/delete/route.ts index f26248d6f23..05309cda907 100644 --- a/apps/sim/app/api/tools/postgresql/delete/route.ts +++ b/apps/sim/app/api/tools/postgresql/delete/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createPostgresConnection, executeDelete } from '@/app/api/tools/postgresql/utils' const logger = createLogger('PostgreSQLDeleteAPI') @@ -19,7 +19,7 @@ const DeleteSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/postgresql/execute/route.ts b/apps/sim/app/api/tools/postgresql/execute/route.ts index 35cfe03b6a7..1dba7c11414 100644 --- a/apps/sim/app/api/tools/postgresql/execute/route.ts +++ b/apps/sim/app/api/tools/postgresql/execute/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createPostgresConnection, executeQuery, @@ -22,7 +22,7 @@ const ExecuteSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/postgresql/insert/route.ts b/apps/sim/app/api/tools/postgresql/insert/route.ts index 28e898d8c2d..01073a96577 100644 --- a/apps/sim/app/api/tools/postgresql/insert/route.ts +++ b/apps/sim/app/api/tools/postgresql/insert/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createPostgresConnection, executeInsert } from '@/app/api/tools/postgresql/utils' const logger = createLogger('PostgreSQLInsertAPI') @@ -40,7 +40,7 @@ const InsertSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/postgresql/introspect/route.ts b/apps/sim/app/api/tools/postgresql/introspect/route.ts index 7d504f918c0..cf376bef9de 100644 --- a/apps/sim/app/api/tools/postgresql/introspect/route.ts +++ b/apps/sim/app/api/tools/postgresql/introspect/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createPostgresConnection, executeIntrospect } from '@/app/api/tools/postgresql/utils' const logger = createLogger('PostgreSQLIntrospectAPI') @@ -18,7 +18,7 @@ const IntrospectSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/postgresql/query/route.ts b/apps/sim/app/api/tools/postgresql/query/route.ts index 6e1f8c35933..72e73489a5b 100644 --- a/apps/sim/app/api/tools/postgresql/query/route.ts +++ b/apps/sim/app/api/tools/postgresql/query/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createPostgresConnection, executeQuery } from '@/app/api/tools/postgresql/utils' const logger = createLogger('PostgreSQLQueryAPI') @@ -18,7 +18,7 @@ const QuerySchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/postgresql/update/route.ts b/apps/sim/app/api/tools/postgresql/update/route.ts index a3d5784e2a9..4eb2cc9d4da 100644 --- a/apps/sim/app/api/tools/postgresql/update/route.ts +++ b/apps/sim/app/api/tools/postgresql/update/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createPostgresConnection, executeUpdate } from '@/app/api/tools/postgresql/utils' const logger = createLogger('PostgreSQLUpdateAPI') @@ -38,7 +38,7 @@ const UpdateSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/rds/delete/route.ts b/apps/sim/app/api/tools/rds/delete/route.ts index 8db9e2e1dd1..92b2c9d0b93 100644 --- a/apps/sim/app/api/tools/rds/delete/route.ts +++ b/apps/sim/app/api/tools/rds/delete/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createRdsClient, executeDelete } from '@/app/api/tools/rds/utils' const logger = createLogger('RDSDeleteAPI') @@ -21,7 +21,7 @@ const DeleteSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/rds/execute/route.ts b/apps/sim/app/api/tools/rds/execute/route.ts index 8c88edb0f74..af6304f98da 100644 --- a/apps/sim/app/api/tools/rds/execute/route.ts +++ b/apps/sim/app/api/tools/rds/execute/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createRdsClient, executeStatement } from '@/app/api/tools/rds/utils' const logger = createLogger('RDSExecuteAPI') @@ -18,7 +18,7 @@ const ExecuteSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/rds/insert/route.ts b/apps/sim/app/api/tools/rds/insert/route.ts index 783d80821a0..7fba5fcbb7c 100644 --- a/apps/sim/app/api/tools/rds/insert/route.ts +++ b/apps/sim/app/api/tools/rds/insert/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createRdsClient, executeInsert } from '@/app/api/tools/rds/utils' const logger = createLogger('RDSInsertAPI') @@ -21,7 +21,7 @@ const InsertSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/rds/introspect/route.ts b/apps/sim/app/api/tools/rds/introspect/route.ts index ea96f05b243..2e8aa42a8ef 100644 --- a/apps/sim/app/api/tools/rds/introspect/route.ts +++ b/apps/sim/app/api/tools/rds/introspect/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createRdsClient, executeIntrospect, type RdsEngine } from '@/app/api/tools/rds/utils' const logger = createLogger('RDSIntrospectAPI') @@ -19,7 +19,7 @@ const IntrospectSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/rds/query/route.ts b/apps/sim/app/api/tools/rds/query/route.ts index 6caf743c3ab..21a73291073 100644 --- a/apps/sim/app/api/tools/rds/query/route.ts +++ b/apps/sim/app/api/tools/rds/query/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createRdsClient, executeStatement, validateQuery } from '@/app/api/tools/rds/utils' const logger = createLogger('RDSQueryAPI') @@ -18,7 +18,7 @@ const QuerySchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/rds/update/route.ts b/apps/sim/app/api/tools/rds/update/route.ts index d973d04d8c6..1e2826e4ac7 100644 --- a/apps/sim/app/api/tools/rds/update/route.ts +++ b/apps/sim/app/api/tools/rds/update/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createRdsClient, executeUpdate } from '@/app/api/tools/rds/utils' const logger = createLogger('RDSUpdateAPI') @@ -24,7 +24,7 @@ const UpdateSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/search/route.ts b/apps/sim/app/api/tools/search/route.ts index c3b23303181..b45213115d8 100644 --- a/apps/sim/app/api/tools/search/route.ts +++ b/apps/sim/app/api/tools/search/route.ts @@ -4,6 +4,7 @@ import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' import { SEARCH_TOOL_COST } from '@/lib/billing/constants' import { env } from '@/lib/core/config/env' +import { generateId } from '@/lib/core/utils/uuid' import { executeTool } from '@/tools' const logger = createLogger('search') @@ -16,7 +17,7 @@ export const maxDuration = 60 export const dynamic = 'force-dynamic' export async function POST(request: NextRequest) { - const requestId = crypto.randomUUID() + const requestId = generateId() try { const { searchParams: urlParams } = new URL(request.url) diff --git a/apps/sim/app/api/tools/secrets_manager/create-secret/route.ts b/apps/sim/app/api/tools/secrets_manager/create-secret/route.ts index baa3f39de9b..7cb4a60160b 100644 --- a/apps/sim/app/api/tools/secrets_manager/create-secret/route.ts +++ b/apps/sim/app/api/tools/secrets_manager/create-secret/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSecret, createSecretsManagerClient } from '../utils' const logger = createLogger('SecretsManagerCreateSecretAPI') @@ -17,7 +17,7 @@ const CreateSecretSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/secrets_manager/delete-secret/route.ts b/apps/sim/app/api/tools/secrets_manager/delete-secret/route.ts index 87b76f2391c..21a35e64af7 100644 --- a/apps/sim/app/api/tools/secrets_manager/delete-secret/route.ts +++ b/apps/sim/app/api/tools/secrets_manager/delete-secret/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSecretsManagerClient, deleteSecret } from '../utils' const logger = createLogger('SecretsManagerDeleteSecretAPI') @@ -17,7 +17,7 @@ const DeleteSecretSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/secrets_manager/get-secret/route.ts b/apps/sim/app/api/tools/secrets_manager/get-secret/route.ts index f96c81bd811..22df5b57072 100644 --- a/apps/sim/app/api/tools/secrets_manager/get-secret/route.ts +++ b/apps/sim/app/api/tools/secrets_manager/get-secret/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSecretsManagerClient, getSecretValue } from '../utils' const logger = createLogger('SecretsManagerGetSecretAPI') @@ -17,7 +17,7 @@ const GetSecretSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/secrets_manager/list-secrets/route.ts b/apps/sim/app/api/tools/secrets_manager/list-secrets/route.ts index 00b0e68e591..58617b4864f 100644 --- a/apps/sim/app/api/tools/secrets_manager/list-secrets/route.ts +++ b/apps/sim/app/api/tools/secrets_manager/list-secrets/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSecretsManagerClient, listSecrets } from '../utils' const logger = createLogger('SecretsManagerListSecretsAPI') @@ -16,7 +16,7 @@ const ListSecretsSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/secrets_manager/update-secret/route.ts b/apps/sim/app/api/tools/secrets_manager/update-secret/route.ts index e82f2aedda3..5becf7f0dc3 100644 --- a/apps/sim/app/api/tools/secrets_manager/update-secret/route.ts +++ b/apps/sim/app/api/tools/secrets_manager/update-secret/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSecretsManagerClient, updateSecretValue } from '../utils' const logger = createLogger('SecretsManagerUpdateSecretAPI') @@ -17,7 +17,7 @@ const UpdateSecretSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/sharepoint/site/route.ts b/apps/sim/app/api/tools/sharepoint/site/route.ts index 24941f034de..7afc3954fa2 100644 --- a/apps/sim/app/api/tools/sharepoint/site/route.ts +++ b/apps/sim/app/api/tools/sharepoint/site/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { account } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -6,6 +5,7 @@ import { eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { getSession } from '@/lib/auth' import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation' +import { generateId } from '@/lib/core/utils/uuid' import { refreshAccessTokenIfNeeded, resolveOAuthAccountId } from '@/app/api/auth/oauth/utils' export const dynamic = 'force-dynamic' @@ -13,7 +13,7 @@ export const dynamic = 'force-dynamic' const logger = createLogger('SharePointSiteAPI') export async function GET(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const session = await getSession() diff --git a/apps/sim/app/api/tools/sqs/send/route.ts b/apps/sim/app/api/tools/sqs/send/route.ts index 2c3e643e376..c9078aecc4b 100644 --- a/apps/sim/app/api/tools/sqs/send/route.ts +++ b/apps/sim/app/api/tools/sqs/send/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSqsClient, sendMessage } from '../utils' const logger = createLogger('SQSSendMessageAPI') @@ -20,7 +20,7 @@ const SendMessageSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) const auth = await checkInternalAuth(request) if (!auth.success || !auth.userId) { diff --git a/apps/sim/app/api/tools/ssh/check-command-exists/route.ts b/apps/sim/app/api/tools/ssh/check-command-exists/route.ts index 6290cde47d1..186b4c390aa 100644 --- a/apps/sim/app/api/tools/ssh/check-command-exists/route.ts +++ b/apps/sim/app/api/tools/ssh/check-command-exists/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, escapeShellArg, executeSSHCommand } from '@/app/api/tools/ssh/utils' const logger = createLogger('SSHCheckCommandExistsAPI') @@ -18,7 +18,7 @@ const CheckCommandExistsSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/check-file-exists/route.ts b/apps/sim/app/api/tools/ssh/check-file-exists/route.ts index b5e2546279a..e7e65cc633b 100644 --- a/apps/sim/app/api/tools/ssh/check-file-exists/route.ts +++ b/apps/sim/app/api/tools/ssh/check-file-exists/route.ts @@ -1,9 +1,9 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import type { Client, SFTPWrapper, Stats } from 'ssh2' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, getFileType, @@ -37,7 +37,7 @@ function getSFTP(client: Client): Promise { } export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/create-directory/route.ts b/apps/sim/app/api/tools/ssh/create-directory/route.ts index 3fd058ba689..467c097d4e3 100644 --- a/apps/sim/app/api/tools/ssh/create-directory/route.ts +++ b/apps/sim/app/api/tools/ssh/create-directory/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, escapeShellArg, @@ -25,7 +25,7 @@ const CreateDirectorySchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/delete-file/route.ts b/apps/sim/app/api/tools/ssh/delete-file/route.ts index 14cbc2ae6f3..44506996b07 100644 --- a/apps/sim/app/api/tools/ssh/delete-file/route.ts +++ b/apps/sim/app/api/tools/ssh/delete-file/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, escapeShellArg, @@ -25,7 +25,7 @@ const DeleteFileSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/download-file/route.ts b/apps/sim/app/api/tools/ssh/download-file/route.ts index cd908a1b948..6dbfdf3c5ee 100644 --- a/apps/sim/app/api/tools/ssh/download-file/route.ts +++ b/apps/sim/app/api/tools/ssh/download-file/route.ts @@ -1,10 +1,10 @@ -import { randomUUID } from 'crypto' import path from 'path' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import type { Client, SFTPWrapper } from 'ssh2' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { getFileExtension, getMimeTypeFromExtension } from '@/lib/uploads/utils/file-utils' import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils' @@ -33,7 +33,7 @@ function getSFTP(client: Client): Promise { } export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/execute-command/route.ts b/apps/sim/app/api/tools/ssh/execute-command/route.ts index ba7f7b91c89..66b5dfb1555 100644 --- a/apps/sim/app/api/tools/ssh/execute-command/route.ts +++ b/apps/sim/app/api/tools/ssh/execute-command/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, escapeShellArg, @@ -24,7 +24,7 @@ const ExecuteCommandSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/execute-script/route.ts b/apps/sim/app/api/tools/ssh/execute-script/route.ts index f52dbc00c54..b0158e43fdd 100644 --- a/apps/sim/app/api/tools/ssh/execute-script/route.ts +++ b/apps/sim/app/api/tools/ssh/execute-script/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, escapeShellArg, executeSSHCommand } from '@/app/api/tools/ssh/utils' const logger = createLogger('SSHExecuteScriptAPI') @@ -20,7 +20,7 @@ const ExecuteScriptSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) @@ -55,7 +55,7 @@ export async function POST(request: NextRequest) { const escapedScriptPath = escapeShellArg(scriptPath) const escapedInterpreter = escapeShellArg(params.interpreter) - const heredocDelimiter = `SIMEOF_${randomUUID().replace(/-/g, '')}` + const heredocDelimiter = `SIMEOF_${generateId().replace(/-/g, '')}` let command = `cat > '${escapedScriptPath}' << '${heredocDelimiter}' ${params.script} ${heredocDelimiter} diff --git a/apps/sim/app/api/tools/ssh/get-system-info/route.ts b/apps/sim/app/api/tools/ssh/get-system-info/route.ts index cdb6c0cf25f..65a25e82e21 100644 --- a/apps/sim/app/api/tools/ssh/get-system-info/route.ts +++ b/apps/sim/app/api/tools/ssh/get-system-info/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, executeSSHCommand } from '@/app/api/tools/ssh/utils' const logger = createLogger('SSHGetSystemInfoAPI') @@ -17,7 +17,7 @@ const GetSystemInfoSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/list-directory/route.ts b/apps/sim/app/api/tools/ssh/list-directory/route.ts index cb256f42396..2971ef9202b 100644 --- a/apps/sim/app/api/tools/ssh/list-directory/route.ts +++ b/apps/sim/app/api/tools/ssh/list-directory/route.ts @@ -1,9 +1,9 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import type { Client, FileEntry, SFTPWrapper } from 'ssh2' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, getFileType, @@ -58,7 +58,7 @@ async function listDir(sftp: SFTPWrapper, dirPath: string): Promise } export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/move-rename/route.ts b/apps/sim/app/api/tools/ssh/move-rename/route.ts index ba4a9a2956b..98285041707 100644 --- a/apps/sim/app/api/tools/ssh/move-rename/route.ts +++ b/apps/sim/app/api/tools/ssh/move-rename/route.ts @@ -1,8 +1,8 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, escapeShellArg, @@ -25,7 +25,7 @@ const MoveRenameSchema = z.object({ }) export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/read-file-content/route.ts b/apps/sim/app/api/tools/ssh/read-file-content/route.ts index 237c8336ca2..7493a6cb10c 100644 --- a/apps/sim/app/api/tools/ssh/read-file-content/route.ts +++ b/apps/sim/app/api/tools/ssh/read-file-content/route.ts @@ -1,9 +1,9 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import type { Client, SFTPWrapper } from 'ssh2' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils' const logger = createLogger('SSHReadFileContentAPI') @@ -33,7 +33,7 @@ function getSFTP(client: Client): Promise { } export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/upload-file/route.ts b/apps/sim/app/api/tools/ssh/upload-file/route.ts index 2ce4804303c..2020271465b 100644 --- a/apps/sim/app/api/tools/ssh/upload-file/route.ts +++ b/apps/sim/app/api/tools/ssh/upload-file/route.ts @@ -1,9 +1,9 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import type { Client, SFTPWrapper } from 'ssh2' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils' const logger = createLogger('SSHUploadFileAPI') @@ -35,7 +35,7 @@ function getSFTP(client: Client): Promise { } export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/ssh/write-file-content/route.ts b/apps/sim/app/api/tools/ssh/write-file-content/route.ts index ede5252004c..77a180b9dae 100644 --- a/apps/sim/app/api/tools/ssh/write-file-content/route.ts +++ b/apps/sim/app/api/tools/ssh/write-file-content/route.ts @@ -1,9 +1,9 @@ -import { randomUUID } from 'crypto' import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import type { Client, SFTPWrapper } from 'ssh2' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { generateId } from '@/lib/core/utils/uuid' import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils' const logger = createLogger('SSHWriteFileContentAPI') @@ -34,7 +34,7 @@ function getSFTP(client: Client): Promise { } export async function POST(request: NextRequest) { - const requestId = randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const auth = await checkInternalAuth(request) diff --git a/apps/sim/app/api/tools/stt/route.ts b/apps/sim/app/api/tools/stt/route.ts index aaacadd5a69..e45bb273f06 100644 --- a/apps/sim/app/api/tools/stt/route.ts +++ b/apps/sim/app/api/tools/stt/route.ts @@ -7,6 +7,7 @@ import { secureFetchWithPinnedIP, validateUrlWithDNS, } from '@/lib/core/security/input-validation.server' +import { generateId } from '@/lib/core/utils/uuid' import { getMimeTypeFromExtension, isInternalFileUrl } from '@/lib/uploads/utils/file-utils' import { downloadFileFromStorage, @@ -45,7 +46,7 @@ interface SttRequestBody { } export async function POST(request: NextRequest) { - const requestId = crypto.randomUUID() + const requestId = generateId() logger.info(`[${requestId}] STT transcription request started`) try { diff --git a/apps/sim/app/api/tools/tts/unified/route.ts b/apps/sim/app/api/tools/tts/unified/route.ts index c8b6b89c930..5b6ba35198a 100644 --- a/apps/sim/app/api/tools/tts/unified/route.ts +++ b/apps/sim/app/api/tools/tts/unified/route.ts @@ -4,6 +4,7 @@ import { NextResponse } from 'next/server' import { checkInternalAuth } from '@/lib/auth/hybrid' import { validateAlphanumericId } from '@/lib/core/security/input-validation' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { StorageService } from '@/lib/uploads' import type { AzureTtsParams, @@ -83,7 +84,7 @@ interface TtsUnifiedRequestBody { } export async function POST(request: NextRequest) { - const requestId = crypto.randomUUID() + const requestId = generateId() logger.info(`[${requestId}] TTS unified request started`) try { diff --git a/apps/sim/app/api/tools/video/route.ts b/apps/sim/app/api/tools/video/route.ts index 258928289eb..3a5a5b817f7 100644 --- a/apps/sim/app/api/tools/video/route.ts +++ b/apps/sim/app/api/tools/video/route.ts @@ -2,6 +2,7 @@ import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { checkInternalAuth } from '@/lib/auth/hybrid' import { getMaxExecutionTimeout } from '@/lib/core/execution-limits' +import { generateId } from '@/lib/core/utils/uuid' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import type { UserFile } from '@/executor/types' import type { VideoRequestBody } from '@/tools/video/types' @@ -12,7 +13,7 @@ export const dynamic = 'force-dynamic' export const maxDuration = 600 // 10 minutes for video generation export async function POST(request: NextRequest) { - const requestId = crypto.randomUUID() + const requestId = generateId() logger.info(`[${requestId}] Video generation request started`) try { diff --git a/apps/sim/app/api/users/me/api-keys/route.ts b/apps/sim/app/api/users/me/api-keys/route.ts index 25a63120875..173bc01be7a 100644 --- a/apps/sim/app/api/users/me/api-keys/route.ts +++ b/apps/sim/app/api/users/me/api-keys/route.ts @@ -2,11 +2,11 @@ import { db } from '@sim/db' import { apiKey } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq } from 'drizzle-orm' -import { nanoid } from 'nanoid' import { type NextRequest, NextResponse } from 'next/server' import { createApiKey, getApiKeyDisplayFormat } from '@/lib/api-key/auth' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' +import { generateShortId } from '@/lib/core/utils/uuid' const logger = createLogger('ApiKeysAPI') @@ -96,7 +96,7 @@ export async function POST(request: NextRequest) { const [newKey] = await db .insert(apiKey) .values({ - id: nanoid(), + id: generateShortId(), userId, workspaceId: null, name, diff --git a/apps/sim/app/api/users/me/settings/route.ts b/apps/sim/app/api/users/me/settings/route.ts index b1277754c32..84876b67071 100644 --- a/apps/sim/app/api/users/me/settings/route.ts +++ b/apps/sim/app/api/users/me/settings/route.ts @@ -2,11 +2,11 @@ import { db } from '@sim/db' import { settings } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { eq } from 'drizzle-orm' -import { nanoid } from 'nanoid' import { NextResponse } from 'next/server' import { z } from 'zod' import { getSession } from '@/lib/auth' import { generateRequestId } from '@/lib/core/utils/request' +import { generateShortId } from '@/lib/core/utils/uuid' const logger = createLogger('UserSettingsAPI') @@ -108,7 +108,7 @@ export async function PATCH(request: Request) { await db .insert(settings) .values({ - id: nanoid(), + id: generateShortId(), userId, ...validatedData, updatedAt: new Date(), diff --git a/apps/sim/app/api/v1/admin/credits/route.ts b/apps/sim/app/api/v1/admin/credits/route.ts index 93276f8afc3..feaec3b95d9 100644 --- a/apps/sim/app/api/v1/admin/credits/route.ts +++ b/apps/sim/app/api/v1/admin/credits/route.ts @@ -27,7 +27,6 @@ import { db } from '@sim/db' import { organization, subscription, user, userStats } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq, inArray } from 'drizzle-orm' -import { nanoid } from 'nanoid' import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription' import { addCredits } from '@/lib/billing/credits/balance' import { setUsageLimitForCredits } from '@/lib/billing/credits/purchase' @@ -36,6 +35,7 @@ import { ENTITLED_SUBSCRIPTION_STATUSES, getEffectiveSeats, } from '@/lib/billing/subscriptions/utils' +import { generateShortId } from '@/lib/core/utils/uuid' import { withAdminAuth } from '@/app/api/v1/admin/middleware' import { badRequestResponse, @@ -148,7 +148,7 @@ export const POST = withAdminAuth(async (request) => { if (!existingStats) { await db.insert(userStats).values({ - id: nanoid(), + id: generateShortId(), userId: entityId, }) } diff --git a/apps/sim/app/api/v1/admin/organizations/route.ts b/apps/sim/app/api/v1/admin/organizations/route.ts index 5cac5aba078..f4da57737e6 100644 --- a/apps/sim/app/api/v1/admin/organizations/route.ts +++ b/apps/sim/app/api/v1/admin/organizations/route.ts @@ -21,11 +21,11 @@ * Response: AdminSingleResponse */ -import { randomUUID } from 'crypto' import { db } from '@sim/db' import { member, organization, user } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { count, eq } from 'drizzle-orm' +import { generateId } from '@/lib/core/utils/uuid' import { withAdminAuth } from '@/app/api/v1/admin/middleware' import { badRequestResponse, @@ -108,8 +108,8 @@ export const POST = withAdminAuth(async (request) => { .replace(/[^a-z0-9]+/g, '-') .replace(/^-|-$/g, '') - const organizationId = randomUUID() - const memberId = randomUUID() + const organizationId = generateId() + const memberId = generateId() const now = new Date() await db.transaction(async (tx) => { diff --git a/apps/sim/app/api/v1/admin/users/[id]/billing/route.ts b/apps/sim/app/api/v1/admin/users/[id]/billing/route.ts index 5e863c82ab9..1639db0baea 100644 --- a/apps/sim/app/api/v1/admin/users/[id]/billing/route.ts +++ b/apps/sim/app/api/v1/admin/users/[id]/billing/route.ts @@ -22,9 +22,9 @@ import { db } from '@sim/db' import { member, organization, subscription, user, userStats } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { eq, or } from 'drizzle-orm' -import { nanoid } from 'nanoid' import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription' import { isOrgPlan } from '@/lib/billing/plan-helpers' +import { generateShortId } from '@/lib/core/utils/uuid' import { withAdminAuthParams } from '@/app/api/v1/admin/middleware' import { badRequestResponse, @@ -232,7 +232,7 @@ export const PATCH = withAdminAuthParams(async (request, context) = await db.update(userStats).set(updateData).where(eq(userStats.userId, userId)) } else { await db.insert(userStats).values({ - id: nanoid(), + id: generateShortId(), userId, ...updateData, }) diff --git a/apps/sim/app/api/v1/admin/workflows/import/route.ts b/apps/sim/app/api/v1/admin/workflows/import/route.ts index d5907ce3995..1d384f0cf6b 100644 --- a/apps/sim/app/api/v1/admin/workflows/import/route.ts +++ b/apps/sim/app/api/v1/admin/workflows/import/route.ts @@ -19,6 +19,7 @@ import { workflow, workspace } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq, isNull } from 'drizzle-orm' import { NextResponse } from 'next/server' +import { generateId } from '@/lib/core/utils/uuid' import { parseWorkflowJson } from '@/lib/workflows/operations/import-export' import { saveWorkflowToNormalizedTables } from '@/lib/workflows/persistence/utils' import { deduplicateWorkflowName } from '@/lib/workflows/utils' @@ -92,7 +93,7 @@ export const POST = withAdminAuth(async (request) => { description: workflowDescription, } = extractWorkflowMetadata(parsedWorkflow, overrideName) - const workflowId = crypto.randomUUID() + const workflowId = generateId() const now = new Date() const dedupedName = await deduplicateWorkflowName(workflowName, workspaceId, folderId || null) @@ -122,7 +123,7 @@ export const POST = withAdminAuth(async (request) => { if (workflowData.variables && Array.isArray(workflowData.variables)) { const variablesRecord: Record = {} workflowData.variables.forEach((v) => { - const varId = v.id || crypto.randomUUID() + const varId = v.id || generateId() variablesRecord[varId] = { id: varId, name: v.name, diff --git a/apps/sim/app/api/v1/admin/workspaces/[id]/import/route.ts b/apps/sim/app/api/v1/admin/workspaces/[id]/import/route.ts index 15830d2e6dd..adcc927785d 100644 --- a/apps/sim/app/api/v1/admin/workspaces/[id]/import/route.ts +++ b/apps/sim/app/api/v1/admin/workspaces/[id]/import/route.ts @@ -28,6 +28,7 @@ import { workflow, workflowFolder } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { eq } from 'drizzle-orm' import { NextResponse } from 'next/server' +import { generateId } from '@/lib/core/utils/uuid' import { extractWorkflowName, extractWorkflowsFromZip, @@ -126,7 +127,7 @@ export const POST = withAdminAuthParams(async (request, context) => let rootFolderId: string | undefined if (rootFolderName && createFolders) { - rootFolderId = crypto.randomUUID() + rootFolderId = generateId() await db.insert(workflowFolder).values({ id: rootFolderId, name: rootFolderName, @@ -203,7 +204,7 @@ async function importSingleWorkflow( const fullPath = rootFolderId ? `root/${pathSegment}` : pathSegment if (!folderMap.has(fullPath)) { - const folderId = crypto.randomUUID() + const folderId = generateId() await db.insert(workflowFolder).values({ id: folderId, name: wf.folderPath[i], @@ -234,7 +235,7 @@ async function importSingleWorkflow( } })() const { color: workflowColor } = extractWorkflowMetadata(parsedContent) - const workflowId = crypto.randomUUID() + const workflowId = generateId() const now = new Date() const dedupedName = await deduplicateWorkflowName(workflowName, workspaceId, targetFolderId) @@ -269,7 +270,7 @@ async function importSingleWorkflow( if (workflowData.variables && Array.isArray(workflowData.variables)) { const variablesRecord: Record = {} workflowData.variables.forEach((v) => { - const varId = v.id || crypto.randomUUID() + const varId = v.id || generateId() variablesRecord[varId] = { id: varId, name: v.name, diff --git a/apps/sim/app/api/v1/admin/workspaces/[id]/members/route.ts b/apps/sim/app/api/v1/admin/workspaces/[id]/members/route.ts index 78b70b7d52e..d9a399268fd 100644 --- a/apps/sim/app/api/v1/admin/workspaces/[id]/members/route.ts +++ b/apps/sim/app/api/v1/admin/workspaces/[id]/members/route.ts @@ -30,11 +30,11 @@ * Response: AdminSingleResponse<{ removed: true }> */ -import crypto from 'crypto' import { db } from '@sim/db' import { permissions, user, workspaceEnvironment } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, count, eq } from 'drizzle-orm' +import { generateId } from '@/lib/core/utils/uuid' import { syncWorkspaceEnvCredentials } from '@/lib/credentials/environment' import { getWorkspaceById } from '@/lib/workspaces/permissions/utils' import { withAdminAuthParams } from '@/app/api/v1/admin/middleware' @@ -209,7 +209,7 @@ export const POST = withAdminAuthParams(async (request, context) => } const now = new Date() - const permissionId = crypto.randomUUID() + const permissionId = generateId() await db.insert(permissions).values({ id: permissionId, diff --git a/apps/sim/app/api/v1/audit-logs/[id]/route.ts b/apps/sim/app/api/v1/audit-logs/[id]/route.ts index 3cf6351d2bd..948a034afc0 100644 --- a/apps/sim/app/api/v1/audit-logs/[id]/route.ts +++ b/apps/sim/app/api/v1/audit-logs/[id]/route.ts @@ -15,6 +15,7 @@ import { auditLog, workspace } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq, inArray, or } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' +import { generateId } from '@/lib/core/utils/uuid' import { validateEnterpriseAuditAccess } from '@/app/api/v1/audit-logs/auth' import { formatAuditLogEntry } from '@/app/api/v1/audit-logs/format' import { createApiResponse, getUserLimits } from '@/app/api/v1/logs/meta' @@ -25,7 +26,7 @@ const logger = createLogger('V1AuditLogDetailAPI') export const revalidate = 0 export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = crypto.randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const rateLimit = await checkRateLimit(request, 'audit-logs') diff --git a/apps/sim/app/api/v1/audit-logs/route.ts b/apps/sim/app/api/v1/audit-logs/route.ts index 825cf376203..5a090391da4 100644 --- a/apps/sim/app/api/v1/audit-logs/route.ts +++ b/apps/sim/app/api/v1/audit-logs/route.ts @@ -25,6 +25,7 @@ import { createLogger } from '@sim/logger' import { and, desc, eq, gte, inArray, lt, lte, or, type SQL } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' +import { generateId } from '@/lib/core/utils/uuid' import { validateEnterpriseAuditAccess } from '@/app/api/v1/audit-logs/auth' import { formatAuditLogEntry } from '@/app/api/v1/audit-logs/format' import { createApiResponse, getUserLimits } from '@/app/api/v1/logs/meta' @@ -74,7 +75,7 @@ function decodeCursor(cursor: string): CursorData | null { } export async function GET(request: NextRequest) { - const requestId = crypto.randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const rateLimit = await checkRateLimit(request, 'audit-logs') diff --git a/apps/sim/app/api/v1/copilot/chat/route.ts b/apps/sim/app/api/v1/copilot/chat/route.ts index 09a5a70f3e1..52be435d681 100644 --- a/apps/sim/app/api/v1/copilot/chat/route.ts +++ b/apps/sim/app/api/v1/copilot/chat/route.ts @@ -4,6 +4,7 @@ import { z } from 'zod' import { createRunSegment } from '@/lib/copilot/async-runs/repository' import { COPILOT_REQUEST_MODES } from '@/lib/copilot/models' import { orchestrateCopilotStream } from '@/lib/copilot/orchestrator' +import { generateId } from '@/lib/core/utils/uuid' import { getWorkflowById, resolveWorkflowIdForUser } from '@/lib/workflows/utils' import { authenticateV1Request } from '@/app/api/v1/auth' @@ -80,9 +81,9 @@ export async function POST(req: NextRequest) { const transportMode = effectiveMode === 'build' ? 'agent' : effectiveMode // Always generate a chatId - required for artifacts system to work with subagents - const chatId = parsed.chatId || crypto.randomUUID() + const chatId = parsed.chatId || generateId() - messageId = crypto.randomUUID() + messageId = generateId() const reqLogger = logger.withMetadata({ messageId }) reqLogger.info('Received headless copilot chat start request', { workflowId: resolved.workflowId, @@ -102,8 +103,8 @@ export async function POST(req: NextRequest) { chatId, } - const executionId = crypto.randomUUID() - const runId = crypto.randomUUID() + const executionId = generateId() + const runId = generateId() await createRunSegment({ id: runId, diff --git a/apps/sim/app/api/v1/logs/[id]/route.ts b/apps/sim/app/api/v1/logs/[id]/route.ts index 6e5176c5760..e9b33de99ff 100644 --- a/apps/sim/app/api/v1/logs/[id]/route.ts +++ b/apps/sim/app/api/v1/logs/[id]/route.ts @@ -3,6 +3,7 @@ import { permissions, workflow, workflowExecutionLogs } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' +import { generateId } from '@/lib/core/utils/uuid' import { createApiResponse, getUserLimits } from '@/app/api/v1/logs/meta' import { checkRateLimit, createRateLimitResponse } from '@/app/api/v1/middleware' @@ -11,7 +12,7 @@ const logger = createLogger('V1LogDetailsAPI') export const revalidate = 0 export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = crypto.randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const rateLimit = await checkRateLimit(request, 'logs-detail') diff --git a/apps/sim/app/api/v1/logs/route.ts b/apps/sim/app/api/v1/logs/route.ts index bc9562fd273..cab370d8141 100644 --- a/apps/sim/app/api/v1/logs/route.ts +++ b/apps/sim/app/api/v1/logs/route.ts @@ -4,6 +4,7 @@ import { createLogger } from '@sim/logger' import { and, eq, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' +import { generateId } from '@/lib/core/utils/uuid' import { buildLogFilters, getOrderBy } from '@/app/api/v1/logs/filters' import { createApiResponse, getUserLimits } from '@/app/api/v1/logs/meta' import { checkRateLimit, createRateLimitResponse } from '@/app/api/v1/middleware' @@ -53,7 +54,7 @@ function decodeCursor(cursor: string): CursorData | null { } export async function GET(request: NextRequest) { - const requestId = crypto.randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const rateLimit = await checkRateLimit(request, 'logs') diff --git a/apps/sim/app/api/v1/workflows/[id]/route.ts b/apps/sim/app/api/v1/workflows/[id]/route.ts index 9fe825e6224..15a97f9b9ad 100644 --- a/apps/sim/app/api/v1/workflows/[id]/route.ts +++ b/apps/sim/app/api/v1/workflows/[id]/route.ts @@ -3,6 +3,7 @@ import { workflowBlocks } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' +import { generateId } from '@/lib/core/utils/uuid' import { getActiveWorkflowRecord } from '@/lib/workflows/active-context' import { extractInputFieldsFromBlocks } from '@/lib/workflows/input-format' import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' @@ -14,7 +15,7 @@ const logger = createLogger('V1WorkflowDetailsAPI') export const revalidate = 0 export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { - const requestId = crypto.randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const rateLimit = await checkRateLimit(request, 'workflow-detail') diff --git a/apps/sim/app/api/v1/workflows/route.ts b/apps/sim/app/api/v1/workflows/route.ts index 267650aff10..718f0afb37f 100644 --- a/apps/sim/app/api/v1/workflows/route.ts +++ b/apps/sim/app/api/v1/workflows/route.ts @@ -4,6 +4,7 @@ import { createLogger } from '@sim/logger' import { and, asc, eq, gt, isNull, or } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' +import { generateId } from '@/lib/core/utils/uuid' import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' import { createApiResponse, getUserLimits } from '@/app/api/v1/logs/meta' import { checkRateLimit, createRateLimitResponse } from '@/app/api/v1/middleware' @@ -40,7 +41,7 @@ function decodeCursor(cursor: string): CursorData | null { } export async function GET(request: NextRequest) { - const requestId = crypto.randomUUID().slice(0, 8) + const requestId = generateId().slice(0, 8) try { const rateLimit = await checkRateLimit(request, 'workflows') diff --git a/apps/sim/app/api/webhooks/agentmail/route.ts b/apps/sim/app/api/webhooks/agentmail/route.ts index 7486a24556e..25e87f1de35 100644 --- a/apps/sim/app/api/webhooks/agentmail/route.ts +++ b/apps/sim/app/api/webhooks/agentmail/route.ts @@ -12,8 +12,8 @@ import { tasks } from '@trigger.dev/sdk' import { and, eq, gt, ne, sql } from 'drizzle-orm' import { NextResponse } from 'next/server' import { Webhook } from 'svix' -import { v4 as uuidv4 } from 'uuid' import { isTriggerDevEnabled } from '@/lib/core/config/feature-flags' +import { generateId } from '@/lib/core/utils/uuid' import { executeInboxTask } from '@/lib/mothership/inbox/executor' import type { AgentMailWebhookPayload, RejectionReason } from '@/lib/mothership/inbox/types' @@ -137,7 +137,7 @@ export async function POST(req: Request) { const fromName = extractDisplayName(message.from_) - const taskId = uuidv4() + const taskId = generateId() const bodyText = message.text?.substring(0, 50_000) || null const bodyHtml = message.html?.substring(0, 50_000) || null const bodyPreview = (bodyText || '')?.substring(0, 200) || null @@ -254,7 +254,7 @@ async function createRejectedTask( reason: RejectionReason ): Promise { await db.insert(mothershipInboxTask).values({ - id: uuidv4(), + id: generateId(), workspaceId, fromEmail: extractSenderEmail(message.from_) || 'unknown', fromName: extractDisplayName(message.from_), diff --git a/apps/sim/app/api/webhooks/poll/gmail/route.ts b/apps/sim/app/api/webhooks/poll/gmail/route.ts index 7b8f6c250b0..5eabf8b9b63 100644 --- a/apps/sim/app/api/webhooks/poll/gmail/route.ts +++ b/apps/sim/app/api/webhooks/poll/gmail/route.ts @@ -1,8 +1,8 @@ import { createLogger } from '@sim/logger' -import { nanoid } from 'nanoid' import { type NextRequest, NextResponse } from 'next/server' import { verifyCronAuth } from '@/lib/auth/internal' import { acquireLock, releaseLock } from '@/lib/core/config/redis' +import { generateShortId } from '@/lib/core/utils/uuid' import { pollGmailWebhooks } from '@/lib/webhooks/gmail-polling-service' const logger = createLogger('GmailPollingAPI') @@ -14,7 +14,7 @@ const LOCK_KEY = 'gmail-polling-lock' const LOCK_TTL_SECONDS = 180 // Same as maxDuration (3 min) export async function GET(request: NextRequest) { - const requestId = nanoid() + const requestId = generateShortId() logger.info(`Gmail webhook polling triggered (${requestId})`) let lockValue: string | undefined diff --git a/apps/sim/app/api/webhooks/poll/imap/route.ts b/apps/sim/app/api/webhooks/poll/imap/route.ts index 1759f43c0b4..29826e04bff 100644 --- a/apps/sim/app/api/webhooks/poll/imap/route.ts +++ b/apps/sim/app/api/webhooks/poll/imap/route.ts @@ -1,8 +1,8 @@ import { createLogger } from '@sim/logger' -import { nanoid } from 'nanoid' import { type NextRequest, NextResponse } from 'next/server' import { verifyCronAuth } from '@/lib/auth/internal' import { acquireLock, releaseLock } from '@/lib/core/config/redis' +import { generateShortId } from '@/lib/core/utils/uuid' import { pollImapWebhooks } from '@/lib/webhooks/imap-polling-service' const logger = createLogger('ImapPollingAPI') @@ -14,7 +14,7 @@ const LOCK_KEY = 'imap-polling-lock' const LOCK_TTL_SECONDS = 180 // Same as maxDuration (3 min) export async function GET(request: NextRequest) { - const requestId = nanoid() + const requestId = generateShortId() logger.info(`IMAP webhook polling triggered (${requestId})`) let lockValue: string | undefined diff --git a/apps/sim/app/api/webhooks/poll/outlook/route.ts b/apps/sim/app/api/webhooks/poll/outlook/route.ts index c7266fa6363..2a72c34f86a 100644 --- a/apps/sim/app/api/webhooks/poll/outlook/route.ts +++ b/apps/sim/app/api/webhooks/poll/outlook/route.ts @@ -1,8 +1,8 @@ import { createLogger } from '@sim/logger' -import { nanoid } from 'nanoid' import { type NextRequest, NextResponse } from 'next/server' import { verifyCronAuth } from '@/lib/auth/internal' import { acquireLock, releaseLock } from '@/lib/core/config/redis' +import { generateShortId } from '@/lib/core/utils/uuid' import { pollOutlookWebhooks } from '@/lib/webhooks/outlook-polling-service' const logger = createLogger('OutlookPollingAPI') @@ -14,7 +14,7 @@ const LOCK_KEY = 'outlook-polling-lock' const LOCK_TTL_SECONDS = 180 // Same as maxDuration (3 min) export async function GET(request: NextRequest) { - const requestId = nanoid() + const requestId = generateShortId() logger.info(`Outlook webhook polling triggered (${requestId})`) let lockValue: string | undefined diff --git a/apps/sim/app/api/webhooks/poll/rss/route.ts b/apps/sim/app/api/webhooks/poll/rss/route.ts index 1f9201ee7d2..cd221abe394 100644 --- a/apps/sim/app/api/webhooks/poll/rss/route.ts +++ b/apps/sim/app/api/webhooks/poll/rss/route.ts @@ -1,8 +1,8 @@ import { createLogger } from '@sim/logger' -import { nanoid } from 'nanoid' import { type NextRequest, NextResponse } from 'next/server' import { verifyCronAuth } from '@/lib/auth/internal' import { acquireLock, releaseLock } from '@/lib/core/config/redis' +import { generateShortId } from '@/lib/core/utils/uuid' import { pollRssWebhooks } from '@/lib/webhooks/rss-polling-service' const logger = createLogger('RssPollingAPI') @@ -14,7 +14,7 @@ const LOCK_KEY = 'rss-polling-lock' const LOCK_TTL_SECONDS = 180 // Same as maxDuration (3 min) export async function GET(request: NextRequest) { - const requestId = nanoid() + const requestId = generateShortId() logger.info(`RSS webhook polling triggered (${requestId})`) let lockValue: string | undefined diff --git a/apps/sim/app/api/webhooks/route.ts b/apps/sim/app/api/webhooks/route.ts index e58baa8d54c..ea17b75cefe 100644 --- a/apps/sim/app/api/webhooks/route.ts +++ b/apps/sim/app/api/webhooks/route.ts @@ -2,12 +2,12 @@ import { db } from '@sim/db' import { permissions, webhook, workflow, workflowDeploymentVersion } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, desc, eq, inArray, isNull, or } from 'drizzle-orm' -import { nanoid } from 'nanoid' import { type NextRequest, NextResponse } from 'next/server' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { PlatformEvents } from '@/lib/core/telemetry' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId, generateShortId } from '@/lib/core/utils/uuid' import { getProviderIdFromServiceId } from '@/lib/oauth' import { captureServerEvent } from '@/lib/posthog/server' import { resolveEnvVarsInObject } from '@/lib/webhooks/env-resolver' @@ -247,7 +247,7 @@ export async function POST(request: NextRequest) { // If still no path, generate a new dummy path (first-time save) if (!finalPath || finalPath.trim() === '') { - finalPath = `${provider}-${crypto.randomUUID()}` + finalPath = `${provider}-${generateId()}` logger.info(`[${requestId}] Generated webhook path for ${provider} trigger: ${finalPath}`) } } else { @@ -492,7 +492,7 @@ export async function POST(request: NextRequest) { let externalSubscriptionCreated = false const createTempWebhookData = (providerConfigOverride = resolvedProviderConfig) => ({ - id: targetWebhookId || nanoid(), + id: targetWebhookId || generateShortId(), path: finalPath, provider, providerConfig: providerConfigOverride, @@ -579,7 +579,7 @@ export async function POST(request: NextRequest) { }) } else { // Create a new webhook - const webhookId = nanoid() + const webhookId = generateShortId() logger.info(`[${requestId}] Creating new webhook with ID: ${webhookId}`) const newResult = await db .insert(webhook) diff --git a/apps/sim/app/api/webhooks/trigger/[path]/route.test.ts b/apps/sim/app/api/webhooks/trigger/[path]/route.test.ts index 7938123e1d1..7ee5d198f3f 100644 --- a/apps/sim/app/api/webhooks/trigger/[path]/route.test.ts +++ b/apps/sim/app/api/webhooks/trigger/[path]/route.test.ts @@ -414,12 +414,6 @@ describe('Webhook Trigger API Route', () => { handleWhatsAppVerificationMock.mockResolvedValue(null) processGenericDeduplicationMock.mockResolvedValue(null) processWebhookMock.mockResolvedValue(new Response('Webhook processed', { status: 200 })) - - if ((global as any).crypto?.randomUUID) { - vi.spyOn(crypto, 'randomUUID').mockRestore() - } - - vi.spyOn(crypto, 'randomUUID').mockReturnValue('mock-uuid-12345') }) afterEach(() => { diff --git a/apps/sim/app/api/workflows/[id]/execute/route.async.test.ts b/apps/sim/app/api/workflows/[id]/execute/route.async.test.ts index a800994c004..77feaf9843a 100644 --- a/apps/sim/app/api/workflows/[id]/execute/route.async.test.ts +++ b/apps/sim/app/api/workflows/[id]/execute/route.async.test.ts @@ -93,9 +93,12 @@ vi.mock('@sim/logger', () => { return { createLogger: vi.fn(() => createMockLogger()) } }) -vi.mock('uuid', () => ({ - validate: vi.fn().mockReturnValue(true), - v4: vi.fn().mockReturnValue('execution-123'), +vi.mock('@/lib/core/utils/uuid', () => ({ + generateId: vi.fn(() => 'execution-123'), + generateShortId: vi.fn(() => 'mock-short-id'), + isValidUuid: vi.fn((v: string) => + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v) + ), })) import { POST } from './route' diff --git a/apps/sim/app/api/workflows/[id]/execute/route.ts b/apps/sim/app/api/workflows/[id]/execute/route.ts index 37e87cb4de2..d5b484dfaca 100644 --- a/apps/sim/app/api/workflows/[id]/execute/route.ts +++ b/apps/sim/app/api/workflows/[id]/execute/route.ts @@ -1,6 +1,5 @@ import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' -import { validate as uuidValidate, v4 as uuidv4 } from 'uuid' import { z } from 'zod' import { AuthType, checkHybridAuth, hasExternalApiCredentials } from '@/lib/auth/hybrid' import { admissionRejectedResponse, tryAdmit } from '@/lib/core/admission/gate' @@ -14,6 +13,7 @@ import { import { generateRequestId } from '@/lib/core/utils/request' import { SSE_HEADERS } from '@/lib/core/utils/sse' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId, isValidUuid } from '@/lib/core/utils/uuid' import { DispatchQueueFullError, enqueueWorkspaceDispatch, @@ -133,19 +133,19 @@ function resolveOutputIds( const dotIndex = outputId.indexOf('.') if (underscoreIndex > 0) { const maybeUuid = outputId.substring(0, underscoreIndex) - if (uuidValidate(maybeUuid)) { + if (isValidUuid(maybeUuid)) { return outputId } } if (dotIndex > 0) { const maybeUuid = outputId.substring(0, dotIndex) - if (uuidValidate(maybeUuid)) { + if (isValidUuid(maybeUuid)) { return `${outputId.substring(0, dotIndex)}_${outputId.substring(dotIndex + 1)}` } } - if (uuidValidate(outputId)) { + if (isValidUuid(outputId)) { return outputId } @@ -594,7 +594,7 @@ async function handleExecutePost( ) } - const executionId = uuidv4() + const executionId = generateId() reqLogger = reqLogger.withMetadata({ userId, executionId }) reqLogger.info('Starting server-side execution', { diff --git a/apps/sim/app/api/workflows/route.ts b/apps/sim/app/api/workflows/route.ts index cab2bbb2324..3615afd0890 100644 --- a/apps/sim/app/api/workflows/route.ts +++ b/apps/sim/app/api/workflows/route.ts @@ -7,6 +7,7 @@ import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { captureServerEvent } from '@/lib/posthog/server' import { getNextWorkflowColor } from '@/lib/workflows/colors' import { buildDefaultWorkflowArtifacts } from '@/lib/workflows/defaults' @@ -162,7 +163,7 @@ export async function POST(req: NextRequest) { ) } - const workflowId = clientId || crypto.randomUUID() + const workflowId = clientId || generateId() const now = new Date() logger.info(`[${requestId}] Creating workflow ${workflowId} for user ${userId}`) diff --git a/apps/sim/app/api/workspaces/[id]/api-keys/route.ts b/apps/sim/app/api/workspaces/[id]/api-keys/route.ts index 62638bbb47a..a6a15bb52f2 100644 --- a/apps/sim/app/api/workspaces/[id]/api-keys/route.ts +++ b/apps/sim/app/api/workspaces/[id]/api-keys/route.ts @@ -2,7 +2,6 @@ import { db } from '@sim/db' import { apiKey } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq, inArray } from 'drizzle-orm' -import { nanoid } from 'nanoid' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { createApiKey, getApiKeyDisplayFormat } from '@/lib/api-key/auth' @@ -10,6 +9,7 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { PlatformEvents } from '@/lib/core/telemetry' import { generateRequestId } from '@/lib/core/utils/request' +import { generateShortId } from '@/lib/core/utils/uuid' import { captureServerEvent } from '@/lib/posthog/server' import { getUserEntityPermissions, getWorkspaceById } from '@/lib/workspaces/permissions/utils' @@ -135,7 +135,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ const [newKey] = await db .insert(apiKey) .values({ - id: nanoid(), + id: generateShortId(), workspaceId, userId: userId, createdBy: userId, diff --git a/apps/sim/app/api/workspaces/[id]/byok-keys/route.ts b/apps/sim/app/api/workspaces/[id]/byok-keys/route.ts index 49efb08d59f..65f177b1c55 100644 --- a/apps/sim/app/api/workspaces/[id]/byok-keys/route.ts +++ b/apps/sim/app/api/workspaces/[id]/byok-keys/route.ts @@ -2,13 +2,13 @@ import { db } from '@sim/db' import { workspaceBYOKKeys } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq } from 'drizzle-orm' -import { nanoid } from 'nanoid' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { decryptSecret, encryptSecret } from '@/lib/core/security/encryption' import { generateRequestId } from '@/lib/core/utils/request' +import { generateShortId } from '@/lib/core/utils/uuid' import { captureServerEvent } from '@/lib/posthog/server' import { getUserEntityPermissions, getWorkspaceById } from '@/lib/workspaces/permissions/utils' @@ -186,7 +186,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ const [newKey] = await db .insert(workspaceBYOKKeys) .values({ - id: nanoid(), + id: generateShortId(), workspaceId, providerId, encryptedApiKey: encrypted, diff --git a/apps/sim/app/api/workspaces/[id]/environment/route.ts b/apps/sim/app/api/workspaces/[id]/environment/route.ts index 25bbe66719f..2e118b628d7 100644 --- a/apps/sim/app/api/workspaces/[id]/environment/route.ts +++ b/apps/sim/app/api/workspaces/[id]/environment/route.ts @@ -8,6 +8,7 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { encryptSecret } from '@/lib/core/security/encryption' import { generateRequestId } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { syncWorkspaceEnvCredentials } from '@/lib/credentials/environment' import { getPersonalAndWorkspaceEnv } from '@/lib/environment/utils' import { getUserEntityPermissions, getWorkspaceById } from '@/lib/workspaces/permissions/utils' @@ -114,7 +115,7 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{ await db .insert(workspaceEnvironment) .values({ - id: crypto.randomUUID(), + id: generateId(), workspaceId, variables: merged, createdAt: new Date(), @@ -199,7 +200,7 @@ export async function DELETE( await db .insert(workspaceEnvironment) .values({ - id: wsRows[0]?.id || crypto.randomUUID(), + id: wsRows[0]?.id || generateId(), workspaceId, variables: current, createdAt: wsRows[0]?.createdAt || new Date(), diff --git a/apps/sim/app/api/workspaces/[id]/inbox/senders/route.ts b/apps/sim/app/api/workspaces/[id]/inbox/senders/route.ts index 3b48f75db04..488f819a48f 100644 --- a/apps/sim/app/api/workspaces/[id]/inbox/senders/route.ts +++ b/apps/sim/app/api/workspaces/[id]/inbox/senders/route.ts @@ -2,10 +2,10 @@ import { db, mothershipInboxAllowedSender, permissions, user } from '@sim/db' import { createLogger } from '@sim/logger' import { and, eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { z } from 'zod' import { getSession } from '@/lib/auth' import { hasInboxAccess } from '@/lib/billing/core/subscription' +import { generateId } from '@/lib/core/utils/uuid' import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' const logger = createLogger('InboxSendersAPI') @@ -113,7 +113,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id: const [sender] = await db .insert(mothershipInboxAllowedSender) .values({ - id: uuidv4(), + id: generateId(), workspaceId, email: normalizedEmail, label: label || null, diff --git a/apps/sim/app/api/workspaces/[id]/notifications/[notificationId]/test/route.ts b/apps/sim/app/api/workspaces/[id]/notifications/[notificationId]/test/route.ts index 5e13dc9a540..c1d0c930339 100644 --- a/apps/sim/app/api/workspaces/[id]/notifications/[notificationId]/test/route.ts +++ b/apps/sim/app/api/workspaces/[id]/notifications/[notificationId]/test/route.ts @@ -4,7 +4,6 @@ import { account, workspaceNotificationSubscription } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { type EmailRateLimitsData, type EmailUsageData, @@ -14,6 +13,7 @@ import { getSession } from '@/lib/auth' import { decryptSecret } from '@/lib/core/security/encryption' import { secureFetchWithValidation } from '@/lib/core/security/input-validation.server' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { sendEmail } from '@/lib/messaging/email/mailer' import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' @@ -41,8 +41,8 @@ function generateSignature(secret: string, timestamp: number, body: string): str function buildTestPayload(subscription: typeof workspaceNotificationSubscription.$inferSelect) { const timestamp = Date.now() - const eventId = `evt_test_${uuidv4()}` - const executionId = `exec_test_${uuidv4()}` + const eventId = `evt_test_${generateId()}` + const executionId = `exec_test_${generateId()}` const payload: Record = { id: eventId, @@ -120,7 +120,7 @@ async function testWebhook(subscription: typeof workspaceNotificationSubscriptio const { payload, timestamp } = buildTestPayload(subscription) const body = JSON.stringify(payload) - const deliveryId = `delivery_test_${uuidv4()}` + const deliveryId = `delivery_test_${generateId()}` const headers: Record = { 'Content-Type': 'application/json', diff --git a/apps/sim/app/api/workspaces/[id]/notifications/route.ts b/apps/sim/app/api/workspaces/[id]/notifications/route.ts index c49c451752f..1a18f8d2386 100644 --- a/apps/sim/app/api/workspaces/[id]/notifications/route.ts +++ b/apps/sim/app/api/workspaces/[id]/notifications/route.ts @@ -3,11 +3,11 @@ import { workflow, workspaceNotificationSubscription } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { and, eq, inArray } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' -import { v4 as uuidv4 } from 'uuid' import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { encryptSecret } from '@/lib/core/security/encryption' +import { generateId } from '@/lib/core/utils/uuid' import { captureServerEvent } from '@/lib/posthog/server' import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' import { MAX_EMAIL_RECIPIENTS, MAX_NOTIFICATIONS_PER_TYPE, MAX_WORKFLOW_IDS } from './constants' @@ -232,7 +232,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{ const [subscription] = await db .insert(workspaceNotificationSubscription) .values({ - id: uuidv4(), + id: generateId(), workspaceId, notificationType: data.notificationType, workflowIds: data.workflowIds, diff --git a/apps/sim/app/api/workspaces/[id]/permissions/route.ts b/apps/sim/app/api/workspaces/[id]/permissions/route.ts index 01d5a01ae9d..f31bce34ba6 100644 --- a/apps/sim/app/api/workspaces/[id]/permissions/route.ts +++ b/apps/sim/app/api/workspaces/[id]/permissions/route.ts @@ -1,4 +1,3 @@ -import crypto from 'crypto' import { db } from '@sim/db' import { permissions, user, workspace, workspaceEnvironment } from '@sim/db/schema' import { createLogger } from '@sim/logger' @@ -7,6 +6,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' +import { generateId } from '@/lib/core/utils/uuid' import { syncWorkspaceEnvCredentials } from '@/lib/credentials/environment' import { captureServerEvent } from '@/lib/posthog/server' import { @@ -161,7 +161,7 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise< ) await tx.insert(permissions).values({ - id: crypto.randomUUID(), + id: generateId(), userId: update.userId, entityType: 'workspace' as const, entityId: workspaceId, diff --git a/apps/sim/app/api/workspaces/invitations/[invitationId]/route.test.ts b/apps/sim/app/api/workspaces/invitations/[invitationId]/route.test.ts index 6ccb82e0252..5d1681f1052 100644 --- a/apps/sim/app/api/workspaces/invitations/[invitationId]/route.test.ts +++ b/apps/sim/app/api/workspaces/invitations/[invitationId]/route.test.ts @@ -143,8 +143,12 @@ vi.mock('drizzle-orm', () => ({ isNull: vi.fn((field: unknown) => ({ type: 'isNull', field })), })) -vi.mock('crypto', () => ({ - randomUUID: vi.fn().mockReturnValue('mock-uuid-1234'), +vi.mock('@/lib/core/utils/uuid', () => ({ + generateId: vi.fn().mockReturnValue('mock-uuid-1234'), + generateShortId: vi.fn(() => 'mock-short-id'), + isValidUuid: vi.fn((v: string) => + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v) + ), })) import { DELETE, GET } from './route' diff --git a/apps/sim/app/api/workspaces/invitations/[invitationId]/route.ts b/apps/sim/app/api/workspaces/invitations/[invitationId]/route.ts index df71f666986..602b60e88cd 100644 --- a/apps/sim/app/api/workspaces/invitations/[invitationId]/route.ts +++ b/apps/sim/app/api/workspaces/invitations/[invitationId]/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { render } from '@react-email/render' import { db } from '@sim/db' import { @@ -16,6 +15,7 @@ import { WorkspaceInvitationEmail } from '@/components/emails' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { syncWorkspaceEnvCredentials } from '@/lib/credentials/environment' import { sendEmail } from '@/lib/messaging/email/mailer' import { getFromEmailAddress } from '@/lib/messaging/email/utils' @@ -147,7 +147,7 @@ export async function GET( await db.transaction(async (tx) => { await tx.insert(permissions).values({ - id: randomUUID(), + id: generateId(), entityType: 'workspace' as const, entityId: invitation.workspaceId, userId: session.user.id, @@ -325,7 +325,7 @@ export async function POST( return NextResponse.json({ error: 'Workspace not found' }, { status: 404 }) } - const newToken = randomUUID() + const newToken = generateId() const newExpiresAt = new Date() newExpiresAt.setDate(newExpiresAt.getDate() + 7) diff --git a/apps/sim/app/api/workspaces/invitations/route.test.ts b/apps/sim/app/api/workspaces/invitations/route.test.ts index 248e721258d..20b697fd8e1 100644 --- a/apps/sim/app/api/workspaces/invitations/route.test.ts +++ b/apps/sim/app/api/workspaces/invitations/route.test.ts @@ -58,8 +58,12 @@ const { } }) -vi.mock('crypto', () => ({ - randomUUID: mockRandomUUID, +vi.mock('@/lib/core/utils/uuid', () => ({ + generateId: mockRandomUUID, + generateShortId: vi.fn(() => 'mock-short-id'), + isValidUuid: vi.fn((v: string) => + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v) + ), })) vi.mock('@/lib/auth', () => ({ diff --git a/apps/sim/app/api/workspaces/invitations/route.ts b/apps/sim/app/api/workspaces/invitations/route.ts index 4dbcc3152e7..30c91acd22f 100644 --- a/apps/sim/app/api/workspaces/invitations/route.ts +++ b/apps/sim/app/api/workspaces/invitations/route.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto' import { render } from '@react-email/render' import { db } from '@sim/db' import { @@ -17,6 +16,7 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { PlatformEvents } from '@/lib/core/telemetry' import { getBaseUrl } from '@/lib/core/utils/urls' +import { generateId } from '@/lib/core/utils/uuid' import { sendEmail } from '@/lib/messaging/email/mailer' import { getFromEmailAddress } from '@/lib/messaging/email/utils' import { captureServerEvent } from '@/lib/posthog/server' @@ -184,12 +184,12 @@ export async function POST(req: NextRequest) { ) } - const token = randomUUID() + const token = generateId() const expiresAt = new Date() expiresAt.setDate(expiresAt.getDate() + 7) // 7 days expiry const invitationData = { - id: randomUUID(), + id: generateId(), workspaceId, email, inviterId: session.user.id, diff --git a/apps/sim/app/api/workspaces/route.ts b/apps/sim/app/api/workspaces/route.ts index 686d6a0a1a2..d64fd05f758 100644 --- a/apps/sim/app/api/workspaces/route.ts +++ b/apps/sim/app/api/workspaces/route.ts @@ -7,6 +7,7 @@ import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { PlatformEvents } from '@/lib/core/telemetry' +import { generateId } from '@/lib/core/utils/uuid' import { captureServerEvent } from '@/lib/posthog/server' import { buildDefaultWorkflowArtifacts } from '@/lib/workflows/defaults' import { saveWorkflowToNormalizedTables } from '@/lib/workflows/persistence/utils' @@ -140,8 +141,8 @@ async function createWorkspace( skipDefaultWorkflow = false, explicitColor?: string ) { - const workspaceId = crypto.randomUUID() - const workflowId = crypto.randomUUID() + const workspaceId = generateId() + const workflowId = generateId() const now = new Date() const color = explicitColor || getRandomWorkspaceColor() @@ -159,7 +160,7 @@ async function createWorkspace( }) await tx.insert(permissions).values({ - id: crypto.randomUUID(), + id: generateId(), entityType: 'workspace' as const, entityId: workspaceId, userId: userId, diff --git a/apps/sim/app/chat/[identifier]/chat.tsx b/apps/sim/app/chat/[identifier]/chat.tsx index aec07245aa9..5d7cf9e6f8f 100644 --- a/apps/sim/app/chat/[identifier]/chat.tsx +++ b/apps/sim/app/chat/[identifier]/chat.tsx @@ -2,8 +2,8 @@ import { type RefObject, useCallback, useEffect, useRef, useState } from 'react' import { createLogger } from '@sim/logger' -import { v4 as uuidv4 } from 'uuid' import { noop } from '@/lib/core/utils/request' +import { generateId } from '@/lib/core/utils/uuid' import { getFormattedGitHubStars } from '@/app/(landing)/actions/github' import { ChatErrorState, @@ -256,7 +256,7 @@ export default function ChatClient({ identifier }: { identifier: string }) { useEffect(() => { fetchChatConfig() - setConversationId(uuidv4()) + setConversationId(generateId()) getFormattedGitHubStars() .then((formattedStars) => { @@ -303,7 +303,7 @@ export default function ChatClient({ identifier }: { identifier: string }) { setUserHasScrolled(false) const userMessage: ChatMessage = { - id: crypto.randomUUID(), + id: generateId(), content: messageToSend || (files && files.length > 0 ? `Sent ${files.length} file(s)` : ''), type: 'user', timestamp: new Date(), @@ -416,7 +416,7 @@ export default function ChatClient({ identifier }: { identifier: string }) { logger.error('Error sending message:', error) setIsLoading(false) const errorMessage: ChatMessage = { - id: crypto.randomUUID(), + id: generateId(), content: CHAT_ERROR_MESSAGES.GENERIC_ERROR, type: 'assistant', timestamp: new Date(), diff --git a/apps/sim/app/chat/components/input/input.tsx b/apps/sim/app/chat/components/input/input.tsx index 31ba5922701..7a282525d03 100644 --- a/apps/sim/app/chat/components/input/input.tsx +++ b/apps/sim/app/chat/components/input/input.tsx @@ -6,6 +6,7 @@ import { createLogger } from '@sim/logger' import { ArrowUp, Mic, Paperclip, X } from 'lucide-react' import { Badge, Tooltip } from '@/components/emcn' import { cn } from '@/lib/core/utils/cn' +import { generateId } from '@/lib/core/utils/uuid' import { CHAT_ACCEPT_ATTRIBUTE } from '@/lib/uploads/utils/validation' import { VoiceInput } from '@/app/chat/components/input/voice-input' @@ -92,7 +93,7 @@ export const ChatInput: React.FC<{ } newFiles.push({ - id: crypto.randomUUID(), + id: generateId(), name: file.name, size: file.size, type: file.type, diff --git a/apps/sim/app/chat/hooks/use-chat-streaming.ts b/apps/sim/app/chat/hooks/use-chat-streaming.ts index 79dfb02f40a..807cb0a1733 100644 --- a/apps/sim/app/chat/hooks/use-chat-streaming.ts +++ b/apps/sim/app/chat/hooks/use-chat-streaming.ts @@ -3,6 +3,7 @@ import { useRef, useState } from 'react' import { createLogger } from '@sim/logger' import { isUserFileWithMetadata } from '@/lib/core/utils/user-file' +import { generateId } from '@/lib/core/utils/uuid' import type { ChatFile, ChatMessage } from '@/app/chat/components/message/message' import { CHAT_ERROR_MESSAGES } from '@/app/chat/constants' @@ -136,7 +137,7 @@ export function useChatStreaming() { let lastAudioPosition = 0 const messageIdMap = new Map() - const messageId = crypto.randomUUID() + const messageId = generateId() const UI_BATCH_MAX_MS = 50 let uiDirty = false diff --git a/apps/sim/app/layout.tsx b/apps/sim/app/layout.tsx index 5863c4405d3..c7b35d1c1fa 100644 --- a/apps/sim/app/layout.tsx +++ b/apps/sim/app/layout.tsx @@ -31,24 +31,6 @@ export default function RootLayout({ children }: { children: React.ReactNode }) return ( - {/* Polyfill crypto.randomUUID for non-secure contexts (HTTP on non-localhost) */} -