Commit Graph
112 Commits
Author SHA1 Message Date
Lemon-miaow 15c58d982d feat(panel): player management 2026-07-02 03:30:50 +08:00
Lemon-miaow d2de11af22 feat(panel): fleet 2026-07-01 03:46:07 +08:00
Lemon-miaow 7507cfaae4 Revert "feat(panel): wire role-switcher into the app shell"
This reverts commit 50b8487ff5.
2026-07-01 00:05:51 +08:00
flyemoji 50b8487ff5 feat(panel): wire role-switcher into the app shell
Build the React consumer over the fail-closed view-mode logic so an admin
can view the app as each of the three homes (User/Admin/SysAdmin) and step
down to a plain User-Side home.

- ViewModeProvider holds the raw requested home (seeded from localStorage,
  shape-checked only) and resolves it live against is_admin on every render,
  so a demotion or transient /me failure collapses to the User home with no
  flash, while an unentitled value is never stored or applied.
- RoleSwitcher renders only for admins (availableViewModes > 1); switching
  re-gates the choice and navigates to the chosen home's root.
- AppShell drives its sidebar from sectionsForView(view, isAdmin), which only
  ever narrows visibleSections — an admin viewing as a user sees a plain
  user's sidebar and lands on the Dashboard at /.
- landingPathForView / viewModeLabelKey added to the logic layer (tested);
  view_* and view_switch_label i18n keys added for en-US and zh-CN.

Placement note: the spec calls for a top-right avatar control, but the panel
has no desktop top bar, so the switcher lives in the sidebar foot beside the
user strip. Functionally complete; placement is not yet spec-parity.
2026-06-30 12:18:51 +09:00
flyemoji 563041ada3 feat(panel): add fail-closed role-switcher view-mode logic
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.
2026-06-30 12:01:24 +09:00
Lemon-miaow 832b200d55 fix(panel): reactive system theme detection 2026-06-28 03:41:50 +08:00
Lemon-miaow a49443cd1f refactor(panel): simplify sidebar 2026-06-28 00:04:27 +08:00
Lemon-miaow cfe126fbee feat(panel): add RCON command input to server console 2026-06-27 23:10:16 +08:00
Lemon-miaow 7b458daf77 feat(panel): light/dark theme 2026-06-27 18:48:12 +08:00
Lemon-miaow dd2fc6fa82 feat(panel): i18n 2026-06-27 18:31:26 +08:00
flyemoji 885c4a9bd8 feat(panel): local-password login and forced password change
Add the op.console login and forced first-login password-change flow to
the panel. RequireAuth bounces an unauthenticated visitor to /login;
both /login and /change-password render outside the app shell with their
own centered chrome.

- TierProvider now derives auth state (deriveAuth) and exposes refresh()
  so a successful login re-fetches identity without a full reload; only a
  genuine 401 marks the session unauthenticated, so a transient /me
  failure keeps a healthy Zero-Trust principal in the app.
- api.login/logout/changePassword send Content-Type: application/json on
  bodied requests to satisfy the backend guard; humanizeError maps the
  auth error codes to stable copy.

Covered by vitest unit tests for deriveAuth branch coverage and the
login/change-password wire-shape contracts.
2026-06-27 04:23:32 +09:00
flyemoji eee00c2772 feat(panel): add three-sided web console (User, Admin, SysAdmin)
Vite + TypeScript + Tailwind single-page console presenting the three operator tiers and consuming the external felis-api face. Build output and design notes are not tracked.
2026-06-26 23:32:39 +09:00