diff --git a/docs/INTERFACE_PATTERN_MIGRATION.md b/docs/INTERFACE_PATTERN_MIGRATION.md
index a6dc725..a62bd82 100644
--- a/docs/INTERFACE_PATTERN_MIGRATION.md
+++ b/docs/INTERFACE_PATTERN_MIGRATION.md
@@ -31,9 +31,14 @@ through declared capabilities or metadata.
## Interaction evidence
-- `AdminPageLayout`, `TreeSubnav`, `DataGrid`, `Dialog`, `ConfirmDialog`,
+- `WorkspaceLayout`, headerless `PageLayout`, `AdminPageLayout`, `TreeSubnav`,
+ `DataGrid`, `Dialog`, `ConfirmDialog`,
`TableActionGroup`, `PasswordField`, `ActionBlockerHint`, and
`DocumentationHelpLink` come from Core.
+- The administration tree and its contributed panels now share Core-owned pane
+ sizing, scrolling, content inset, responsive collapse, region labels, and
+ contextual-help identity; Access no longer carries a raw workspace or page
+ frame exception.
- Dialog focus trapping and restoration, disabled-action tooltips, keyboard
ordering, responsive grid overflow, and alert semantics therefore inherit
the tested Core behavior.
diff --git a/webui/src/features/admin/AdminPage.tsx b/webui/src/features/admin/AdminPage.tsx
index bec8332..fdc3a16 100644
--- a/webui/src/features/admin/AdminPage.tsx
+++ b/webui/src/features/admin/AdminPage.tsx
@@ -12,6 +12,7 @@ import type {
} from "@govoplan/core-webui";
import { fetchShellAuth } from "@govoplan/core-webui";
import { ActionBlockerHint } from "@govoplan/core-webui";
+import { PageLayout, WorkspaceLayout } from "@govoplan/core-webui";
import { PageScrollViewport } from "@govoplan/core-webui";
import {
TreeSubnav,
@@ -322,15 +323,26 @@ export default function AdminPage({
const contributionContext = { settings, auth, onAuthChange, refreshAuth, availableSections: available, selectSection };
return (
-
-
-
-
+
+ )}
+ primaryLabel="i18n:govoplan-access.admin.4e7afebc"
+ contentLabel="i18n:govoplan-access.admin.4e7afebc"
+ documentationType="admin"
+ >
+
{contributedSection && contributedSection.render(contributionContext)}
{!contributedSection && active === "system-mail-servers" && (
@@ -368,9 +380,8 @@ export default function AdminPage({
{!contributedSection && active === "tenant-group-credentials" && }
{!contributedSection && active === "tenant-user-file-connectors" && }
{!contributedSection && active === "tenant-group-file-connectors" && }
-
-
-
+
+
);
}
diff --git a/webui/src/features/admin/GroupsPanel.tsx b/webui/src/features/admin/GroupsPanel.tsx
index 049576d..31b853a 100644
--- a/webui/src/features/admin/GroupsPanel.tsx
+++ b/webui/src/features/admin/GroupsPanel.tsx
@@ -1,4 +1,4 @@
-import { DescriptionItem, DescriptionList } from "@govoplan/core-webui";
+import { ContentGrid, DescriptionItem, DescriptionList } from "@govoplan/core-webui";
import { useEffect, useMemo, useRef, useState } from "react";
import { Pencil, Plus, Search, Trash2 } from "lucide-react";
import type { FormGrid, ApiSettings, AuthInfo } from "@govoplan/core-webui";
@@ -158,10 +158,10 @@ export default function GroupsPanel({ settings, auth, canDefine, canManageMember
-
+
i18n:govoplan-access.members.1cb449c1 ({ id: user.id, label: user.display_name || user.email, description: user.email, disabled: !canManageMembers || !user.is_active || !user.account_is_active }))} selected={draft.memberIds} onChange={(memberIds) => setDraft({ ...draft, memberIds })} emptyText="i18n:govoplan-access.no_tenant_users_exist.96b4a88a" />
i18n:govoplan-access.inherited_roles.8def9f05 ({ id: role.id, label: role.name, description: role.description, disabled: !canAssignRoles }))} selected={draft.roleIds} onChange={(roleIds) => setDraft({ ...draft, roleIds })} emptyText="i18n:govoplan-access.no_assignable_roles_exist.a4c268c2" />
-
+
i18n:govoplan-access.the_backend_evaluates_the_resulting_access_graph.f318a7dc
diff --git a/webui/src/features/admin/SystemUsersPanel.tsx b/webui/src/features/admin/SystemUsersPanel.tsx
index 481b2a4..fae31ee 100644
--- a/webui/src/features/admin/SystemUsersPanel.tsx
+++ b/webui/src/features/admin/SystemUsersPanel.tsx
@@ -1,4 +1,4 @@
-import { DescriptionItem, DescriptionList } from "@govoplan/core-webui";
+import { ContentGrid, DescriptionItem, DescriptionList } from "@govoplan/core-webui";
import { useEffect, useMemo, useRef, useState } from "react";
import { Search, Pencil, Plus, Trash2 } from "lucide-react";
import type { FormGrid, ApiSettings } from "@govoplan/core-webui";
@@ -250,10 +250,10 @@ export default function SystemUsersPanel({
}
-
+
i18n:govoplan-access.system_roles.a9461aa6 ({ id: role.id, label: role.name, description: role.description, disabled: !canAssignRoles }))} selected={draft.roleIds} onChange={(roleIds) => setDraft({ ...draft, roleIds })} />
i18n:govoplan-access.tenant_memberships.451de736 ({ id: tenant.id, label: tenant.name, description: tenant.slug, disabled: !canManageMemberships || Boolean(draft.memberships.find((item) => item.tenant_id === tenant.id)?.is_last_active_owner) }))} selected={draft.memberships.map((item) => item.tenant_id)} onChange={setMembershipSelection} />
-
+
{editing && editing !== "new" && editing.memberships.some((membership) => membership.is_last_active_owner) && i18n:govoplan-access.this_account_is_the_last_active_operational_owne.5087839f
}
i18n:govoplan-access.removing_a_tenant_checkbox_suspends_that_members.7c6df77d
diff --git a/webui/src/features/admin/UsersPanel.tsx b/webui/src/features/admin/UsersPanel.tsx
index 366d765..cb2eb77 100644
--- a/webui/src/features/admin/UsersPanel.tsx
+++ b/webui/src/features/admin/UsersPanel.tsx
@@ -1,4 +1,4 @@
-import { DescriptionItem, DescriptionList } from "@govoplan/core-webui";
+import { ContentGrid, DescriptionItem, DescriptionList } from "@govoplan/core-webui";
import { useEffect, useMemo, useRef, useState } from "react";
import { KeyRound, Pencil, Plus, Search, Trash2 } from "lucide-react";
import type { FormGrid, ApiSettings, AuthInfo } from "@govoplan/core-webui";
@@ -225,10 +225,10 @@ export default function UsersPanel({ settings, auth, canCreate, canUpdate, canSu
{editing === "new" && setDraft({ ...draft, passwordResetRequired })} />}
{editing && editing !== "new" && editing.is_last_active_owner && i18n:govoplan-access.this_membership_is_the_tenant_s_last_active_oper.072b247f
}
-
+
i18n:govoplan-access.groups.ae9629f4 group.is_active).map((group) => ({ id: group.id, label: group.name, description: group.description, disabled: !canManageGroups }))} selected={draft.groupIds} onChange={(groupIds) => setDraft({ ...draft, groupIds })} emptyText="i18n:govoplan-access.no_groups_exist_yet.9cd029f6" />
i18n:govoplan-access.direct_roles.c4db7156 ({ id: role.id, label: role.name, description: role.description, disabled: !canAssignRoles }))} selected={draft.roleIds} onChange={(roleIds) => setDraft({ ...draft, roleIds })} emptyText="i18n:govoplan-access.no_assignable_roles_exist.a4c268c2" />
-
+
i18n:govoplan-access.group_roles_and_direct_roles_are_combined_the_ba.a43c2f16
@@ -251,7 +251,7 @@ export default function UsersPanel({ settings, auth, canCreate, canUpdate, canSu
i18n:govoplan-access.function_facts.848b32cc>}>{accessExplanation.function_facts.length}
i18n:govoplan-access.role_sources.6f42a672
- {accessExplanation.role_sources.length ?
+ {accessExplanation.role_sources.length ?
{accessExplanation.role_sources.map((source) =>
{source.role_name}
@@ -263,7 +263,7 @@ export default function UsersPanel({ settings, auth, canCreate, canUpdate, canSu
{source.permissions.map((scope) => {scope})}
)}
-
: i18n:govoplan-access.no_role_sources_found.91013aa5
}
+ :
i18n:govoplan-access.no_role_sources_found.91013aa5
}
i18n:govoplan-access.function_facts.848b32cc
{accessExplanation.function_facts.length ?
{accessExplanation.function_facts.map((fact) =>