c49a807966
The "Role: Anonymous / User / Administrator" widget at the bottom of
the portal-shell sidebar always struck the same audience as the user
menu — it told the reader who they were and what they could do. With
the menu now carrying the full identity card (displayName, username,
role-curated actions like "Open Portal Admin"), keeping the role
in the sidebar duplicates the surface and surfaces the label on
anonymous traffic where it carries no real information ("Role:
Anonymous" was a verbose synonym for "Sign in").
This PR moves the role chip into the user-menu panel header, where
it sits between the username and the menu rows. Hidden on anonymous
traffic by construction — the `<lib-user-menu>` only renders for
the authenticated case in both apps' headers.
Shape:
* `UserMenu` (shared-ui) gains an **optional `role` input**. When
set, a small brand-tinted pill renders inside the panel header
below the username (`data-testid="user-menu-role"`). When
undefined, the entire chip is omitted — keeps backwards compat
with any future caller that doesn't carry a role concept.
* `portal-shell`'s header computes `roleLabel` from the existing
`CapabilitiesService.canAccessAdmin` signal (the same logic that
previously lived in the sidebar), passing the localised string
through the new input. The sidebar role widget — HTML +
`roleLabel` / `roleAriaLabel` computeds + the `AuthService` and
`CapabilitiesService` injections — is removed.
* `portal-admin`'s header passes a hardcoded `'Administrator'`.
Every reader who reaches the admin app already carries
`Portal.Admin` (guard precondition); no need to re-derive. No
i18n marks per ADR-0020's source-locale-only chrome.
* The `sidebar.role.{anonymous,administrator,user,aria,label}`
translation units are removed from `messages.fr.xlf`. Replaced by
`common.role.{administrator,user}` (the new owners are the user
menu in either app, hence the generic prefix). The "Anonymous"
string is gone too — the chip is hidden on anonymous traffic, the
label served no purpose without the user menu rendering it.
* The portal-shell sidebar spec drops its three "role label" tests
(the widget is gone) and grows a guard test asserting the
`data-testid="sidebar-role"` element no longer exists. The
setup is simplified back to the pre-#151 shape — no Http
testing infrastructure needed, since the sidebar no longer
injects `AuthService` / `CapabilitiesService`.
* The portal-shell header spec gains two assertions for the role
chip inside the open menu panel (Administrator / User).
* The shared `UserMenu` spec gains two assertions covering the new
input's presence/absence semantics.
Verification:
* 43 portal-shell specs pass (header +2, sidebar -2 net, balanced).
* 50 portal-admin specs pass (no spec edits).
* 10 shared-ui specs pass (was 8, +2 for the role chip).
* `pnpm nx run portal-shell:build:production` (i18n-strict) green
— confirms the xlf cleanup + new `common.role.*` keys are
consistent with the source-locale usage.