import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom"; import { ThemeProvider } from "@/lib/theme"; import { TierProvider } from "@/lib/tier"; import { AppShell } from "@/components/AppShell"; import { RequireAdmin } from "@/components/RequireAdmin"; import { RequireAuth } from "@/components/RequireAuth"; import { RequireOwner } from "@/components/RequireOwner"; import { Login } from "@/pages/Login"; import { Setup } from "@/pages/Setup"; import { Dashboard } from "@/pages/Dashboard"; import { ServersPage } from "@/pages/servers/ServersPage"; import { ServerConsole } from "@/pages/ServerConsole"; import { ServerPlayers } from "@/pages/ServerPlayers"; import { ServerBackups } from "@/pages/ServerBackups"; import { ServerLuckPerms } from "@/pages/ServerLuckPerms"; import { Account } from "@/pages/Account"; import { ImageAdmin } from "@/pages/admin/ImageAdmin"; import { ImageBuildPage } from "@/pages/admin/ImageBuildPage"; import { SubmissionsPage } from "@/pages/admin/SubmissionsPage"; import { UsersPage } from "@/pages/admin/UsersPage"; import { UserDetailPage } from "@/pages/admin/UserDetailPage"; import { MySubmissionsPage } from "@/pages/MySubmissionsPage"; import { UpdatesPage } from "@/pages/admin/UpdatesPage"; // Three UX surfaces over two Zero-Trust tiers (DESIGN-WEB-3SIDES): // / User-Side — app-tier, every authenticated principal // /admin/* Admin-Side — admin-tier, server & content administration // /ops/* SysAdmin-Side— admin-tier, platform observability cockpit // Both admin groups sit behind the SAME RequireAdmin wrapper (one is_admin gate); // the split is by concern, not by tier. TierProvider fetches /me once at boot. export default function App() { return ( {/* Pre-app sign-in surface (spec §B, passwordless). It sits OUTSIDE RequireAuth — RequireAuth redirects here — and outside AppShell, so it renders its own centered chrome with no nav/tier dependency. */} } /> {/* Owner first-run onboarding. Like /login it sits OUTSIDE RequireAuth: the visitor arrives from the `felis setup` link with no session, and redeeming the one-time token is what mints one. */} } /> {/* Everything else requires a session. RequireAuth gates the whole app: no/expired session → /login, transient /me failure → still renders (graded ZT). */} }> }> {/* User-Side — app-tier */} } /> } /> } /> } /> } /> } /> } /> } /> {/* Admin-Side — admin-tier (server & content ops). /admin has no landing page; redirect to the first concrete view so the section root and any stale bookmarks land somewhere useful. */} }> } /> } /> } /> } /> } /> {/* Owner-gated: user management (one level above admin). */} }> } /> } /> } /> ); }