panel/src/lib/viewmode.test.ts
0 → 100644
+164
−0
panel/src/lib/viewmode.ts
0 → 100644
+113
−0
Loading
Pure logic layer for the top-right avatar role-switcher: derive the home a principal is in and may switch into, mirroring nav.ts/auth.ts so the decision is unit-tested without a React renderer. - ViewMode is derived from NavSection["id"], so the three switchable homes (User/Admin/SysAdmin) can never drift from the nav sections. - availableViewModes / effectiveViewMode resolve a requested view against the live is_admin flag, failing closed: a non-admin or a demoted admin always collapses to the User home. - restoreViewMode re-gates a persisted (localStorage) choice on every read, never trusting the stored value over the live flag, closing the one escalation vector a client-side persona could open. - sectionsForView composes the view ceiling on top of visibleSections, so the switcher only ever narrows the sidebar, never widens access. The avatar dropdown UI that consumes this lands as a separate increment.