fix: sandbox warning persistence and add env var option

Fix race condition where sandbox warning appeared on every refresh
even after checking "Do not show again". The issue was that the
sandbox check effect ran before settings were hydrated from the
server, so skipSandboxWarning was always false (the default).

Changes:
- Add settingsLoaded to sandbox check dependencies to ensure the
  user's preference is loaded before checking
- Add AUTOMAKER_SKIP_SANDBOX_WARNING env var option to skip the
  warning entirely (useful for dev/CI environments)
This commit is contained in:
Stefan de Vogelaere
2026-01-17 15:33:51 +01:00
parent b9567f5904
commit 17e2cdfc85
3 changed files with 21 additions and 7 deletions

View File

@@ -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);
};
}

View File

@@ -483,6 +483,7 @@ export const verifySession = async (): Promise<boolean> => {
*/
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' };

View File

@@ -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(