Skip to main content
stralos-feature-user-settings is the Module Federation widget remote that owns the Your settings panel. It is a manifest v2 kind: widget remote with slot: floating-end. The shell mounts the slot once inside its authenticated layout and passes widgetProps = { assistantOpen }; this remote exposes the panel and its provider. The panel is open to every signed-in member regardless of role. The shell’s authenticated layout controls access; the API scopes every read and write to the caller.

What this remote owns

Exposed entries

The remote exposes one module:
  • ./widget — the UserSettingsWidget component and the RemoteProvider + REMOTE_KEY the shell wraps the slot with.

Host contract

1. Render the widget in the floating-end slot

Inside the authenticated layout the shell mounts the slot:
The assistantOpen prop is passed by the shell’s floating-end slot to every widget in it. This remote does not use that prop; the shared SideSheet resolves its modality when it opens.

2. Dispatch the open event

The shell’s user menu “Your settings” item dispatches:
This is a cross-repository contract. Renaming USER_SETTINGS_OPEN_EVENT in this remote without updating the shell leaves the menu item dispatching into silence.

3. Widget bundle size

The ./widget entry is mounted on every chromed page and must remain Chakra-free. The sheet is a dynamic import() on first open. .ci/remote-size-baseline.json is the accepted gzip sum; build:remote fails more than 10% over it.

API endpoints

All calls are to the Global API (/api/global). Authentication follows the stralos.auth.* / window.__STRALOS_AUTH__ contract.

Response shapes

GET /me/default-office and PUT /me/default-office return:
source values:
  • chosen — the person has an explicit choice stored.
  • first-office — no choice stored, or the choice is no longer an active office; the organisation’s first-created active office is used.
  • none — the organisation has no active offices.
A PUT of null clears the choice, returning the caller to the first-office or none source. A 422 with the code invalid_default_office means the chosen office can no longer be used (it may have been retired); the sheet shows a message asking the person to pick another. Every response is parsed field by field. A shape the client does not recognise is treated as a failure rather than silently accepted.

Default office sheet behaviour

The sheet re-reads the default office on every open so it reflects changes made elsewhere (the Locations screen or an admin in Settings → Users) since the last open. The Save button is disabled until the in-panel choice differs from the stored choice. After a successful save, a live region (visible and announced to screen readers) confirms the saved office name, or says the choice is automatic and names the current stand-in office. If the sheet is closed with unsaved changes, SideSheet’s confirmOnDirtyClose shows a confirmation dialog. The record name in that dialog is Default office.

Federation contract

This remote follows the thin-host contract (PRD D1/D3). Host-provided singletons are react, react-dom, react-router-dom, and react/jsx-runtime, declared as caret ranges in .ci/shell-federation-contract.json. @stralos-co-nz/ui and @stralos-co-nz/domain are exact pins in package.json and are bundled into the remote — they are not shell-provided singletons. src/widget.tsx opens with four specifier-less imports (import "react" etc.) that force @module-federation/vite to keep each import: false share’s full export surface. Deleting them makes the build intermittently red. See the file header and src/shareGuard.test.ts for the mechanism.