Description
The SPA "router" is a switch in src/routes/AppRoutes.jsx fed by a routeMap object in
src/App.jsx. The two have drifted out of sync. Two page components are rendered without ever being
imported, four route keys are declared twice (so the second declaration is dead), and 14 security
consoles that exist as page components are unreachable from any URL.
Problem 1: two components are used but never imported
case "keyvault-security":
case "keyvault":
return ProtectedRoute(KeyVaultSecurityPage); // never imported
...
case "microsegmentation":
return ProtectedRoute(MicrosegmentationPage); // never imported
AppRoutes.jsx imports SecurityKeyVaultPage (from ../pages/auth/SecurityKeyVaultPage) but
renders KeyVaultSecurityPage. MicrosegmentationPage is not imported under any name.
At runtime this is an uncaught ReferenceError that the ErrorBoundary turns into a blank screen
the moment a user navigates to /keyvault or /microsegmentation.
Correction to an earlier version of this issue: I first wrote that these are no-undef ESLint
errors that fail npm run build. They are not, and the reason is itself part of the problem:
package.json has no eslintConfig field. react-scripts therefore runs its ESLint plugin with
only eslint-config-react-app/base as the base config, and never loads the full react-app ruleset
where no-undef, no-dupe-keys and no-duplicate-case are set to error. I verified this by
building the branch with both components still undefined:
$ CI=true npm run build
Compiled successfully.
So none of the four defects below are currently caught by anything. Restoring the eslintConfig
field is part of the fix.
Problem 2: duplicate case labels — dead branches
$ duplicate case labels in AppRoutes.jsx: ["keyvault-security", "microsegmentation"]
case "keyvault-security": appears twice inside the same group:
case "keyvault-security":
case "keyvault":
case "keyvault-security": // dead
return ProtectedRoute(KeyVaultSecurityPage);
case "microsegmentation": appears once under the ZTNA group (line ~176) and again under the
SDP group (line ~198). The first wins, so MicrosegmentationPage is unreachable and
/microsegmentation silently renders ZeroTrustNetworkPage instead.
no-duplicate-case is part of eslint:recommended, which react-app extends.
Problem 3: duplicate keys in routeMap (src/App.jsx)
$ duplicate routeMap keys: ["help", "microsegmentation"]
help: "help", // line 74
...
microsegmentation: "ztna", // line 106
...
help: "help", // line 115 (silently overwrites)
...
microsegmentation: "microsegmentation", // line 119 (silently overwrites line 106)
The two microsegmentation entries disagree about the target page. In an object literal the last
wins, so /microsegmentation maps to "microsegmentation" — which then hits the dead case from
Problem 2. no-dupe-keys is also an eslint:recommended error.
Problem 4: 14 security consoles are unreachable
These page components exist under src/pages/auth/ and have no case in AppRoutes.jsx and no
routeMap entry in App.jsx:
CspmPage, SbomPage, SoarPage, SecurityPosturePage, SecurityGovernancePage,
SecurityObservabilityPage, SecurityPlaybookPage, SecurityThreatPage,
SecurityVulnerabilityPage, SamlIdentityProviderPage, ThreatIntelligencePage,
ComplianceEvidencePage, ComplianceReportingPage, IncidentResponsePlaybookPage
SecurityPosturePage is even imported by AppRoutes.jsx and then never referenced (no-unused-vars).
Problem 5: UnauthorizedPage never receives its message
const UnauthorizedPage = ({ onNavigate, message }) => ( ... {message || "Your account role is ..."} )
ProtectedRoute calls <UnauthorizedPage onNavigate={onNavigate} /> with no message, so the prop
is dead code and every denial shows the same generic string.
Root Cause
Route information is duplicated in three places — the routeMap object, the switch statement, and
the import list — with nothing keeping them consistent. Every subsystem PR has to edit all three, and
the drift above is the accumulated result.
Expected Result
/keyvault, /keyvault-security, /key-vault render the key-vault console.
/microsegmentation, /sdp, /perimeter-security render MicrosegmentationPage;
/ztna, /network-access render ZeroTrustNetworkPage.
- Every page component under
src/pages/auth/ is reachable by at least one URL.
npm run build emits no no-undef, no-duplicate-case, no-dupe-keys or no-unused-vars errors.
Proposed Fix
- Introduce
src/routes/routeRegistry.js as the single source of truth: one entry per page holding
its canonical slug, URL aliases, component, allowed roles and layout flag.
- Derive both the
routeMap in App.jsx and the resolution logic in AppRoutes.jsx from that
registry, replacing the switch and deleting the duplicated import list.
- Register the 14 orphaned consoles.
- Pass a specific
message into UnauthorizedPage naming the roles that may access the route.
- Add
routeRegistry.test.js asserting: no duplicate slug or alias across the registry, every
registered component is defined (not undefined), and every *Page.jsx under src/pages/auth/
appears in the registry — so orphaned pages and undefined components fail the build instead of
the browser.
Labels
bug, frontend
Description
The SPA "router" is a
switchinsrc/routes/AppRoutes.jsxfed by arouteMapobject insrc/App.jsx. The two have drifted out of sync. Two page components are rendered without ever beingimported, four route keys are declared twice (so the second declaration is dead), and 14 security
consoles that exist as page components are unreachable from any URL.
Problem 1: two components are used but never imported
AppRoutes.jsximportsSecurityKeyVaultPage(from../pages/auth/SecurityKeyVaultPage) butrenders
KeyVaultSecurityPage.MicrosegmentationPageis not imported under any name.At runtime this is an uncaught
ReferenceErrorthat theErrorBoundaryturns into a blank screenthe moment a user navigates to
/keyvaultor/microsegmentation.Correction to an earlier version of this issue: I first wrote that these are
no-undefESLinterrors that fail
npm run build. They are not, and the reason is itself part of the problem:package.jsonhas noeslintConfigfield.react-scriptstherefore runs its ESLint plugin withonly
eslint-config-react-app/baseas the base config, and never loads the fullreact-apprulesetwhere
no-undef,no-dupe-keysandno-duplicate-caseare set toerror. I verified this bybuilding the branch with both components still undefined:
So none of the four defects below are currently caught by anything. Restoring the
eslintConfigfield is part of the fix.
Problem 2: duplicate
caselabels — dead branchescase "keyvault-security":appears twice inside the same group:case "microsegmentation":appears once under the ZTNA group (line ~176) and again under theSDP group (line ~198). The first wins, so
MicrosegmentationPageis unreachable and/microsegmentationsilently rendersZeroTrustNetworkPageinstead.no-duplicate-caseis part ofeslint:recommended, whichreact-appextends.Problem 3: duplicate keys in
routeMap(src/App.jsx)The two
microsegmentationentries disagree about the target page. In an object literal the lastwins, so
/microsegmentationmaps to"microsegmentation"— which then hits the deadcasefromProblem 2.
no-dupe-keysis also aneslint:recommendederror.Problem 4: 14 security consoles are unreachable
These page components exist under
src/pages/auth/and have nocaseinAppRoutes.jsxand norouteMapentry inApp.jsx:CspmPage,SbomPage,SoarPage,SecurityPosturePage,SecurityGovernancePage,SecurityObservabilityPage,SecurityPlaybookPage,SecurityThreatPage,SecurityVulnerabilityPage,SamlIdentityProviderPage,ThreatIntelligencePage,ComplianceEvidencePage,ComplianceReportingPage,IncidentResponsePlaybookPageSecurityPosturePageis even imported byAppRoutes.jsxand then never referenced (no-unused-vars).Problem 5:
UnauthorizedPagenever receives itsmessageProtectedRoutecalls<UnauthorizedPage onNavigate={onNavigate} />with nomessage, so the propis dead code and every denial shows the same generic string.
Root Cause
Route information is duplicated in three places — the
routeMapobject, theswitchstatement, andthe import list — with nothing keeping them consistent. Every subsystem PR has to edit all three, and
the drift above is the accumulated result.
Expected Result
/keyvault,/keyvault-security,/key-vaultrender the key-vault console./microsegmentation,/sdp,/perimeter-securityrenderMicrosegmentationPage;/ztna,/network-accessrenderZeroTrustNetworkPage.src/pages/auth/is reachable by at least one URL.npm run buildemits nono-undef,no-duplicate-case,no-dupe-keysorno-unused-varserrors.Proposed Fix
src/routes/routeRegistry.jsas the single source of truth: one entry per page holdingits canonical slug, URL aliases, component, allowed roles and layout flag.
routeMapinApp.jsxand the resolution logic inAppRoutes.jsxfrom thatregistry, replacing the
switchand deleting the duplicated import list.messageintoUnauthorizedPagenaming the roles that may access the route.routeRegistry.test.jsasserting: no duplicate slug or alias across the registry, everyregistered component is defined (not
undefined), and every*Page.jsxundersrc/pages/auth/appears in the registry — so orphaned pages and undefined components fail the build instead of
the browser.
Labels
bug,frontend