diff --git a/web/actions/backups.ts b/web/actions/backups.ts
index 978cdf2..181cae9 100644
--- a/web/actions/backups.ts
+++ b/web/actions/backups.ts
@@ -1,10 +1,10 @@
 "use server";
 
-import { desc, eq } from "drizzle-orm";
+import { eq } from "drizzle-orm";
 import { revalidatePath } from "next/cache";
 import { db } from "@/db";
 import { getBackupStorageConfig } from "@/db/queries";
-import { servers, volumeBackups } from "@/db/schema";
+import { volumeBackups } from "@/db/schema";
 import { requireAuth } from "@/lib/auth";
 import { triggerBackup } from "@/lib/backups/trigger-backup";
 import { inngest } from "@/lib/inngest/client";
@@ -31,27 +31,6 @@ export async function createBackup(serviceId: string, volumeId: string) {
 	return { success: true, backupId: result.backupId };
 }
 
-export async function listBackups(serviceId: string) {
-	await requireAuth();
-	const backups = await db
-		.select({
-			id: volumeBackups.id,
-			volumeName: volumeBackups.volumeName,
-			status: volumeBackups.status,
-			sizeBytes: volumeBackups.sizeBytes,
-			createdAt: volumeBackups.createdAt,
-			completedAt: volumeBackups.completedAt,
-			errorMessage: volumeBackups.errorMessage,
-			serverName: servers.name,
-		})
-		.from(volumeBackups)
-		.leftJoin(servers, eq(volumeBackups.serverId, servers.id))
-		.where(eq(volumeBackups.serviceId, serviceId))
-		.orderBy(desc(volumeBackups.createdAt));
-
-	return backups;
-}
-
 export async function restoreBackup(
 	serviceId: string,
 	backupId: string,
diff --git a/web/actions/migrations.ts b/web/actions/migrations.ts
index f7b6353..f4b9e0b 100644
--- a/web/actions/migrations.ts
+++ b/web/actions/migrations.ts
@@ -1,101 +1,20 @@
 "use server";
 
-import { and, eq } from "drizzle-orm";
+import { eq } from "drizzle-orm";
 import { revalidatePath } from "next/cache";
 import { db } from "@/db";
-import { getBackupStorageConfig } from "@/db/queries";
-import { deployments, services, serviceVolumes } from "@/db/schema";
+import { services } from "@/db/schema";
 import { requireAuth } from "@/lib/auth";
 import { inngest } from "@/lib/inngest/client";
 import { inngestEvents } from "@/lib/inngest/events";
+import { startMigrationInternal } from "@/lib/migrations";
 
 export async function startMigration(
 	serviceId: string,
 	targetServerId: string,
 ) {
 	await requireAuth();
-	const storageConfig = await getBackupStorageConfig();
-	if (!storageConfig) {
-		throw new Error(
-			"Backup storage not configured. Configure it in Settings first.",
-		);
-	}
-
-	const service = await db
-		.select()
-		.from(services)
-		.where(eq(services.id, serviceId))
-		.then((r) => r[0]);
-
-	if (!service) {
-		throw new Error("Service not found");
-	}
-
-	if (!service.stateful) {
-		throw new Error("Only stateful services can be migrated");
-	}
-
-	if (service.migrationStatus) {
-		throw new Error("Migration already in progress");
-	}
-
-	const volumes = await db
-		.select()
-		.from(serviceVolumes)
-		.where(eq(serviceVolumes.serviceId, serviceId));
-
-	if (volumes.length === 0) {
-		throw new Error("No volumes found for this service");
-	}
-
-	const deployment = await db
-		.select({
-			id: deployments.id,
-			serverId: deployments.serverId,
-			containerId: deployments.containerId,
-		})
-		.from(deployments)
-		.where(
-			and(
-				eq(deployments.serviceId, serviceId),
-				eq(deployments.status, "running"),
-			),
-		)
-		.then((r) => r[0]);
-
-	if (!deployment?.serverId) {
-		throw new Error("No running deployment found");
-	}
-
-	if (!deployment.containerId) {
-		throw new Error("Deployment is missing container ID");
-	}
-
-	if (deployment.serverId === targetServerId) {
-		throw new Error("Service is already running on the target server");
-	}
-
-	await db
-		.update(services)
-		.set({
-			migrationStatus: "backing_up",
-			migrationTargetServerId: targetServerId,
-			migrationBackupId: null,
-			migrationError: null,
-		})
-		.where(eq(services.id, serviceId));
-
-	await inngest.send(
-		inngestEvents.migrationStarted.create({
-			serviceId,
-			targetServerId,
-			sourceServerId: deployment.serverId,
-			sourceDeploymentId: deployment.id,
-			sourceContainerId: deployment.containerId,
-			volumes: volumes.map((v) => ({ id: v.id, name: v.name })),
-		}),
-	);
-
+	await startMigrationInternal(serviceId, targetServerId);
 	revalidatePath(`/dashboard/projects`);
 	return { success: true };
 }
@@ -117,17 +36,3 @@ export async function cancelMigration(serviceId: string) {
 	revalidatePath(`/dashboard/projects`);
 	return { success: true };
 }
-
-export async function getMigrationStatus(serviceId: string) {
-	await requireAuth();
-	const service = await db
-		.select({
-			migrationStatus: services.migrationStatus,
-			migrationError: services.migrationError,
-		})
-		.from(services)
-		.where(eq(services.id, serviceId))
-		.then((r) => r[0]);
-
-	return service ?? null;
-}
diff --git a/web/actions/projects.ts b/web/actions/projects.ts
index b07053e..057e878 100644
--- a/web/actions/projects.ts
+++ b/web/actions/projects.ts
@@ -30,6 +30,7 @@ import {
 } from "@/db/schema";
 import { requireAuth } from "@/lib/auth";
 import { DEFAULT_RESOURCE_LIMITS } from "@/lib/constants";
+import { deployServiceInternal } from "@/lib/deploy-service";
 import { markDeploymentUndesired } from "@/lib/deployment-status";
 import { inngest } from "@/lib/inngest/client";
 import { inngestEvents } from "@/lib/inngest/events";
@@ -47,7 +48,6 @@ import type {
 import { getZodErrorMessage, slugify } from "@/lib/utils";
 import { enqueueWork } from "@/lib/work-queue";
 import { deleteBackup } from "./backups";
-import { startMigration } from "./migrations";
 
 function isValidImageReferencePart(reference: string): boolean {
 	const tagPattern = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/;
@@ -860,62 +860,7 @@ export async function updateServiceGithubRepo(
 
 export async function deployService(serviceId: string) {
 	await requireAuth();
-	const service = await getService(serviceId);
-	if (!service) {
-		throw new Error("Service not found");
-	}
-
-	if (service.stateful) {
-		const configuredReplicas = await db
-			.select({
-				serverId: serviceReplicas.serverId,
-				replicas: serviceReplicas.count,
-			})
-			.from(serviceReplicas)
-			.where(eq(serviceReplicas.serviceId, serviceId));
-
-		const placements = configuredReplicas.filter((p) => p.replicas > 0);
-		const totalReplicas = placements.reduce((sum, p) => sum + p.replicas, 0);
-
-		if (totalReplicas !== 1) {
-			throw new Error("Stateful services can only have exactly 1 replica");
-		}
-
-		const serverIds = placements.map((p) => p.serverId);
-		if (serverIds.length !== 1) {
-			throw new Error(
-				"Stateful services must be deployed to exactly one server",
-			);
-		}
-
-		const targetServerId = serverIds[0];
-		if (service.lockedServerId && service.lockedServerId !== targetServerId) {
-			if (service.migrationStatus) {
-				throw new Error("Migration already in progress");
-			}
-			await startMigration(serviceId, targetServerId);
-			revalidatePath(`/dashboard/projects`);
-			return { migrationStarted: true };
-		}
-	}
-
-	const rolloutId = randomUUID();
-
-	await db.insert(rollouts).values({
-		id: rolloutId,
-		serviceId,
-		status: "in_progress",
-		currentStage: "queued",
-	});
-
-	await inngest.send(
-		inngestEvents.rolloutCreated.create({
-			rolloutId,
-			serviceId,
-		}),
-	);
-
-	return { rolloutId };
+	return deployServiceInternal(serviceId);
 }
 
 export async function deleteDeployments(serviceId: string) {
diff --git a/web/actions/servers.ts b/web/actions/servers.ts
index 5802add..cda9740 100644
--- a/web/actions/servers.ts
+++ b/web/actions/servers.ts
@@ -51,11 +51,6 @@ export async function deleteServer(id: string) {
 	await db.delete(servers).where(eq(servers.id, id));
 }
 
-export async function approveServer(id: string) {
-	await requireAuth();
-	await db.update(servers).set({ status: "pending" }).where(eq(servers.id, id));
-}
-
 export async function updateServerName(id: string, name: string) {
 	await requireAuth();
 	try {
diff --git a/web/app/api/v1/agent/builds/[id]/status/route.ts b/web/app/api/v1/agent/builds/[id]/status/route.ts
index bf35d19..da67cf2 100644
--- a/web/app/api/v1/agent/builds/[id]/status/route.ts
+++ b/web/app/api/v1/agent/builds/[id]/status/route.ts
@@ -1,6 +1,5 @@
 import { and, eq, isNull } from "drizzle-orm";
 import { type NextRequest, NextResponse } from "next/server";
-import { deployService } from "@/actions/projects";
 import { db } from "@/db";
 import {
 	builds,
@@ -10,6 +9,7 @@ import {
 	services,
 } from "@/db/schema";
 import { verifyAgentRequest } from "@/lib/agent-auth";
+import { deployServiceInternal } from "@/lib/deploy-service";
 import { sendBuildFailureAlert } from "@/lib/email";
 import { updateGitHubDeploymentStatus } from "@/lib/github";
 import { inngest } from "@/lib/inngest/client";
@@ -351,7 +351,7 @@ export async function POST(
 				);
 
 				try {
-					await deployService(build.serviceId);
+					await deployServiceInternal(build.serviceId);
 				} catch (error) {
 					console.error("[build:complete] deployment failed:", error);
 					await db
diff --git a/web/db/queries.ts b/web/db/queries.ts
index ebe3546..ea2bae5 100644
--- a/web/db/queries.ts
+++ b/web/db/queries.ts
@@ -1,14 +1,10 @@
 import { and, eq, isNotNull, isNull } from "drizzle-orm";
 import { db } from "@/db";
 import {
-	deploymentPorts,
 	deployments,
 	environments,
 	projects,
-	secrets,
 	servers,
-	servicePorts,
-	serviceReplicas,
 	services,
 	settings,
 } from "@/db/schema";
@@ -61,14 +57,6 @@ export async function getProjectBySlug(slug: string) {
 	return results[0] || null;
 }
 
-export async function listServices(projectId: string) {
-	return db
-		.select()
-		.from(services)
-		.where(and(eq(services.projectId, projectId), isNull(services.deletedAt)))
-		.orderBy(services.createdAt);
-}
-
 export async function getService(id: string) {
 	const results = await db
 		.select()
@@ -77,14 +65,6 @@ export async function getService(id: string) {
 	return results[0] || null;
 }
 
-export async function getDeletedService(id: string) {
-	const results = await db
-		.select()
-		.from(services)
-		.where(and(eq(services.id, id), isNotNull(services.deletedAt)));
-	return results[0] || null;
-}
-
 export async function listDeletedServices(
 	projectId: string,
 	environmentId?: string,
@@ -104,83 +84,10 @@ export async function listDeletedServices(
 		.orderBy(services.deletedAt);
 }
 
-export async function getOnlineServers() {
-	return db
-		.select({
-			id: servers.id,
-			name: servers.name,
-			wireguardIp: servers.wireguardIp,
-		})
-		.from(servers)
-		.where(eq(servers.status, "online"));
-}
-
-export async function getServicePorts(serviceId: string) {
-	return db
-		.select()
-		.from(servicePorts)
-		.where(eq(servicePorts.serviceId, serviceId))
-		.orderBy(servicePorts.port);
-}
-
-export async function getDeploymentPorts(deploymentId: string) {
-	return db
-		.select({
-			id: deploymentPorts.id,
-			hostPort: deploymentPorts.hostPort,
-			containerPort: servicePorts.port,
-		})
-		.from(deploymentPorts)
-		.innerJoin(servicePorts, eq(deploymentPorts.servicePortId, servicePorts.id))
-		.where(eq(deploymentPorts.deploymentId, deploymentId));
-}
-
-export async function listDeployments(serviceId: string) {
-	return db
-		.select()
-		.from(deployments)
-		.where(eq(deployments.serviceId, serviceId))
-		.orderBy(deployments.createdAt);
-}
-
-export async function getServiceReplicas(serviceId: string) {
-	const replicas = await db
-		.select({
-			id: serviceReplicas.id,
-			serverId: serviceReplicas.serverId,
-			serverName: servers.name,
-			count: serviceReplicas.count,
-		})
-		.from(serviceReplicas)
-		.innerJoin(servers, eq(serviceReplicas.serverId, servers.id))
-		.where(eq(serviceReplicas.serviceId, serviceId));
-
-	return replicas;
-}
-
-export async function listSecrets(serviceId: string) {
-	const secretsList = await db
-		.select({
-			id: secrets.id,
-			key: secrets.key,
-			createdAt: secrets.createdAt,
-		})
-		.from(secrets)
-		.where(eq(secrets.serviceId, serviceId))
-		.orderBy(secrets.createdAt);
-
-	return secretsList;
-}
-
 export async function listServers() {
 	return db.select().from(servers).orderBy(servers.createdAt);
 }
 
-export async function getServer(id: string) {
-	const results = await db.select().from(servers).where(eq(servers.id, id));
-	return results[0] || null;
-}
-
 export async function getServerDetails(id: string) {
 	const serverResults = await db
 		.select({
diff --git a/web/lib/api-auth.ts b/web/lib/api-auth.ts
index 8d7396f..954e9d8 100644
--- a/web/lib/api-auth.ts
+++ b/web/lib/api-auth.ts
@@ -22,7 +22,7 @@ function getAuthErrorResponse(error: unknown) {
 	);
 }
 
-export async function getRequestSession(request: Request) {
+async function getRequestSession(request: Request) {
 	return auth.api.getSession({
 		headers: request.headers,
 	});
diff --git a/web/lib/auth.ts b/web/lib/auth.ts
index 99e700b..700965f 100644
--- a/web/lib/auth.ts
+++ b/web/lib/auth.ts
@@ -6,7 +6,7 @@ import { headers } from "next/headers";
 import { db } from "@/db";
 import * as schema from "@/db/schema";
 
-export const TECHULUS_CLI_CLIENT_ID = "techulus-cli";
+const TECHULUS_CLI_CLIENT_ID = "techulus-cli";
 
 export const auth = betterAuth({
 	database: drizzleAdapter(db, {
diff --git a/web/lib/cli-service.ts b/web/lib/cli-service.ts
index 7b221a7..3d1222e 100644
--- a/web/lib/cli-service.ts
+++ b/web/lib/cli-service.ts
@@ -1,6 +1,5 @@
 import { and, desc, eq, ne } from "drizzle-orm";
 import {
-	deployService,
 	updateServiceConfig,
 	updateServiceResourceLimits,
 	updateServiceStartCommand,
@@ -25,6 +24,7 @@ import {
 	techulusManifestSchema,
 } from "@/lib/cli-manifest";
 import { DEFAULT_RESOURCE_LIMITS } from "@/lib/constants";
+import { deployServiceInternal } from "@/lib/deploy-service";
 import { slugify } from "@/lib/utils";
 
 export type ManifestChange = {
@@ -714,7 +714,7 @@ export async function deployManifest(manifest: TechulusManifest) {
 		manifest.service.replicas.count,
 	);
 
-	const result = await deployService(service.id);
+	const result = await deployServiceInternal(service.id);
 
 	return {
 		serviceId: service.id,
diff --git a/web/lib/date.ts b/web/lib/date.ts
index a7684c0..8132505 100644
--- a/web/lib/date.ts
+++ b/web/lib/date.ts
@@ -19,7 +19,7 @@ export function formatDateTime(date: string | Date): string {
 	});
 }
 
-export function formatDate(date: string | Date): string {
+function formatDate(date: string | Date): string {
 	return new Date(date).toLocaleDateString();
 }
 
diff --git a/web/lib/deploy-service.ts b/web/lib/deploy-service.ts
new file mode 100644
index 0000000..4e846dd
--- /dev/null
+++ b/web/lib/deploy-service.ts
@@ -0,0 +1,68 @@
+import { randomUUID } from "node:crypto";
+import { eq } from "drizzle-orm";
+import { revalidatePath } from "next/cache";
+import { db } from "@/db";
+import { getService } from "@/db/queries";
+import { rollouts, serviceReplicas } from "@/db/schema";
+import { inngest } from "@/lib/inngest/client";
+import { inngestEvents } from "@/lib/inngest/events";
+import { startMigrationInternal } from "@/lib/migrations";
+
+export async function deployServiceInternal(serviceId: string) {
+	const service = await getService(serviceId);
+	if (!service) {
+		throw new Error("Service not found");
+	}
+
+	if (service.stateful) {
+		const configuredReplicas = await db
+			.select({
+				serverId: serviceReplicas.serverId,
+				replicas: serviceReplicas.count,
+			})
+			.from(serviceReplicas)
+			.where(eq(serviceReplicas.serviceId, serviceId));
+
+		const placements = configuredReplicas.filter((p) => p.replicas > 0);
+		const totalReplicas = placements.reduce((sum, p) => sum + p.replicas, 0);
+
+		if (totalReplicas !== 1) {
+			throw new Error("Stateful services can only have exactly 1 replica");
+		}
+
+		const serverIds = placements.map((p) => p.serverId);
+		if (serverIds.length !== 1) {
+			throw new Error(
+				"Stateful services must be deployed to exactly one server",
+			);
+		}
+
+		const targetServerId = serverIds[0];
+		if (service.lockedServerId && service.lockedServerId !== targetServerId) {
+			if (service.migrationStatus) {
+				throw new Error("Migration already in progress");
+			}
+			await startMigrationInternal(serviceId, targetServerId);
+			revalidatePath(`/dashboard/projects`);
+			return { migrationStarted: true };
+		}
+	}
+
+	const rolloutId = randomUUID();
+
+	await db.insert(rollouts).values({
+		id: rolloutId,
+		serviceId,
+		status: "in_progress",
+		currentStage: "queued",
+	});
+
+	await inngest.send(
+		inngestEvents.rolloutCreated.create({
+			rolloutId,
+			serviceId,
+		}),
+	);
+
+	return { rolloutId };
+}
diff --git a/web/lib/deployment-status.ts b/web/lib/deployment-status.ts
index 4e95753..a1aa2cd 100644
--- a/web/lib/deployment-status.ts
+++ b/web/lib/deployment-status.ts
@@ -13,7 +13,7 @@ type DeploymentStatusCapabilities = {
 	dns: boolean;
 };
 
-export const deploymentStatusCapabilities = {
+const deploymentStatusCapabilities = {
 	pending: { expected: true, routable: false, dns: false },
 	pulling: { expected: true, routable: false, dns: false },
 	starting: { expected: true, routable: false, dns: false },
diff --git a/web/lib/email/index.ts b/web/lib/email/index.ts
index 1f29288..a918401 100644
--- a/web/lib/email/index.ts
+++ b/web/lib/email/index.ts
@@ -10,11 +10,11 @@ import { formatDateTime } from "@/lib/date";
 import type { SmtpConfig } from "@/lib/settings-keys";
 import { Alert } from "./templates/alert";
 
-export function getAppBaseUrl(): string | undefined {
+function getAppBaseUrl(): string | undefined {
 	return process.env.APP_URL;
 }
 
-export function createTransporter(config: SmtpConfig): Transporter {
+function createTransporter(config: SmtpConfig): Transporter {
 	const secure = config.encryption === "tls";
 	const requireTLS = config.encryption === "starttls";
 
@@ -33,23 +33,13 @@ export function createTransporter(config: SmtpConfig): Transporter {
 	});
 }
 
-export async function verifyConnection(config: SmtpConfig): Promise<boolean> {
-	const transporter = createTransporter(config);
-	try {
-		await transporter.verify();
-		return true;
-	} finally {
-		transporter.close();
-	}
-}
-
 type SendEmailOptions = {
 	to: string;
 	subject: string;
 	template: ReactElement;
 };
 
-export async function sendEmail(
+async function sendEmail(
 	config: SmtpConfig,
 	options: SendEmailOptions,
 ): Promise<void> {
@@ -81,7 +71,7 @@ type AlertOptions = {
 	template: ReactElement;
 };
 
-export async function sendAlert(options: AlertOptions): Promise<void> {
+async function sendAlert(options: AlertOptions): Promise<void> {
 	const config = getSmtpConfig();
 
 	if (!config?.enabled || !config.alertEmails) {
diff --git a/web/lib/inngest/functions/build-workflow.ts b/web/lib/inngest/functions/build-workflow.ts
index e9129d9..d9c1ec4 100644
--- a/web/lib/inngest/functions/build-workflow.ts
+++ b/web/lib/inngest/functions/build-workflow.ts
@@ -1,7 +1,7 @@
 import { and, eq, isNull } from "drizzle-orm";
-import { deployService } from "@/actions/projects";
 import { db } from "@/db";
 import { builds, serviceReplicas, services } from "@/db/schema";
+import { deployServiceInternal } from "@/lib/deploy-service";
 import { inngest } from "../client";
 import { inngestEvents } from "../events";
 
@@ -69,7 +69,7 @@ export const buildWorkflow = inngest.createFunction(
 
 			if (shouldDeploy) {
 				await step.run("trigger-deploy", async () => {
-					await deployService(serviceId);
+					await deployServiceInternal(serviceId);
 				});
 			}
 
@@ -145,7 +145,7 @@ export const buildWorkflow = inngest.createFunction(
 
 		if (shouldDeploy) {
 			await step.run("trigger-deploy-group", async () => {
-				await deployService(serviceId);
+				await deployServiceInternal(serviceId);
 			});
 		}
 
diff --git a/web/lib/inngest/functions/migration-workflow.ts b/web/lib/inngest/functions/migration-workflow.ts
index 0f2a8c4..bb66e71 100644
--- a/web/lib/inngest/functions/migration-workflow.ts
+++ b/web/lib/inngest/functions/migration-workflow.ts
@@ -1,6 +1,5 @@
 import { randomUUID } from "node:crypto";
 import { and, eq } from "drizzle-orm";
-import { deployService } from "@/actions/projects";
 import { db } from "@/db";
 import { getBackupStorageConfig } from "@/db/queries";
 import {
@@ -9,6 +8,7 @@ import {
 	services,
 	volumeBackups,
 } from "@/db/schema";
+import { deployServiceInternal } from "@/lib/deploy-service";
 import { markDeploymentUndesired } from "@/lib/deployment-status";
 import { enqueueWork } from "@/lib/work-queue";
 import { inngest } from "../client";
@@ -327,7 +327,7 @@ export const migrationWorkflow = inngest.createFunction(
 				.set({ lockedServerId: targetServerId })
 				.where(eq(services.id, serviceId));
 
-			await deployService(serviceId);
+			await deployServiceInternal(serviceId);
 		});
 
 		await step.run("complete-migration", async () => {
diff --git a/web/lib/inngest/functions/service-deletion-workflow.ts b/web/lib/inngest/functions/service-deletion-workflow.ts
index c3e40b2..d13911a 100644
--- a/web/lib/inngest/functions/service-deletion-workflow.ts
+++ b/web/lib/inngest/functions/service-deletion-workflow.ts
@@ -2,7 +2,6 @@ import { randomUUID } from "node:crypto";
 import { and, eq, inArray, isNotNull, isNull, lte, or } from "drizzle-orm";
 import { cron } from "inngest";
 import { deleteBackup } from "@/actions/backups";
-import { deployService } from "@/actions/projects";
 import { db } from "@/db";
 import { getBackupStorageConfig } from "@/db/queries";
 import {
@@ -13,6 +12,7 @@ import {
 	serviceVolumes,
 	volumeBackups,
 } from "@/db/schema";
+import { deployServiceInternal } from "@/lib/deploy-service";
 import { markDeploymentUndesired } from "@/lib/deployment-status";
 import { enqueueWork } from "@/lib/work-queue";
 import { inngest } from "../client";
@@ -432,7 +432,7 @@ export const serviceRestoreWorkflow = inngest.createFunction(
 						.where(eq(services.id, serviceId));
 
 					try {
-						const result = await deployService(serviceId);
+						const result = await deployServiceInternal(serviceId);
 						if (!("rolloutId" in result) || !result.rolloutId) {
 							throw new Error("Restore could not start a deployment");
 						}
diff --git a/web/lib/migrations.ts b/web/lib/migrations.ts
new file mode 100644
index 0000000..3d041c0
--- /dev/null
+++ b/web/lib/migrations.ts
@@ -0,0 +1,95 @@
+import { and, eq } from "drizzle-orm";
+import { db } from "@/db";
+import { getBackupStorageConfig } from "@/db/queries";
+import { deployments, services, serviceVolumes } from "@/db/schema";
+import { inngest } from "@/lib/inngest/client";
+import { inngestEvents } from "@/lib/inngest/events";
+
+export async function startMigrationInternal(
+	serviceId: string,
+	targetServerId: string,
+) {
+	const storageConfig = await getBackupStorageConfig();
+	if (!storageConfig) {
+		throw new Error(
+			"Backup storage not configured. Configure it in Settings first.",
+		);
+	}
+
+	const service = await db
+		.select()
+		.from(services)
+		.where(eq(services.id, serviceId))
+		.then((r) => r[0]);
+
+	if (!service) {
+		throw new Error("Service not found");
+	}
+
+	if (!service.stateful) {
+		throw new Error("Only stateful services can be migrated");
+	}
+
+	if (service.migrationStatus) {
+		throw new Error("Migration already in progress");
+	}
+
+	const volumes = await db
+		.select()
+		.from(serviceVolumes)
+		.where(eq(serviceVolumes.serviceId, serviceId));
+
+	if (volumes.length === 0) {
+		throw new Error("No volumes found for this service");
+	}
+
+	const deployment = await db
+		.select({
+			id: deployments.id,
+			serverId: deployments.serverId,
+			containerId: deployments.containerId,
+		})
+		.from(deployments)
+		.where(
+			and(
+				eq(deployments.serviceId, serviceId),
+				eq(deployments.status, "running"),
+			),
+		)
+		.then((r) => r[0]);
+
+	if (!deployment?.serverId) {
+		throw new Error("No running deployment found");
+	}
+
+	if (!deployment.containerId) {
+		throw new Error("Deployment is missing container ID");
+	}
+
+	if (deployment.serverId === targetServerId) {
+		throw new Error("Service is already running on the target server");
+	}
+
+	await db
+		.update(services)
+		.set({
+			migrationStatus: "backing_up",
+			migrationTargetServerId: targetServerId,
+			migrationBackupId: null,
+			migrationError: null,
+		})
+		.where(eq(services.id, serviceId));
+
+	await inngest.send(
+		inngestEvents.migrationStarted.create({
+			serviceId,
+			targetServerId,
+			sourceServerId: deployment.serverId,
+			sourceDeploymentId: deployment.id,
+			sourceContainerId: deployment.containerId,
+			volumes: volumes.map((v) => ({ id: v.id, name: v.name })),
+		}),
+	);
+
+	return { success: true };
+}
diff --git a/web/lib/s3.ts b/web/lib/s3.ts
index 1c289c3..bf0ba75 100644
--- a/web/lib/s3.ts
+++ b/web/lib/s3.ts
@@ -14,7 +14,7 @@ function hashConfig(config: {
 	return `${config.region}-${config.endpoint}-${config.accessKey}`;
 }
 
-export async function getS3Client(): Promise<S3Client | null> {
+async function getS3Client(): Promise<S3Client | null> {
 	const config = await getBackupStorageConfig();
 	if (!config) {
 		return null;
diff --git a/web/lib/scheduler.ts b/web/lib/scheduler.ts
index 89527b6..d157c19 100644
--- a/web/lib/scheduler.ts
+++ b/web/lib/scheduler.ts
@@ -1,7 +1,6 @@
 import { CronExpressionParser } from "cron-parser";
 import { and, eq, inArray, isNotNull, isNull, lt, ne, sql } from "drizzle-orm";
 import { triggerBuild } from "@/actions/builds";
-import { deployService } from "@/actions/projects";
 import { db } from "@/db";
 import {
 	deployments,
@@ -10,6 +9,7 @@ import {
 	services,
 	workQueue,
 } from "@/db/schema";
+import { deployServiceInternal } from "@/lib/deploy-service";
 import {
 	sendManualRecoveryRequiredAlert,
 	sendServerOfflineAlert,
@@ -21,7 +21,7 @@ import {
 
 const STALE_THRESHOLD_MS = 120_000; // 2 minutes
 
-export async function triggerRecoveryForOfflineServers(
+async function triggerRecoveryForOfflineServers(
 	offlineServerIds: string[],
 ): Promise<void> {
 	if (offlineServerIds.length === 0) return;
@@ -216,7 +216,7 @@ export async function checkAndRunScheduledDeployments(): Promise<void> {
 			if (service.sourceType === "github") {
 				await triggerBuild(service.id, "scheduled");
 			} else {
-				await deployService(service.id);
+				await deployServiceInternal(service.id);
 			}
 
 			console.log(
diff --git a/web/lib/schemas.ts b/web/lib/schemas.ts
index f82cbcd..c4db42e 100644
--- a/web/lib/schemas.ts
+++ b/web/lib/schemas.ts
@@ -1,5 +1,4 @@
 import { z } from "zod";
-import cronstrue from "cronstrue";
 
 export const nameSchema = z
 	.string()
@@ -8,18 +7,6 @@ export const nameSchema = z
 	.transform((val) => val.trim())
 	.refine((val) => val.length > 0, "Name cannot be empty");
 
-export const slugSchema = z
-	.string()
-	.min(1, "Slug is required")
-	.transform((val) => val.toLowerCase().replace(/[^a-z0-9-]/g, "-"))
-	.refine((val) => val.length > 0, "Invalid slug");
-
-export const replicaCountSchema = z
-	.number()
-	.int("Replicas must be a whole number")
-	.min(1, "Replicas must be at least 1")
-	.max(10, "Replicas cannot exceed 10");
-
 export const volumeNameSchema = z
 	.string()
 	.min(1, "Volume name is required")
@@ -44,24 +31,7 @@ export const githubRepoUrlSchema = z
 		"Repository URL must be a GitHub URL (https://github.com/...)",
 	);
 
-export const cronScheduleSchema = z
-	.string()
-	.nullable()
-	.refine((val) => {
-		if (!val) return true;
-		try {
-			cronstrue.toString(val);
-			return true;
-		} catch {
-			return false;
-		}
-	}, "Invalid cron expression");
-
-export const envVarKeySchema = z
-	.string()
-	.regex(/^[A-Z_][A-Z0-9_]*$/, "Invalid environment variable key");
-
-export const secretItemSchema = z.object({
+const secretItemSchema = z.object({
 	key: z.string().min(1, "Key is required"),
 	value: z.string().min(1, "Value is required"),
 });
diff --git a/web/lib/settings-keys.ts b/web/lib/settings-keys.ts
index 6fda3c3..eccabcd 100644
--- a/web/lib/settings-keys.ts
+++ b/web/lib/settings-keys.ts
@@ -10,8 +10,6 @@ export const SETTING_KEYS = {
 
 export const DEFAULT_BUILD_TIMEOUT_MINUTES = 30;
 export const DEFAULT_BACKUP_RETENTION_DAYS = 7;
-export const MIN_BACKUP_RETENTION_DAYS = 7;
-export const MAX_BACKUP_RETENTION_DAYS = 30;
 
 export type BackupStorageProvider = "s3" | "r2" | "gcs" | "custom";
 
@@ -44,7 +42,7 @@ const commaSeparatedEmails = z
 		{ message: "Invalid email address in list" },
 	);
 
-export const smtpConfigSchema = z.object({
+const smtpConfigSchema = z.object({
 	enabled: z.boolean(),
 	fromName: z.string().transform((val) => val.trim()),
 	fromAddress: z
diff --git a/web/package.json b/web/package.json
index dbccf6e..638ba82 100644
--- a/web/package.json
+++ b/web/package.json
@@ -22,7 +22,6 @@
     "better-auth": "^1.4.9",
     "class-variance-authority": "^0.7.1",
     "clsx": "^2.1.1",
-    "cmdk": "^1.1.1",
     "cron-parser": "^5.4.0",
     "cronstrue": "^3.9.0",
     "drizzle-orm": "^0.45.1",
diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml
index bd82b55..1af7703 100644
--- a/web/pnpm-lock.yaml
+++ b/web/pnpm-lock.yaml
@@ -42,9 +42,6 @@ importers:
       clsx:
         specifier: ^2.1.1
         version: 2.1.1
-      cmdk:
-        specifier: ^1.1.1
-        version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
       cron-parser:
         specifier: ^5.4.0
         version: 5.5.0
@@ -2059,177 +2056,6 @@ packages:
   '@protobufjs/utf8@1.1.1':
     resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==}
 
-  '@radix-ui/primitive@1.1.4':
-    resolution: {integrity: sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ==}
-
-  '@radix-ui/react-compose-refs@1.1.3':
-    resolution: {integrity: sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  '@radix-ui/react-context@1.1.4':
-    resolution: {integrity: sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  '@radix-ui/react-dialog@1.1.17':
-    resolution: {integrity: sha512-TDTYmpdq8dI2+Xgvgj9AJ8Ghqq+Eph/TRVEdaFQPDItIY+6QSkU7MJMeevw1568Yw/2Ijz8BTphPSP2XejKphw==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-      '@types/react-dom':
-        optional: true
-
-  '@radix-ui/react-dismissable-layer@1.1.13':
-    resolution: {integrity: sha512-2v+zNAWWe0ySxgC0D0yeXMPQ23xZVgXZTerTz+JKlmdRj6gfTqmCcR29jb6d290DezXPGgruHWDX/vYUebtErg==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-      '@types/react-dom':
-        optional: true
-
-  '@radix-ui/react-focus-guards@1.1.4':
-    resolution: {integrity: sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  '@radix-ui/react-focus-scope@1.1.10':
-    resolution: {integrity: sha512-Fas/lXQqhVvqwAb64s5RFeHiHYElZ6SUQbZaNd6EkfhP/Al7wTIQ9WIR4QVX475tlu5yFCEdDcJH6/UwsZjMWw==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-      '@types/react-dom':
-        optional: true
-
-  '@radix-ui/react-id@1.1.2':
-    resolution: {integrity: sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  '@radix-ui/react-portal@1.1.12':
-    resolution: {integrity: sha512-m309havGzsjLHHaIX50G5PlvRs3xkgPCsGk/5PTvYm8D5q33yG0J7w/712PTOhid7NTaFETtnSXjngHQavvhVw==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-      '@types/react-dom':
-        optional: true
-
-  '@radix-ui/react-presence@1.1.6':
-    resolution: {integrity: sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-      '@types/react-dom':
-        optional: true
-
-  '@radix-ui/react-primitive@2.1.6':
-    resolution: {integrity: sha512-wetd0QI77DbvrPpTAvH1SqOxsYF2wZe5TNxqwOd5Ty4XDpV3dpV0s8K/1MGMJBeY5o7lg8ub5VIt1Ub+yVen6g==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-      '@types/react-dom':
-        optional: true
-
-  '@radix-ui/react-slot@1.3.0':
-    resolution: {integrity: sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  '@radix-ui/react-use-callback-ref@1.1.2':
-    resolution: {integrity: sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  '@radix-ui/react-use-controllable-state@1.2.3':
-    resolution: {integrity: sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  '@radix-ui/react-use-effect-event@0.0.3':
-    resolution: {integrity: sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  '@radix-ui/react-use-escape-keydown@1.1.2':
-    resolution: {integrity: sha512-2uVLvLjgO7NZCWw01/FdqRwmA42J0BcjPMUCA+koFEOAb+zjqIP7SiFz/7zWPrKnVmSqr76Omq2ALyCuX4dhLw==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  '@radix-ui/react-use-layout-effect@1.1.2':
-    resolution: {integrity: sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
   '@react-email/body@0.3.0':
     resolution: {integrity: sha512-uGo0BOOzjbMUo3lu+BIDWayvn5o6Xyfmnlla5VGf05n8gHMvO1ll7U4FtzWe3hxMLwt53pmc4iE0M+B5slG+Ug==}
     engines: {node: '>=20.0.0'}
@@ -3049,10 +2875,6 @@ packages:
   argparse@2.0.1:
     resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
 
-  aria-hidden@1.2.6:
-    resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
-    engines: {node: '>=10'}
-
   aria-query@5.3.2:
     resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
     engines: {node: '>= 0.4'}
@@ -3318,12 +3140,6 @@ packages:
     resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
     engines: {node: '>=6'}
 
-  cmdk@1.1.1:
-    resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==}
-    peerDependencies:
-      react: ^18 || ^19 || ^19.0.0-rc
-      react-dom: ^18 || ^19 || ^19.0.0-rc
-
   code-block-writer@13.0.3:
     resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==}
 
@@ -3514,9 +3330,6 @@ packages:
     resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
     engines: {node: '>=8'}
 
-  detect-node-es@1.1.0:
-    resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
-
   diff@8.0.4:
     resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==}
     engines: {node: '>=0.3.1'}
@@ -4093,10 +3906,6 @@ packages:
     resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
     engines: {node: '>= 0.4'}
 
-  get-nonce@1.0.1:
-    resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
-    engines: {node: '>=6'}
-
   get-own-enumerable-keys@1.0.0:
     resolution: {integrity: sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==}
     engines: {node: '>=14.16'}
@@ -5261,36 +5070,6 @@ packages:
   react-is@16.13.1:
     resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
 
-  react-remove-scroll-bar@2.3.8:
-    resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
-    engines: {node: '>=10'}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  react-remove-scroll@2.7.2:
-    resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==}
-    engines: {node: '>=10'}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  react-style-singleton@2.2.3:
-    resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
-    engines: {node: '>=10'}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
   react@19.2.7:
     resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==}
     engines: {node: '>=0.10.0'}
@@ -5807,26 +5586,6 @@ packages:
   uri-js@4.4.1:
     resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
 
-  use-callback-ref@1.3.3:
-    resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
-    engines: {node: '>=10'}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
-  use-sidecar@1.1.3:
-    resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
-    engines: {node: '>=10'}
-    peerDependencies:
-      '@types/react': 19.2.17
-      react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
-    peerDependenciesMeta:
-      '@types/react':
-        optional: true
-
   use-sync-external-store@1.6.0:
     resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==}
     peerDependencies:
@@ -8080,148 +7839,6 @@ snapshots:
 
   '@protobufjs/utf8@1.1.1': {}
 
-  '@radix-ui/primitive@1.1.4': {}
-
-  '@radix-ui/react-compose-refs@1.1.3(@types/react@19.2.17)(react@19.2.7)':
-    dependencies:
-      react: 19.2.7
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  '@radix-ui/react-context@1.1.4(@types/react@19.2.17)(react@19.2.7)':
-    dependencies:
-      react: 19.2.7
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  '@radix-ui/react-dialog@1.1.17(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
-    dependencies:
-      '@radix-ui/primitive': 1.1.4
-      '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-context': 1.1.4(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-dismissable-layer': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
-      '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-focus-scope': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
-      '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-portal': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
-      '@radix-ui/react-presence': 1.1.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
-      '@radix-ui/react-primitive': 2.1.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
-      '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7)
-      aria-hidden: 1.2.6
-      react: 19.2.7
-      react-dom: 19.2.7(react@19.2.7)
-      react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7)
-    optionalDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3(@types/react@19.2.17)
-
-  '@radix-ui/react-dismissable-layer@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
-    dependencies:
-      '@radix-ui/primitive': 1.1.4
-      '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-primitive': 2.1.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
-      '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-use-escape-keydown': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      react: 19.2.7
-      react-dom: 19.2.7(react@19.2.7)
-    optionalDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3(@types/react@19.2.17)
-
-  '@radix-ui/react-focus-guards@1.1.4(@types/react@19.2.17)(react@19.2.7)':
-    dependencies:
-      react: 19.2.7
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  '@radix-ui/react-focus-scope@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
-    dependencies:
-      '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-primitive': 2.1.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
-      '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      react: 19.2.7
-      react-dom: 19.2.7(react@19.2.7)
-    optionalDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3(@types/react@19.2.17)
-
-  '@radix-ui/react-id@1.1.2(@types/react@19.2.17)(react@19.2.7)':
-    dependencies:
-      '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      react: 19.2.7
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  '@radix-ui/react-portal@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
-    dependencies:
-      '@radix-ui/react-primitive': 2.1.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
-      '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      react: 19.2.7
-      react-dom: 19.2.7(react@19.2.7)
-    optionalDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3(@types/react@19.2.17)
-
-  '@radix-ui/react-presence@1.1.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
-    dependencies:
-      '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      react: 19.2.7
-      react-dom: 19.2.7(react@19.2.7)
-    optionalDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3(@types/react@19.2.17)
-
-  '@radix-ui/react-primitive@2.1.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
-    dependencies:
-      '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7)
-      react: 19.2.7
-      react-dom: 19.2.7(react@19.2.7)
-    optionalDependencies:
-      '@types/react': 19.2.17
-      '@types/react-dom': 19.2.3(@types/react@19.2.17)
-
-  '@radix-ui/react-slot@1.3.0(@types/react@19.2.17)(react@19.2.7)':
-    dependencies:
-      '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7)
-      react: 19.2.7
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  '@radix-ui/react-use-callback-ref@1.1.2(@types/react@19.2.17)(react@19.2.7)':
-    dependencies:
-      react: 19.2.7
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  '@radix-ui/react-use-controllable-state@1.2.3(@types/react@19.2.17)(react@19.2.7)':
-    dependencies:
-      '@radix-ui/react-use-effect-event': 0.0.3(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      react: 19.2.7
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  '@radix-ui/react-use-effect-event@0.0.3(@types/react@19.2.17)(react@19.2.7)':
-    dependencies:
-      '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      react: 19.2.7
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  '@radix-ui/react-use-escape-keydown@1.1.2(@types/react@19.2.17)(react@19.2.7)':
-    dependencies:
-      '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      react: 19.2.7
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  '@radix-ui/react-use-layout-effect@1.1.2(@types/react@19.2.17)(react@19.2.7)':
-    dependencies:
-      react: 19.2.7
-    optionalDependencies:
-      '@types/react': 19.2.17
-
   '@react-email/body@0.3.0(react@19.2.7)':
     dependencies:
       react: 19.2.7
@@ -8933,10 +8550,6 @@ snapshots:
 
   argparse@2.0.1: {}
 
-  aria-hidden@1.2.6:
-    dependencies:
-      tslib: 2.8.1
-
   aria-query@5.3.2: {}
 
   array-buffer-byte-length@1.0.2:
@@ -9199,18 +8812,6 @@ snapshots:
 
   clsx@2.1.1: {}
 
-  cmdk@1.1.1(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
-    dependencies:
-      '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-dialog': 1.1.17(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
-      '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7)
-      '@radix-ui/react-primitive': 2.1.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
-      react: 19.2.7
-      react-dom: 19.2.7(react@19.2.7)
-    transitivePeerDependencies:
-      - '@types/react'
-      - '@types/react-dom'
-
   code-block-writer@13.0.3: {}
 
   color-convert@2.0.1:
@@ -9365,8 +8966,6 @@ snapshots:
 
   detect-libc@2.1.2: {}
 
-  detect-node-es@1.1.0: {}
-
   diff@8.0.4: {}
 
   doctrine@2.1.0:
@@ -10141,8 +9740,6 @@ snapshots:
       hasown: 2.0.4
       math-intrinsics: 1.1.0
 
-  get-nonce@1.0.1: {}
-
   get-own-enumerable-keys@1.0.0: {}
 
   get-proto@1.0.1:
@@ -11198,33 +10795,6 @@ snapshots:
 
   react-is@16.13.1: {}
 
-  react-remove-scroll-bar@2.3.8(@types/react@19.2.17)(react@19.2.7):
-    dependencies:
-      react: 19.2.7
-      react-style-singleton: 2.2.3(@types/react@19.2.17)(react@19.2.7)
-      tslib: 2.8.1
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  react-remove-scroll@2.7.2(@types/react@19.2.17)(react@19.2.7):
-    dependencies:
-      react: 19.2.7
-      react-remove-scroll-bar: 2.3.8(@types/react@19.2.17)(react@19.2.7)
-      react-style-singleton: 2.2.3(@types/react@19.2.17)(react@19.2.7)
-      tslib: 2.8.1
-      use-callback-ref: 1.3.3(@types/react@19.2.17)(react@19.2.7)
-      use-sidecar: 1.1.3(@types/react@19.2.17)(react@19.2.7)
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  react-style-singleton@2.2.3(@types/react@19.2.17)(react@19.2.7):
-    dependencies:
-      get-nonce: 1.0.1
-      react: 19.2.7
-      tslib: 2.8.1
-    optionalDependencies:
-      '@types/react': 19.2.17
-
   react@19.2.7: {}
 
   recast@0.23.11:
@@ -11904,21 +11474,6 @@ snapshots:
     dependencies:
       punycode: 2.3.1
 
-  use-callback-ref@1.3.3(@types/react@19.2.17)(react@19.2.7):
-    dependencies:
-      react: 19.2.7
-      tslib: 2.8.1
-    optionalDependencies:
-      '@types/react': 19.2.17
-
-  use-sidecar@1.1.3(@types/react@19.2.17)(react@19.2.7):
-    dependencies:
-      detect-node-es: 1.1.0
-      react: 19.2.7
-      tslib: 2.8.1
-    optionalDependencies:
-      '@types/react': 19.2.17
-
   use-sync-external-store@1.6.0(react@19.2.7):
     dependencies:
       react: 19.2.7
