@@ -662,7 +662,7 @@ function ProjectsListPage() {
)}
setAbsoluteConfigFilePath(event.target.value)}
/>
diff --git a/apps/dashboard/src/app/(main)/(protected)/layout-client.tsx b/apps/dashboard/src/app/(main)/(protected)/layout-client.tsx
index 45d6c815f..1120c68d2 100644
--- a/apps/dashboard/src/app/(main)/(protected)/layout-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/layout-client.tsx
@@ -2,7 +2,7 @@
import Loading from "@/app/loading";
import { CursorBlastEffect } from "@hexclave/dashboard-ui-components";
-import { ConfigUpdateDialogProvider } from "@/lib/config-update";
+import { ConfigUpdateDialogProvider } from "@/components/config-update";
import { HexclaveRebrandModal } from "@/components/hexclave-rebrand-modal";
import { getPublicEnvVar } from '@/lib/env';
import { useStackApp, useUser } from "@hexclave/next";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/@modal/(.)apps/[appId]/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/@modal/(.)apps/[appId]/page-client.tsx
index e381e7f81..bffba0ae8 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/@modal/(.)apps/[appId]/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/@modal/(.)apps/[appId]/page-client.tsx
@@ -6,7 +6,7 @@ import { useRouter } from "@/components/router";
import { Dialog, DialogContent, DialogTitle } from "@/components/ui";
import { ALL_APPS_FRONTEND, getAppPath } from "@/lib/apps-frontend";
import { isAppEnabled } from "@/lib/apps-utils";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { AppId, getParentAppId } from "@hexclave/shared/dist/apps/apps-config";
import { usePathname } from "next/navigation";
import { useEffect, useState } from "react";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/queries/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/queries/page-client.tsx
index 220778d1e..a447d45a8 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/queries/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/queries/page-client.tsx
@@ -13,7 +13,7 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { SimpleTooltip } from "@/components/ui/simple-tooltip";
import { Textarea } from "@/components/ui/textarea";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { cn } from "@/lib/utils";
import {
CaretDownIcon,
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/ai-query-dialog.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/ai-query-dialog.tsx
index bc2668c25..6273cc4ee 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/ai-query-dialog.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/ai-query-dialog.tsx
@@ -18,7 +18,7 @@ import { Label } from "@/components/ui/label";
import { SimpleTooltip } from "@/components/ui/simple-tooltip";
import { Textarea } from "@/components/ui/textarea";
import { CreateDashboardPreview } from "@/components/commands/create-dashboard/create-dashboard-preview";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { AssistantRuntimeProvider, type ToolCallContentPartProps } from "@assistant-ui/react";
import {
ArrowClockwiseIcon,
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page-client.tsx
index fa1d5854d..30276a43f 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page-client.tsx
@@ -7,7 +7,7 @@ import {
type DesignEditableGridItem,
} from "@/components/design-components";
import { Switch } from "@/components/ui";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { GearSix, KeyIcon, UsersIcon } from "@phosphor-icons/react";
import { useMemo, useState } from "react";
import { AppEnabledGuard } from "../app-enabled-guard";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/apps/[appId]/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/apps/[appId]/page-client.tsx
index 9f08249da..2e7ea9f01 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/apps/[appId]/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/apps/[appId]/page-client.tsx
@@ -3,7 +3,7 @@
import { useAdminApp } from "@/app/(main)/(protected)/projects/[projectId]/use-admin-app";
import { AppStoreEntry } from "@/components/app-store-entry";
import { useRouter } from "@/components/router";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { ALL_APPS_FRONTEND, getAppPath, getDocumentationHref, type AppId } from "@/lib/apps-frontend";
import { isAppEnabled } from "@/lib/apps-utils";
import { getParentAppId } from "@hexclave/shared/dist/apps/apps-config";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/auth-methods/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/auth-methods/page-client.tsx
index c19338952..b899bd227 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/auth-methods/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/auth-methods/page-client.tsx
@@ -3,7 +3,7 @@
import { InlineSaveDiscard } from "@/components/inline-save-discard";
import { ActionDialog, BrandIcons, BrowserFrame, FormControl, FormField, FormItem, FormLabel, FormMessage, InlineCode, Label, SimpleTooltip, Switch, Typography } from "@/components/ui";
import { FormDialog } from "@/components/form-dialog";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { useDashboardInternalUser } from "@/lib/dashboard-user";
import {
DesignAlert,
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/dashboards/[dashboardId]/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/dashboards/[dashboardId]/page-client.tsx
index 2cfe5f5c5..1f73b4b18 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/dashboards/[dashboardId]/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/dashboards/[dashboardId]/page-client.tsx
@@ -15,7 +15,7 @@ import {
type AssistantComposerApi,
} from "@/components/vibe-coding";
import { ToolCallContent } from "@/components/vibe-coding/chat-adapters";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { useDashboardUser } from "@/lib/dashboard-user";
import { cn } from "@/lib/utils";
import {
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/dashboards/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/dashboards/page-client.tsx
index a140b820e..180e44069 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/dashboards/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/dashboards/page-client.tsx
@@ -6,7 +6,7 @@ import { InputField } from "@/components/form-fields";
import { useRouter } from "@/components/router";
import { ActionDialog, Button, Typography } from "@/components/ui";
import { getShortcutModifierKeyLabel } from "@/lib/keyboard-shortcuts";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import {
ChartBarIcon,
PlusIcon,
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/[storeId]/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/[storeId]/page-client.tsx
index 0b744d263..00f88aabb 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/[storeId]/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/[storeId]/page-client.tsx
@@ -10,7 +10,7 @@ import {
type DesignEditableGridItem,
} from "@/components/design-components";
import { ActionDialog, Label, toast } from "@/components/ui";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { ArrowLeftIcon, CopyIcon, DatabaseIcon, HashIcon, TagIcon, TrashIcon } from "@phosphor-icons/react";
import { deindent } from "@hexclave/shared/dist/utils/strings";
import { useMemo, useState } from "react";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/page-client.tsx
index e7c910cf7..a2f5d87ea 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/page-client.tsx
@@ -6,7 +6,7 @@ import {
DesignListItemRow,
} from "@/components/design-components";
import { ActionDialog, Label, toast } from "@/components/ui";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { DatabaseIcon, PlusIcon } from "@phosphor-icons/react";
import { getUserSpecifiedIdErrorMessage, isValidUserSpecifiedId, sanitizeUserSpecifiedId } from "@hexclave/shared/dist/schema-fields";
import { typedEntries } from "@hexclave/shared/dist/utils/objects";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/domains/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/domains/page-client.tsx
index 6d1f253cc..4d164d264 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/domains/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/domains/page-client.tsx
@@ -5,7 +5,7 @@ import { InlineSaveDiscard } from "@/components/inline-save-discard";
import { DesignAlert } from "@/components/design-components";
import { SettingCard, SettingSwitch } from "@/components/settings";
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActionCell, ActionDialog, Alert, Button, Typography } from "@/components/ui";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { DataGrid, useDataGridUrlState, useDataSource, type DataGridColumnDef } from "@hexclave/dashboard-ui-components";
import { yupString } from "@hexclave/shared/dist/schema-fields";
import { HexclaveAssertionError } from "@hexclave/shared/dist/utils/errors";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx
index 3e508f1c5..fb84e9cff 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx
@@ -8,7 +8,7 @@ import {
DesignCard,
DesignInput,
} from "@/components/design-components";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { getPublicEnvVar } from "@/lib/env";
import { cn } from "@/lib/utils";
import { AdminEmailConfig } from "@hexclave/next";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-themes/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-themes/page-client.tsx
index bcb2f2ab0..4b5cdff2a 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-themes/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-themes/page-client.tsx
@@ -5,7 +5,7 @@ import { FormDialog } from "@/components/form-dialog";
import { InputField } from "@/components/form-fields";
import { useRouter } from "@/components/router";
import { ActionDialog, Alert, AlertDescription, AlertTitle, Button, Typography } from "@/components/ui";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { cn } from "@/lib/utils";
import { CheckIcon, DeviceMobile, DeviceTablet, Monitor, Palette, Plus, Trash } from "@phosphor-icons/react";
import { DEFAULT_EMAIL_THEMES, DEFAULT_EMAIL_THEME_ID, previewTemplateSource } from "@hexclave/shared/dist/helpers/emails";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/emails/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/emails/page-client.tsx
index 6646149cc..3ab184448 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/emails/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/emails/page-client.tsx
@@ -5,7 +5,7 @@ import { FormDialog } from "@/components/form-dialog";
import { InputField, SelectField, TextAreaField } from "@/components/form-fields";
import { ActionDialog, Alert, AlertDescription, AlertTitle, Button, SimpleTooltip, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Typography, useToast } from "@/components/ui";
import { useRouter } from "@/components/router";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { getPublicEnvVar } from "@/lib/env";
import { ArrowSquareOut, CheckCircle, Envelope, HardDrive, Sliders, WarningCircleIcon, XCircle, XIcon } from "@phosphor-icons/react";
import { AdminEmailConfig, AdminProject, AdminSentEmail, ServerUser, UserAvatar } from "@hexclave/next";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/onboarding/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/onboarding/page-client.tsx
index 55604f032..3773cee0f 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/onboarding/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/onboarding/page-client.tsx
@@ -8,7 +8,7 @@ import {
DesignDialogClose,
} from "@/components/design-components";
import { Typography } from "@/components/ui";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { WarningCircle } from "@phosphor-icons/react";
import type { RestrictedReason } from "@hexclave/shared/dist/schema-fields";
import { runAsynchronouslyWithAlert } from "@hexclave/shared/dist/utils/promises";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/layout.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/layout.tsx
index 7b141cde8..5ac62d532 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/layout.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/layout.tsx
@@ -5,7 +5,7 @@ import { SelectField } from "@/components/form-fields";
import { Link } from "@/components/link";
import { StripeConnectProvider } from "@/components/payments/stripe-connect-provider";
import { ActionDialog, Button, Card, CardContent, Typography } from "@/components/ui";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { cn } from "@/lib/utils";
import { getPublicEnvVar } from "@/lib/env";
import { ArrowRightIcon, ArrowsClockwiseIcon, ChartBarIcon, FlaskIcon, ShieldIcon, WalletIcon, WarningIcon, WebhooksLogoIcon } from "@phosphor-icons/react";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/[productId]/edit/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/[productId]/edit/page-client.tsx
index ab129901d..dd4da486d 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/[productId]/edit/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/[productId]/edit/page-client.tsx
@@ -21,7 +21,7 @@ import {
Typography,
} from "@/components/ui";
import { SubpageHeader } from "@/components/design-components/subpage-header";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { cn } from "@/lib/utils";
import { ClockIcon, HardDriveIcon, PackageIcon, PlusIcon, PuzzlePieceIcon, StackIcon, TrashIcon } from "@phosphor-icons/react";
import { CompleteConfig } from "@hexclave/shared/dist/config/schema";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/[productId]/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/[productId]/page-client.tsx
index a7aea9ec8..3070618c9 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/[productId]/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/[productId]/page-client.tsx
@@ -40,7 +40,7 @@ import {
Typography,
} from "@/components/ui";
import { createDefaultDataGridState, DataGrid, useDataGridUrlState, useDataSource, type DataGridColumnDef } from "@hexclave/dashboard-ui-components";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { ArrowLeftIcon, ClockIcon, CopyIcon, CurrencyDollarIcon, DotsThreeIcon, FolderOpenIcon, GiftIcon, HardDriveIcon, PackageIcon, PencilSimpleIcon, PlusIcon, PuzzlePieceIcon, ShoppingCartIcon, StackIcon, TagIcon, TrashIcon, UsersIcon } from "@phosphor-icons/react";
import { CreateCheckoutDialog } from "@/components/payments/create-checkout-dialog";
import type { CustomerType } from "@/components/payments/customer-selector";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/new/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/new/page-client.tsx
index 3edcee8ea..71b588a12 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/new/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/new/page-client.tsx
@@ -24,7 +24,7 @@ import {
toast,
Typography,
} from "@/components/ui";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { cn } from "@/lib/utils";
import { ArrowSquareOutIcon, BuildingOfficeIcon, CaretDownIcon, ChatIcon, ClockIcon, CodeIcon, CopyIcon, GearIcon, HardDriveIcon, LightningIcon, PlusIcon, PuzzlePieceIcon, StackIcon, TrashIcon, UserIcon } from "@phosphor-icons/react";
import { CompleteConfig } from "@hexclave/shared/dist/config/schema";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client-list-view.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client-list-view.tsx
index b4e3d216a..bfac898e7 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client-list-view.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client-list-view.tsx
@@ -5,7 +5,7 @@ import { ItemDialog } from "@/components/payments/item-dialog";
import { useRouter } from "@/components/router";
import { ActionDialog, Alert, AlertDescription, AlertTitle, Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, toast } from "@/components/ui";
import { cn } from "@/lib/utils";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { DotsThreeVerticalIcon } from "@phosphor-icons/react";
import { CompleteConfig } from "@hexclave/shared/dist/config/schema";
import { useHover } from "@hexclave/shared/dist/hooks/use-hover";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client-product-lines-view.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client-product-lines-view.tsx
index cfb86e776..a32ba4edc 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client-product-lines-view.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client-product-lines-view.tsx
@@ -26,7 +26,7 @@ import {
toast
} from "@/components/ui";
import { cn } from "@/lib/utils";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { DndContext, DragOverlay, useDraggable, useDroppable, type DragEndEvent, type DragStartEvent } from '@dnd-kit/core';
import { CaretUpDownIcon, CircleNotchIcon, CodeIcon, CopyIcon, DotsSixVerticalIcon, DotsThreeVerticalIcon, EyeIcon, FileTextIcon, HardDriveIcon, InfoIcon, PencilSimpleIcon, PlusIcon, PuzzlePieceIcon, ShoppingCartIcon, StackIcon, TrashIcon, XIcon } from "@phosphor-icons/react";
import { CreateCheckoutDialog } from "@/components/payments/create-checkout-dialog";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/page-client.tsx
index 32470f6c7..992aafb6a 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/page-client.tsx
@@ -2,7 +2,7 @@
import { Switch, Typography } from "@/components/ui";
import { DesignCard } from "@/components/design-components";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { cn } from "@/lib/utils";
import { LockIcon } from "@phosphor-icons/react";
import { runAsynchronouslyWithAlert } from "@hexclave/shared/dist/utils/promises";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/test-mode-toggle.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/test-mode-toggle.tsx
index 31fbb91e3..375e59152 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/test-mode-toggle.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/test-mode-toggle.tsx
@@ -1,7 +1,7 @@
"use client";
import { Switch, Typography } from "@/components/ui";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { cn } from "@/lib/utils";
import { DesignBadge, DesignCard } from "@/components/design-components";
import { FlaskIcon } from "@phosphor-icons/react";
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx
index e2bf5154c..fe4de87bc 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx
@@ -22,7 +22,7 @@ import {
import { WalkthroughProvider } from "@/components/walkthrough/walkthrough-provider";
import { ALL_APPS_FRONTEND, DUMMY_ORIGIN, getAppPath, getItemPath, hasNavigationItems, testAppPath, testItemPath, type NavigableAppFrontend } from "@/lib/apps-frontend";
import { getEnabledAppIds, getEnabledNavigableAppIds } from "@/lib/apps-utils";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { cn } from "@/lib/utils";
import {
CaretDownIcon,
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx
index 5213915c7..24357805d 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx
@@ -44,7 +44,7 @@ import {
visualTreeToCel,
type RuleNode,
} from "@/lib/cel-visual-parser";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { hexclaveAppInternalsSymbol } from "@/lib/hexclave-app-internals";
import { closestCenter, DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors, type DragEndEvent } from '@dnd-kit/core';
import { arrayMove, SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable';
diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-settings/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-settings/page-client.tsx
index 0c3f2983b..ae00129e5 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-settings/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-settings/page-client.tsx
@@ -8,7 +8,7 @@ import {
type DesignEditableGridItem,
} from "@/components/design-components";
import { ActionDialog, Checkbox, Switch, Typography } from "@/components/ui";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { GearSix, ShieldCheck, ShieldIcon, UserPlus, UsersIcon } from "@phosphor-icons/react";
import { typedFromEntries } from "@hexclave/shared/dist/utils/objects";
import { useCallback, useEffect, useMemo, useState } from "react";
diff --git a/apps/dashboard/src/app/globals.css b/apps/dashboard/src/app/globals.css
index a2299cc96..0c13713b2 100644
--- a/apps/dashboard/src/app/globals.css
+++ b/apps/dashboard/src/app/globals.css
@@ -475,3 +475,28 @@ body:has(.show-site-loading-indicator) .site-loading-indicator {
:where([data-pacifica-children-min-width-0] > *) {
min-width: 0;
}
+
+
+/* Config-agent commit-preview diff (Pierre `@pierre/diffs`).
+ *
+ * Pierre renders into a shadow-DOM `diffs-container`. We can't reach inside with
+ * normal selectors, but CSS custom properties inherit through the shadow
+ * boundary, so setting Pierre's documented override hooks on the light-DOM
+ * wrapper recolors the diff chrome. Syntax-token colors still come from the
+ * shiki github-light/github-dark themes (chosen via `themeType`).
+ *
+ * We only set the *base* surface/accent/number colors and let Pierre derive the
+ * row tints, emphasis, gutters and separators from them (`color-mix` over the
+ * base). The project tokens already flip between light and dark via `.dark`, so
+ * both `light-dark()` branches are pointed at the same token. */
+.config-agent-diff {
+ --diffs-light-bg: hsl(var(--background));
+ --diffs-dark-bg: hsl(var(--background));
+ --diffs-light: hsl(var(--foreground));
+ --diffs-dark: hsl(var(--foreground));
+
+ --diffs-fg-number-override: hsl(var(--muted-foreground));
+
+ --diffs-addition-color-override: hsl(var(--success));
+ --diffs-deletion-color-override: hsl(var(--destructive));
+}
diff --git a/apps/dashboard/src/components/app-square.tsx b/apps/dashboard/src/components/app-square.tsx
index ccacc6383..c71d15c89 100644
--- a/apps/dashboard/src/components/app-square.tsx
+++ b/apps/dashboard/src/components/app-square.tsx
@@ -3,7 +3,7 @@ import { useRouter } from "@/components/router";
import { Button, cn, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui";
import { ALL_APPS_FRONTEND, AppFrontend, getAppPath, getDocumentationHref } from "@/lib/apps-frontend";
import { isAppEnabled } from "@/lib/apps-utils";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { CheckIcon, DotsThreeVerticalIcon } from "@phosphor-icons/react";
import { ALL_APPS, AppId, getParentAppId } from "@hexclave/shared/dist/apps/apps-config";
import { appSquarePaddingExpression, appSquareWidthExpression, AppIcon as SharedAppIcon } from "@hexclave/shared/dist/apps/apps-ui";
diff --git a/apps/dashboard/src/components/commands/create-dashboard/create-dashboard-preview.tsx b/apps/dashboard/src/components/commands/create-dashboard/create-dashboard-preview.tsx
index d697c1701..2e1d6b649 100644
--- a/apps/dashboard/src/components/commands/create-dashboard/create-dashboard-preview.tsx
+++ b/apps/dashboard/src/components/commands/create-dashboard/create-dashboard-preview.tsx
@@ -7,7 +7,7 @@ import { useDebouncedAction } from "@/hooks/use-debounced-action";
import { createUnifiedAiTransport } from "@/components/assistant-ui/chat-stream";
import { buildDashboardMessages } from "@/lib/ai-dashboard/shared-prompt";
import type { AppId } from "@/lib/apps-frontend";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import { useDashboardUser } from "@/lib/dashboard-user";
import { getPublicEnvVar } from "@/lib/env";
import { cn } from "@/lib/utils";
diff --git a/apps/dashboard/src/components/commands/run-query.tsx b/apps/dashboard/src/components/commands/run-query.tsx
index 2806dff4c..31dfb588c 100644
--- a/apps/dashboard/src/components/commands/run-query.tsx
+++ b/apps/dashboard/src/components/commands/run-query.tsx
@@ -27,7 +27,7 @@ import { SimpleTooltip } from "@/components/ui/simple-tooltip";
import { Textarea } from "@/components/ui/textarea";
import { useDebouncedAction } from "@/hooks/use-debounced-action";
import { useFromNow } from "@/hooks/use-from-now";
-import { useUpdateConfig } from "@/lib/config-update";
+import { useUpdateConfig } from "@/components/config-update";
import {
ArrowClockwiseIcon,
CheckCircleIcon,
diff --git a/apps/dashboard/src/components/config-update/github-push-dialog.tsx b/apps/dashboard/src/components/config-update/github-push-dialog.tsx
new file mode 100644
index 000000000..4f77ef6f3
--- /dev/null
+++ b/apps/dashboard/src/components/config-update/github-push-dialog.tsx
@@ -0,0 +1,612 @@
+'use client';
+
+import { Link } from "@/components/link";
+import { DesignAlert, DesignButton, DesignDialog, DesignDialogClose } from "@/components/design-components";
+import { useDashboardInternalUser } from "@/lib/dashboard-user";
+import { ArrowsClockwise, GitBranch, GitCommit } from "@phosphor-icons/react";
+import type { OAuthConnection, StackAdminApp } from "@hexclave/next";
+import type { EnvironmentConfigOverrideOverride } from "@hexclave/shared/dist/config/schema";
+import { captureError } from "@hexclave/shared/dist/utils/errors";
+import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
+import { GITHUB_SCOPE_REQUIREMENTS } from "@/lib/github-api";
+import React, { Suspense, useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
+
+import { AgentDiffViewer, ConfigAgentPreviewProgress } from "./progress-content";
+import { currentEpochMsFromPerformance, getAdminInterface, type AgentStage, type ConfigAgentRun, type GithubPushedSource } from "./shared";
+
+type GithubPushDialogProps = {
+ open: boolean,
+ adminApp: StackAdminApp
| null,
+ source: GithubPushedSource,
+ configUpdate: EnvironmentConfigOverrideOverride | null,
+ projectId: string | undefined,
+ onSettle: (result: boolean) => void,
+};
+
+// GitHub push dialog: staged progress while the agent runs, then a diff review
+// panel; the user must click "Commit" to push.
+
+type ScopeCheck =
+ | { status: "no-account" }
+ | { status: "checking" }
+ | { status: "ok", account: OAuthConnection }
+ | { status: "missing-scopes" };
+
+// "check": verifying the GitHub account is linked with valid scopes; when the
+// check passes the run starts automatically. Also the resting state after a
+// failed run (shows the error + a manual retry).
+//
+// The remaining phases all render the SAME commit-form layout (commit message
+// input + a "Commit preview" box); only the preview box content and the footer
+// buttons differ, so the UI doesn't jump between running and review:
+// "running": agent is in flight — preview box shows the live loader; Commit is
+// disabled; Cancel stops the sandbox. The commit message can be drafted here.
+// "cancelling": user clicked Cancel, waiting for terminal status.
+// "awaiting_review": agent done, diff loaded into the preview box; Commit enabled.
+// "committing": user clicked Commit, pushing to GitHub.
+type DialogPhase = "check" | "running" | "cancelling" | "awaiting_review" | "committing";
+
+// Phases that share the commit-form layout (everything except the scope check).
+function isCommitFormPhase(phase: DialogPhase): boolean {
+ return phase === "running" || phase === "cancelling" || phase === "awaiting_review" || phase === "committing";
+}
+
+function projectSettingsHref(projectId: string | undefined): string {
+ return `/projects/${projectId}/project-settings`;
+}
+
+/**
+ * Outer shell: renders the DesignDialog synchronously; the Suspense-suspending
+ * body (scope check) is isolated inside.
+ */
+export function GithubPushDialog({ open, adminApp, source, configUpdate, projectId, onSettle }: GithubPushDialogProps) {
+ const [scopeStatus, setScopeStatus] = useState("checking");
+ const [phase, setPhase] = useState("check");
+ const [stage, setStage] = useState(null);
+ const [startedAt, setStartedAt] = useState(0);
+ const [activity, setActivity] = useState(null);
+ const [diff, setDiff] = useState(null);
+ const [commitMessage, setCommitMessage] = useState("");
+ const [errorMessage, setErrorMessage] = useState(null);
+
+ // Expose imperative handles from the body (which can suspend) to the outer shell.
+ const handlersRef = useRef<{
+ push: () => Promise,
+ connect: () => Promise,
+ cancel: () => Promise,
+ commit: () => Promise,
+ } | null>(null);
+
+ const isNonDismissible = phase === "running" || phase === "cancelling" || phase === "committing";
+
+ // The commit-form phases explain themselves in the body (so the header stays
+ // identical across running/review); only the scope-check phase needs a header
+ // description.
+ const description = (() => {
+ if (phase !== "check") return undefined;
+ switch (scopeStatus) {
+ case "no-account": { return "Connect a GitHub account to push configuration changes to this repository."; }
+ case "checking": { return "Checking GitHub permissions…"; }
+ case "ok": { return `This will apply your change to ${source.owner}/${source.repo}@${source.branch}.`; }
+ case "missing-scopes": { return `Your linked GitHub account is missing the "repo" and "workflow" permissions. Reconnect to grant them.`; }
+ }
+ })();
+
+ // Footer buttons
+ const footer = (() => {
+ // Shared commit-form footer: Cancel on the left, status + Commit on the right.
+ // The only per-phase differences are button enabled/loading state and the
+ // "Waiting for preview…" hint, so running and review keep the same shape.
+ if (isCommitFormPhase(phase)) {
+ const canCommit = phase === "awaiting_review";
+ return (
+
+
{ await handlersRef.current?.cancel(); }}
+ >
+ {phase === "cancelling" ? "Cancelling…" : "Cancel"}
+
+
+ {phase === "running" && (
+
Waiting for preview…
+ )}
+
{ await handlersRef.current?.commit(); }}
+ >
+ {phase !== "committing" && }
+ {phase === "committing" ? "Committing…" : "Commit"}
+
+
+ );
+ }
+ // check
+ return (
+
+
+ { onSettle(false); }}>
+ Cancel
+
+
+ {scopeStatus === "no-account" || scopeStatus === "missing-scopes" ? (
+
{ await handlersRef.current?.connect(); }}>
+ {scopeStatus === "no-account" ? "Connect with GitHub" : "Reconnect with GitHub"}
+
+ ) : errorMessage != null && configUpdate != null ? (
+
{ await handlersRef.current?.push(); }}>
+
+ Retry update
+
+ ) : (
+ // Scope check passing (or still checking) auto-starts the run; show a
+ // non-interactive loading affordance until the phase flips to "running".
+
+ {scopeStatus === "checking" ? "Checking…" : "Starting…"}
+
+ )}
+
+ );
+ })();
+
+ // The whole commit form (running → review) uses one width so the dialog never
+ // resizes when the preview box swaps the loader out for the diff.
+ const dialogSize = isCommitFormPhase(phase) ? "3xl" : "lg";
+
+ return (
+ {
+ if (o || isNonDismissible) return;
+ onSettle(false);
+ }}
+ size={dialogSize}
+ icon={GitBranch}
+ title="Push configuration"
+ description={description}
+ hideTopCloseButton={isNonDismissible}
+ footer={footer}
+ contentProps={{ onPointerDownOutside: isNonDismissible ? (e) => e.preventDefault() : undefined, onEscapeKeyDown: isNonDismissible ? (e) => e.preventDefault() : undefined }}
+ >
+ Loading…
+
+
+ );
+}
+
+type GithubPushBodyProps = {
+ adminApp: StackAdminApp