diff --git a/frontend/AGENTS.md b/frontend/AGENTS.md index fc4c1c5da8..28214af08e 100644 --- a/frontend/AGENTS.md +++ b/frontend/AGENTS.md @@ -306,7 +306,11 @@ accounts through `core/auth/admin-users.ts` → `/api/v1/admin/users`. The page reuses `userSchema` for rows — both endpoints parse against it, so a malformed payload fails the load instead of rendering a phantom row (`disabled` optional — absent means not disabled) — and PATCHes only -`{disabled}`; role stays a read-only column. The Gateway's rejection detail +`{disabled}`; role stays a read-only column. Like model management, the page +also gates on `isStaticWebsiteOnly()` (the demo user is nominally an admin, +but there is no Gateway to query), and the settings dialog falls back to the +first nav section when a deep link or stale store activates a section the +current user's nav does not offer. The Gateway's rejection detail (last-active-admin 409) renders verbatim. A session that turns out to be disabled maps `account_disabled` (see `AUTH_ERROR_CODES`) to a login redirect with a stated reason (login surface only — sign-up keeps diff --git a/frontend/src/components/workspace/settings/settings-dialog.tsx b/frontend/src/components/workspace/settings/settings-dialog.tsx index 9e1c27268f..49175c9850 100644 --- a/frontend/src/components/workspace/settings/settings-dialog.tsx +++ b/frontend/src/components/workspace/settings/settings-dialog.tsx @@ -184,6 +184,14 @@ export function SettingsDialog(props: SettingsDialogProps) { t.settings.sections.notification, t.settings.sections.about, ]); + // A `?settings=
` deep link (or a stale dialog store) can activate + // a section this user's nav does not offer — e.g. user management for a + // non-admin — so fall back to the first available section instead of + // rendering a panel with no highlighted entry. The base list above is + // non-empty, so the fallback itself always resolves. + const activeId = sections.some((section) => section.id === activeSection) + ? activeSection + : sections[0]!.id; return (