diff --git a/docs/release-control/v6/internal/subsystems/cloud-paid.md b/docs/release-control/v6/internal/subsystems/cloud-paid.md
index 6254576b5d..d62f2ce946 100644
--- a/docs/release-control/v6/internal/subsystems/cloud-paid.md
+++ b/docs/release-control/v6/internal/subsystems/cloud-paid.md
@@ -463,6 +463,12 @@ instead of wiring product-surface components such as
`frontend-modern/src/components/Storage/Storage.tsx` directly into the router,
so hosted bootstrap ownership stays at the app boundary rather than leaking
route concerns back into feature components.
+That same authenticated route shell also owns the canonical post-auth landing
+path. `frontend-modern/src/App.tsx` must send `/` through the dashboard page
+shell first, so existing operators land on the overview route and first-time
+operators hit the governed dashboard empty state that forwards them into
+Infrastructure Install, instead of carrying a root-only redirect to the
+infrastructure route that bypasses the shared landing contract.
The Pro license settings surface now follows the same rule as well. Changes to
`frontend-modern/src/components/Settings/ProLicensePanel.tsx` must carry this
contract and the dedicated Pro-license proof file instead of remaining an
diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md
index 7c26d4edab..92a6dbf073 100644
--- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md
+++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md
@@ -192,6 +192,11 @@ work extends shared components instead of creating new local variants.
must name the canonical install workspace explicitly and expose the same
first-host next step instead of falling back to passive “nothing here yet”
wording.
+11. Keep the authenticated app root aligned with that same first-session path.
+ `frontend-modern/src/App.tsx` must land `/` on the dashboard shell and let
+ the governed dashboard empty state route first-time operators into
+ Infrastructure Install, instead of preserving a separate root-only jump to
+ `/infrastructure` that drifts from the rest of the onboarding contract.
## Current State
diff --git a/frontend-modern/src/App.tsx b/frontend-modern/src/App.tsx
index 18b8617712..9f4bad9d5f 100644
--- a/frontend-modern/src/App.tsx
+++ b/frontend-modern/src/App.tsx
@@ -34,6 +34,7 @@ import { aiChatStore } from './stores/aiChat';
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';
import { useKioskMode } from '@/hooks/useKioskMode';
import {
+ DASHBOARD_PATH,
buildRecoveryPath,
buildInfrastructurePath,
buildStoragePath,
@@ -78,7 +79,8 @@ const SetupCompletionPreviewPage = lazy(() =>
default: module.SetupCompletionPreview,
})),
);
-const ROOT_INFRASTRUCTURE_PATH = buildInfrastructurePath();
+const ROOT_DASHBOARD_PATH = DASHBOARD_PATH;
+const INFRASTRUCTURE_ROUTE_PATH = buildInfrastructurePath();
const ROOT_WORKLOADS_PATH = buildWorkloadsPath();
const STORAGE_PATH = buildStoragePath();
const RECOVERY_ROUTE_PATH = buildRecoveryPath();
@@ -378,13 +380,13 @@ function App() {
-
- } />
+
+ } />
-
+
diff --git a/frontend-modern/src/__tests__/App.architecture.test.ts b/frontend-modern/src/__tests__/App.architecture.test.ts
index 7558049938..4e1f417e65 100644
--- a/frontend-modern/src/__tests__/App.architecture.test.ts
+++ b/frontend-modern/src/__tests__/App.architecture.test.ts
@@ -5,9 +5,13 @@ import appRuntimeStateSource from '@/useAppRuntimeState.ts?raw';
describe('App architecture', () => {
it('keeps App as the entry shell that delegates runtime and chrome ownership', () => {
+ expect(appSource).toContain('DASHBOARD_PATH,');
expect(appSource).toContain("import { AppLayout } from '@/AppLayout';");
expect(appSource).toContain("import { useAppRuntimeState } from '@/useAppRuntimeState';");
expect(appSource).toContain('const runtime = useAppRuntimeState();');
+ expect(appSource).toContain('const ROOT_DASHBOARD_PATH = DASHBOARD_PATH;');
+ expect(appSource).toContain('');
+ expect(appSource).toContain(' } />');
expect(appSource).toContain("const StoragePage = lazy(() => import('./pages/Storage'));");
expect(appSource).toContain("const OperationsPage = lazy(() => import('./pages/Operations'));");
expect(appSource).not.toContain(