From b76664fb4f99580648271af192ccd2df36c895fc Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 29 Apr 2026 18:11:36 +0100 Subject: [PATCH] Remove duplicate app route preload path --- .../v6/internal/subsystems/cloud-paid.md | 9 +++-- .../subsystems/frontend-primitives.md | 26 +++++++------ .../subsystems/performance-and-scalability.md | 16 ++++++-- .../v6/internal/subsystems/registry.json | 37 +++++++++++++++++++ .../src/__tests__/App.architecture.test.ts | 3 ++ frontend-modern/src/useAppRuntimeState.ts | 29 --------------- 6 files changed, 72 insertions(+), 48 deletions(-) diff --git a/docs/release-control/v6/internal/subsystems/cloud-paid.md b/docs/release-control/v6/internal/subsystems/cloud-paid.md index b4be546ed..855911794 100644 --- a/docs/release-control/v6/internal/subsystems/cloud-paid.md +++ b/docs/release-control/v6/internal/subsystems/cloud-paid.md @@ -114,8 +114,9 @@ cloud-specific enforcement rules. ## Shared Boundaries 1. `frontend-modern/src/components/Settings/MonitoredSystemAdmissionPreview.tsx` shared with `agent-lifecycle`: the monitored-system admission preview is both a platform-connections lifecycle surface and a canonical cloud-paid monitored-system presentation boundary. -2. `internal/api/licensing_bridge.go` shared with `api-contracts`: commercial licensing bridge handlers carry both API payload contract and cloud-paid entitlement boundary ownership. -3. `internal/api/licensing_handlers.go` shared with `api-contracts`: commercial licensing handlers carry both API payload contract and cloud-paid entitlement boundary ownership. +2. `frontend-modern/src/useAppRuntimeState.ts` shared with `performance-and-scalability`: the authenticated app runtime bootstrap is both a hosted commercial org-context boundary and a protected app-shell performance boundary. +3. `internal/api/licensing_bridge.go` shared with `api-contracts`: commercial licensing bridge handlers carry both API payload contract and cloud-paid entitlement boundary ownership. +4. `internal/api/licensing_handlers.go` shared with `api-contracts`: commercial licensing handlers carry both API payload contract and cloud-paid entitlement boundary ownership. That same shared licensing boundary also owns installation-version continuity for authenticated v6 installs: `internal/api/router.go` and `internal/api/licensing_handlers.go` must hand the canonical process @@ -123,8 +124,8 @@ cloud-specific enforcement rules. and cloud-paid transport must send that value on activate, legacy exchange, and grant refresh instead of inferring install version from browser state, dev build metadata, or anonymous telemetry. -4. `internal/api/payments_webhook_handlers.go` shared with `api-contracts`: commercial payment webhook handlers carry both API payload contract and cloud-paid billing boundary ownership. -5. `internal/api/public_signup_handlers.go` shared with `api-contracts`: hosted signup handlers carry both API payload contract and cloud-paid hosted provisioning boundary ownership. +5. `internal/api/payments_webhook_handlers.go` shared with `api-contracts`: commercial payment webhook handlers carry both API payload contract and cloud-paid billing boundary ownership. +6. `internal/api/public_signup_handlers.go` shared with `api-contracts`: hosted signup handlers carry both API payload contract and cloud-paid hosted provisioning boundary ownership. That shared monitored-system presentation boundary also owns disabled provider-connection copy. Commercial entitlement surfaces must treat canonical zero-delta and removal-only TrueNAS or VMware previews as non-consuming or diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md index f741d42e7..8a73bbf86 100644 --- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md +++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md @@ -145,15 +145,16 @@ work extends shared components instead of creating new local variants. 119. `frontend-modern/src/stores/sessionPresentationPolicy.ts` 120. `frontend-modern/src/stores/licenseCommercial.ts` 121. `frontend-modern/src/useAppRuntimeState.ts` -122. `frontend-modern/src/stores/aiChat.ts` -123. `frontend-modern/scripts/header-audit.mjs` -124. `frontend-modern/src/components/Settings/DataHandlingPanel.tsx` -125. `frontend-modern/src/components/Settings/dataHandlingPanelModel.ts` -126. `frontend-modern/scripts/canonical-platform-audit.mjs` -127. `frontend-modern/src/utils/platformSupportManifest.generated.ts` -128. `frontend-modern/src/utils/platformSupportManifest.ts` -129. `frontend-modern/src/utils/sourcePlatformOptions.ts` -130. `frontend-modern/src/utils/sourcePlatforms.ts` +122. `frontend-modern/src/routing/routePreload.ts` +123. `frontend-modern/src/stores/aiChat.ts` +124. `frontend-modern/scripts/header-audit.mjs` +125. `frontend-modern/src/components/Settings/DataHandlingPanel.tsx` +126. `frontend-modern/src/components/Settings/dataHandlingPanelModel.ts` +127. `frontend-modern/scripts/canonical-platform-audit.mjs` +128. `frontend-modern/src/utils/platformSupportManifest.generated.ts` +129. `frontend-modern/src/utils/platformSupportManifest.ts` +130. `frontend-modern/src/utils/sourcePlatformOptions.ts` +131. `frontend-modern/src/utils/sourcePlatforms.ts` ## Shared Boundaries @@ -162,9 +163,10 @@ work extends shared components instead of creating new local variants. 3. `frontend-modern/src/components/Settings/GeneralSettingsPanel.tsx` shared with `security-privacy`: the general settings privacy panel is both a security/privacy control surface and a canonical settings-shell presentation boundary. 4. `frontend-modern/src/components/Settings/SecurityAuthPanel.tsx` shared with `security-privacy`: the authentication settings surface is both a security/privacy control surface and a canonical settings-shell presentation boundary. 5. `frontend-modern/src/components/Settings/SecurityOverviewPanel.tsx` shared with `security-privacy`: the security overview settings surface is both a security/privacy control surface and a canonical settings-shell presentation boundary. -6. `frontend-modern/src/stores/aiChat.ts` shared with `ai-runtime`: the assistant drawer and session store is both an AI runtime control surface and a canonical app-shell presentation boundary. -7. `frontend-modern/src/utils/platformSupportManifest.generated.ts` shared with `unified-resources`: the generated platform support projection is both a canonical unified-resource platform union boundary and a shared frontend source/platform vocabulary boundary. -8. `frontend-modern/src/utils/sourcePlatforms.ts` shared with `unified-resources`: the source platform normalizer is both a canonical unified-resource source adapter boundary and a shared frontend source/platform vocabulary boundary. +6. `frontend-modern/src/routing/routePreload.ts` shared with `performance-and-scalability`: the app-shell route preload registry is both a canonical frontend shell boundary and an authenticated hot-path performance boundary. +7. `frontend-modern/src/stores/aiChat.ts` shared with `ai-runtime`: the assistant drawer and session store is both an AI runtime control surface and a canonical app-shell presentation boundary. +8. `frontend-modern/src/utils/platformSupportManifest.generated.ts` shared with `unified-resources`: the generated platform support projection is both a canonical unified-resource platform union boundary and a shared frontend source/platform vocabulary boundary. +9. `frontend-modern/src/utils/sourcePlatforms.ts` shared with `unified-resources`: the source platform normalizer is both a canonical unified-resource source adapter boundary and a shared frontend source/platform vocabulary boundary. ## Extension Points diff --git a/docs/release-control/v6/internal/subsystems/performance-and-scalability.md b/docs/release-control/v6/internal/subsystems/performance-and-scalability.md index 573b425a1..f92da26d0 100644 --- a/docs/release-control/v6/internal/subsystems/performance-and-scalability.md +++ b/docs/release-control/v6/internal/subsystems/performance-and-scalability.md @@ -120,6 +120,8 @@ regression protection. 98. `frontend-modern/src/components/Infrastructure/useInfrastructureSummaryState.ts` 99. `frontend-modern/src/components/Infrastructure/infrastructureSummaryModel.ts` 100. `frontend-modern/src/utils/workloadsSummaryCache.ts` +101. `frontend-modern/src/routing/routePreload.ts` +102. `frontend-modern/src/useAppRuntimeState.ts` 103. `frontend-modern/src/components/Storage/StorageSummary.tsx` 104. `frontend-modern/src/utils/storageSummaryCache.ts` 105. `frontend-modern/src/pages/Workloads.tsx` @@ -140,7 +142,9 @@ regression protection. 12. `frontend-modern/src/components/Infrastructure/useInfrastructureSummaryState.ts` shared with `unified-resources`: infrastructure summary chart polling, cache hydration, and summary-state orchestration are both a canonical unified-resource consumer surface and a fleet-scale summary chart hot-path boundary. 13. `frontend-modern/src/components/Infrastructure/useUnifiedResourceTableState.ts` shared with `unified-resources`: unified resource table state, grouping, and windowing are both a canonical unified-resource consumer surface and a fleet-scale performance hot-path boundary. 14. `frontend-modern/src/components/Infrastructure/useUnifiedResourceTableViewportSync.ts` shared with `unified-resources`: unified resource table viewport sync and selected-row reveal are both a canonical unified-resource consumer surface and a fleet-scale performance hot-path boundary. -15. `internal/api/slo.go` shared with `api-contracts`: the SLO endpoint is both an API contract surface and a protected performance hot-path boundary. +15. `frontend-modern/src/routing/routePreload.ts` shared with `frontend-primitives`: the app-shell route preload registry is both a canonical frontend shell boundary and an authenticated hot-path performance boundary. +16. `frontend-modern/src/useAppRuntimeState.ts` shared with `cloud-paid`: the authenticated app runtime bootstrap is both a hosted commercial org-context boundary and a protected app-shell performance boundary. +17. `internal/api/slo.go` shared with `api-contracts`: the SLO endpoint is both an API contract surface and a protected performance hot-path boundary. ## Extension Points @@ -329,8 +333,8 @@ dashboard-specific overview, trend, or summary transport. the org list from the shared `organizations_changed` event, but that refresh must stay event-driven and route-safe rather than expanding into a second full app bootstrap, a pre-auth org probe, or a deleted dashboard-route prewarm - that duplicates the canonical summary fetch path. - into another summary-fetch or org-bootstrap hot path. + that duplicates the canonical summary fetch path or expands into another + summary-fetch or org-bootstrap hot path. The same protected hot path also owns Patrol route compatibility: if `frontend-modern/src/App.tsx` keeps `/ai` as a legacy alias while `/patrol` is canonical, that alias must stay a thin redirect and must not mount a @@ -345,6 +349,12 @@ dashboard-specific overview, trend, or summary transport. canonical Infrastructure landing path instead of leaving the freshly authenticated shell on a not-found page that immediately pays another cold bootstrap. + App-shell route module preloading belongs to + `frontend-modern/src/routing/routePreload.ts` and the delayed authenticated + preload call in `frontend-modern/src/App.tsx`. `frontend-modern/src/useAppRuntimeState.ts` + must not keep page-local dynamic imports or a second route-preload cache, + because the runtime bootstrap already owns state, chart cache warming, org + hydration, and health probing. The same protected hot path now also owns proof harness steadiness. Store-backed chart SLO and benchmark helpers in `pkg/metrics/store_slo_test.go`, `internal/api/slo_bench_test.go`, and `internal/monitoring/monitor_metrics_slo_test.go` diff --git a/docs/release-control/v6/internal/subsystems/registry.json b/docs/release-control/v6/internal/subsystems/registry.json index b0086fda4..97f0dec16 100644 --- a/docs/release-control/v6/internal/subsystems/registry.json +++ b/docs/release-control/v6/internal/subsystems/registry.json @@ -361,6 +361,14 @@ "api-contracts" ] }, + { + "path": "frontend-modern/src/routing/routePreload.ts", + "rationale": "the app-shell route preload registry is both a canonical frontend shell boundary and an authenticated hot-path performance boundary", + "subsystems": [ + "frontend-primitives", + "performance-and-scalability" + ] + }, { "path": "frontend-modern/src/stores/aiChat.ts", "rationale": "the assistant drawer and session store is both an AI runtime control surface and a canonical app-shell presentation boundary", @@ -369,6 +377,14 @@ "frontend-primitives" ] }, + { + "path": "frontend-modern/src/useAppRuntimeState.ts", + "rationale": "the authenticated app runtime bootstrap is both a hosted commercial org-context boundary and a protected app-shell performance boundary", + "subsystems": [ + "cloud-paid", + "performance-and-scalability" + ] + }, { "path": "frontend-modern/src/utils/agentInstallCommand.ts", "rationale": "the shared frontend install-command helper is both an agent lifecycle control surface and a canonical API/install transport contract boundary", @@ -2992,6 +3008,7 @@ "frontend-modern/src/hooks/createNonSuspendingQuery.ts", "frontend-modern/src/index.css", "frontend-modern/src/pages/Operations.tsx", + "frontend-modern/src/routing/routePreload.ts", "frontend-modern/src/stores/aiChat.ts", "frontend-modern/src/utils/aiSettingsPresentation.ts", "frontend-modern/src/utils/diagnosticsPresentation.ts", @@ -3176,6 +3193,7 @@ "frontend-modern/src/components/Settings/useReportingPanelState.ts", "frontend-modern/src/components/Settings/useSystemLogsPanelState.ts", "frontend-modern/src/pages/Operations.tsx", + "frontend-modern/src/routing/routePreload.ts", "frontend-modern/src/utils/reportableResourceTypes.ts", "frontend-modern/src/utils/reportingPresentation.ts", "frontend-modern/src/utils/reportingResourceTypes.ts" @@ -3192,6 +3210,7 @@ "frontend-modern/src/pages/__tests__/Operations.helpers.test.ts", "frontend-modern/src/pages/__tests__/Recovery.test.tsx", "frontend-modern/src/pages/__tests__/Workloads.helpers.test.ts", + "frontend-modern/src/routing/__tests__/routePreload.test.ts", "frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts", "frontend-modern/src/utils/__tests__/reportableResourceTypes.test.ts", "frontend-modern/src/utils/__tests__/reportingPresentation.test.ts", @@ -4173,6 +4192,8 @@ "frontend-modern/src/components/Workloads/workloadTopology.ts", "frontend-modern/src/components/Workloads/workloadUrlSyncModel.ts", "frontend-modern/src/pages/Workloads.tsx", + "frontend-modern/src/routing/routePreload.ts", + "frontend-modern/src/useAppRuntimeState.ts", "frontend-modern/src/utils/thresholdSliderPresentation.ts", "frontend-modern/src/utils/throughputPresentation.ts", "frontend-modern/src/utils/workloadsSummaryCache.ts", @@ -4231,6 +4252,22 @@ "pkg/metrics/store_slo_test.go" ] }, + { + "id": "app-shell-route-preload", + "label": "app-shell route preload proof", + "match_prefixes": [], + "match_files": [ + "frontend-modern/src/routing/routePreload.ts", + "frontend-modern/src/useAppRuntimeState.ts" + ], + "allow_same_subsystem_tests": false, + "test_prefixes": [], + "exact_files": [ + "frontend-modern/src/__tests__/App.architecture.test.ts", + "frontend-modern/src/__tests__/useAppRuntimeState.test.ts", + "frontend-modern/src/routing/__tests__/routePreload.test.ts" + ] + }, { "id": "workloads-hot-path", "label": "Workloads hot-path proof", diff --git a/frontend-modern/src/__tests__/App.architecture.test.ts b/frontend-modern/src/__tests__/App.architecture.test.ts index 2ec3cf946..7da3680e7 100644 --- a/frontend-modern/src/__tests__/App.architecture.test.ts +++ b/frontend-modern/src/__tests__/App.architecture.test.ts @@ -37,6 +37,9 @@ describe('App architecture', () => { expect(routePreloadSource).toContain('RECOVERY_ROUTE_PATH,'); expect(routePreloadSource).toContain('PATROL_PATH,'); expect(appSource).toContain('await preloadRouteModule(route);'); + expect(appRuntimeStateSource).not.toContain('preloadLazyRoutes'); + expect(appRuntimeStateSource).not.toContain("import('@/pages/Alerts')"); + expect(appRuntimeStateSource).not.toContain("import('@/components/Settings/Settings')"); expect(appSource).toContain('const timeoutId = window.setTimeout(() => {'); expect(appSource).toContain('void preloadAppShellRoutes();'); expect(appSource).toContain( diff --git a/frontend-modern/src/useAppRuntimeState.ts b/frontend-modern/src/useAppRuntimeState.ts index 3428fb461..0100a7df8 100644 --- a/frontend-modern/src/useAppRuntimeState.ts +++ b/frontend-modern/src/useAppRuntimeState.ts @@ -103,7 +103,6 @@ export const useAppRuntimeState = () => { }; const alertsActivation = useAlertsActivation(); - let hasPreloadedRoutes = false; let hasFetchedVersionInfo = false; let hasPrewarmedInfrastructureCharts = false; let hasPrewarmedWorkloadsCharts = false; @@ -194,23 +193,6 @@ export const useAppRuntimeState = () => { prewarmWorkloadsCharts(); }; - const preloadLazyRoutes = () => { - if (hasPreloadedRoutes || typeof window === 'undefined') { - return; - } - hasPreloadedRoutes = true; - const loaders: Array<() => Promise> = [ - () => import('@/pages/Alerts'), - () => import('@/components/Settings/Settings'), - ]; - - loaders.forEach((load) => { - void load().catch((error) => { - logger.warn('Preloading route module failed', error); - }); - }); - }; - const fallbackState: State = { connectedInfrastructure: [], metrics: [], @@ -496,17 +478,6 @@ export const useAppRuntimeState = () => { } }); - createEffect(() => { - if (!isLoading() && !needsAuth()) { - if (typeof window === 'undefined') { - return; - } - if (!hasPreloadedRoutes) { - window.setTimeout(preloadLazyRoutes, 0); - } - } - }); - createEffect(() => { if ( isLoading() ||