diff --git a/apps/server/src/routes/health/routes/environment.ts b/apps/server/src/routes/health/routes/environment.ts index ee5f7d53..8e5a89c9 100644 --- a/apps/server/src/routes/health/routes/environment.ts +++ b/apps/server/src/routes/health/routes/environment.ts @@ -9,12 +9,14 @@ import type { Request, Response } from 'express'; export interface EnvironmentResponse { isContainerized: boolean; + skipSandboxWarning?: boolean; } export function createEnvironmentHandler() { return (_req: Request, res: Response): void => { res.json({ isContainerized: process.env.IS_CONTAINERIZED === 'true', + skipSandboxWarning: process.env.AUTOMAKER_SKIP_SANDBOX_WARNING === 'true', } satisfies EnvironmentResponse); }; } diff --git a/apps/ui/src/lib/http-api-client.ts b/apps/ui/src/lib/http-api-client.ts index d7ac5280..cd0e6739 100644 --- a/apps/ui/src/lib/http-api-client.ts +++ b/apps/ui/src/lib/http-api-client.ts @@ -483,6 +483,7 @@ export const verifySession = async (): Promise => { */ export const checkSandboxEnvironment = async (): Promise<{ isContainerized: boolean; + skipSandboxWarning?: boolean; error?: string; }> => { try { @@ -498,7 +499,10 @@ export const checkSandboxEnvironment = async (): Promise<{ } const data = await response.json(); - return { isContainerized: data.isContainerized ?? false }; + return { + isContainerized: data.isContainerized ?? false, + skipSandboxWarning: data.skipSandboxWarning ?? false, + }; } catch (error) { logger.error('Sandbox environment check failed:', error); return { isContainerized: false, error: 'Network error' }; diff --git a/apps/ui/src/routes/__root.tsx b/apps/ui/src/routes/__root.tsx index f3a662e8..9c118967 100644 --- a/apps/ui/src/routes/__root.tsx +++ b/apps/ui/src/routes/__root.tsx @@ -252,15 +252,16 @@ function RootLayoutContent() { setIsMounted(true); }, []); - // Check sandbox environment only after user is authenticated and setup is complete + // Check sandbox environment only after user is authenticated, setup is complete, and settings are loaded useEffect(() => { // Skip if already decided if (sandboxStatus !== 'pending') { return; } - // Don't check sandbox until user is authenticated and has completed setup - if (!authChecked || !isAuthenticated || !setupComplete) { + // Don't check sandbox until user is authenticated, has completed setup, and settings are loaded + // CRITICAL: settingsLoaded must be true to ensure skipSandboxWarning has been hydrated from server + if (!authChecked || !isAuthenticated || !setupComplete || !settingsLoaded) { return; } @@ -271,8 +272,8 @@ function RootLayoutContent() { if (result.isContainerized) { // Running in a container, no warning needed setSandboxStatus('containerized'); - } else if (skipSandboxWarning) { - // User opted to skip the warning, auto-confirm + } else if (result.skipSandboxWarning || skipSandboxWarning) { + // Skip if env var is set OR if user preference is set setSandboxStatus('confirmed'); } else { // Not containerized, show warning dialog @@ -290,7 +291,14 @@ function RootLayoutContent() { }; checkSandbox(); - }, [sandboxStatus, skipSandboxWarning, authChecked, isAuthenticated, setupComplete]); + }, [ + sandboxStatus, + skipSandboxWarning, + authChecked, + isAuthenticated, + setupComplete, + settingsLoaded, + ]); // Handle sandbox risk confirmation const handleSandboxConfirm = useCallback(