Contract-freeze · UX approval
App scopes, the consolidated user menu & notifications
Four changes to the shell's identity surface plus the inbox behind the bell.
Approving these frames freezes the interaction model and the build inventory below, before
any of it is implemented. Built in the fuse-seam design system (tokens only).
Plan of record: docs/planning/app-scopes-user-menu-notifications.md.
Frame (a)
Consolidated user menu
Account, organization and language in one avatar menu; the top bar sheds the org and
language controls.
Frame (b)
Parallel accounts
Up to five signed-in accounts, per-tab pinning, the cap, per-account sign-out, an expired
parked session — and the storage-namespace isolation contract.
Frame (c)
Install scope & mode
Personal vs organization, install-for-me vs install-for-everyone, the role guard, and the
accept/reject matrix the API enforces.
Frame (d)
Notifications
Inbox, badge states, live SSE arrival, and quiet degradation when the service is down.
Frame (e)
Cross-cutting states
Menu loading, no organizations, failed org fetch, failed language switch, and the mobile sheet.
What approving this builds
Approving these frames approves this inventory. The implementation builds exactly
these flows, components and services — it cannot quietly invent a different architecture.
- Flows
-
ShellUserMenu → /
AccountSwitcherSection → /
InstallAppDialog → /apps
NotificationBell → /
- Components
-
UserMenu
AccountSwitcherSection
OrganizationSwitcherSection
LanguageSection
InstallAppDialog
NotificationBell
NotificationPanel
NotificationItem
- Modules & services
-
frontend/src/lib/accounts.ts
frontend/src/contexts/AccountsContext.tsx
frontend/src/services/notifications.ts
services/notification-service
backend: apps.scope_level + app_installations
- Design-system additions
-
none — built from existing primitives (Avatar, Badge, Modal, Select, Skeleton, StatusCallout, EmptyState, Spinner)
● Awaiting approval
Design system: @fuzefront/design-system (fuse-seam) ·
Contract: services/notification-service/openapi.yaml ·
Backend: /api/apps/:id/install, /api/v1/notifications.
Approval is written per-flow into manifest.json by the design-approval workflow —
reply @claude approve / @claude reject: <reason>.
Re-stamp after any edit: node scripts/stamp-frames.mjs --write.