Skip to content

fix(app-shell): restore the avatar menu "My Workspaces" entry - #4638

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-8096-manage-entry
Aug 14, 2026
Merged

fix(app-shell): restore the avatar menu "My Workspaces" entry#4638
yinlianghui merged 1 commit into
mainfrom
claude/issue-8096-manage-entry

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixesobjectstack-ai/objectstack#8096

The defect

A user belonging to exactly one organization had no UI path to the workspace
management pages (Members / Invitations / Organization settings). Three
individually reasonable behaviours closed every door at once:

  1. /organizations auto-skips the picker at one org (UX P0-1, deliberate).
  2. WorkspaceSwitcher returns null at one org or fewer, so the header-left
    switcher — and its "Manage members" item — never renders for them.
  3. The avatar menu kept only the ?create=1 entry, having dropped the
    ?manage=1 "My Organizations" one on the assumption that (2) covered it.

Reaching member management required hand-typing /_console/organizations?manage=1.

The fix

Restore (3) — the narrowest change, and the one both AppHeader's and
OrganizationsPage's own comments already documented as the intended design.
The switcher's single-org early return is deliberately left alone, and no
Setup-side links were added.

The destination is load-bearing rather than cosmetic. ?manage=1 is what
OrganizationsPage reads as "the user came here to manage": with two or more
orgs it shows the picker, and with exactly one it re-targets the auto-skip at
/organizations/:slug/members instead of bouncing the user home. So the
restored entry lands a single-org user directly on member management — it does
not dead-end in the very auto-skip this card is about.

The entry is deliberately not gated on multiOrgEnabled. That flag governs
creating organizations (it is why "Create workspace" is gated); where
self-service creation is disabled this entry is the only way in, so gating it the
same way would re-close the door.

Label

Reuses the existing organizations.mine key rather than minting one. It is
already shipped in all ten locale packs and had been left dormant when the entry
was removed — no locale files are touched, and check:i18n-keys confirms the
inline defaultValue matches the en pack value exactly.

Comment reconciliation

OrganizationsPage's comment claimed ?manage=1 "shows the picker". For the
single-org majority it does not — it re-targets the auto-skip at that org's
members page, which is what makes the restored entry a real door. Corrected to
describe both branches; AppHeader's comment (which claimed the entry had moved
to the switcher) is rewritten to record why the avatar menu has to carry it.

Verification

All at bc89db3 (the tip of this branch; no commits followed the run).

  • New testpackages/app-shell/src/layout/__tests__/AppHeader.myOrganizations.test.tsx
    — 5 cases. Asserts the entry exists for a single-org user, navigates to
    /organizations?manage=1 verbatim, is present while the real switcher renders
    nothing
    (the precondition that made this bite), survives multiOrgEnabled: false, and is still offered to multi-org users.
  • Reverse verification — direction predicted before running: since all five
    cases assert on the header-my-organizations testid, reverting AppHeader to
    origin/main must fail all five. Observed exactly Tests 5 failed (5);
    restore confirmed byte-identical to HEAD via git diff --quiet HEAD.
  • Blast radiusvitest run packages/app-shell/src/layout/ packages/app-shell/src/console/organizations/:
    Test Files 36 passed (36), Tests 255 passed (255).
  • Type-check@object-ui/app-shell type-check (tsc --noEmit plus
    tsconfig.test.json): exit 0.
  • ESLint on the three changed files: 0 errors (44 warnings, all any /
    unused-destructure in the test's mock factories, matching the sibling
    AppHeader.inboxVariant.test.tsx house style).
  • Gatescheck:control-bytes, check:i18n-keys, check:i18n-drift,
    check-changeset-presence: all green.

A .changeset is included: this is a user-visible behaviour change in a
published package.


Generated by Claude Code

Users in exactly one organization had no UI path to the workspace
management pages (Members / Invitations / Organization settings). Three
individually reasonable behaviours closed every door at once:
1. `/organizations` auto-skips the picker at one org (UX P0-1);
2. `WorkspaceSwitcher` returns null below two orgs, so the header-left
switcher and its "Manage members" item never render;
3. the avatar menu kept only the `?create=1` entry, having dropped the
`?manage=1` one on the assumption that (2) covered it.
Restore (3), which both AppHeader's and OrganizationsPage's own comments
already documented as the intended design. The entry is deliberately not
gated on `multiOrgEnabled`: that flag governs CREATING organizations, and
where self-service creation is off this entry is the only way in.
Reuses the existing `organizations.mine` key, which is already shipped in
all ten locale packs and had been left dormant when the entry was removed.
Also reconciles the now-inaccurate comments. OrganizationsPage's said
`?manage=1` "shows the picker"; for the single-org majority it does not —
it re-targets the auto-skip at that org's members page. That is what makes
the restored entry a real door rather than a dead end.
Fixesobjectstack-ai/objectstack#8096
@vercel

vercelBot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectuiIgnoredIgnoredAug 14, 2026 10:59am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)24.7 KB350 KB
Entry fileindex-DMqGkWBm.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.56KB3.59KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)25.13KB5.40KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)38.46KB10.17KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.35KB1.07KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)489.88KB108.67KB
core (index.js)3.79KB1.52KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)163.56KB44.83KB
fields (index.js)230.37KB57.17KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)3.35KB1.38KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.12KB7.62KB
i18n (useDisplayLocale.js)2.84KB1.45KB
i18n (useObjectLabel.js)27.59KB6.63KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)38.98KB10.85KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.75KB3.06KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)3.67KB1.12KB
permissions (evaluator.js)4.41KB1.44KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.55KB0.71KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.86KB12.91KB
plugin-charts (index.js)62.10KB17.67KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)121.84KB31.74KB
plugin-designer (index.js)212.58KB42.83KB
plugin-detail (index.js)239.93KB60.01KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)114.72KB27.70KB
plugin-gantt (index.js)164.30KB40.02KB
plugin-grid (index.js)190.02KB50.48KB
plugin-kanban (index.js)52.74KB14.53KB
plugin-list (index.js)112.01KB27.27KB
plugin-map (index.js)18.16KB5.81KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)41.38KB11.09KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.09KB20.56KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.71KB3.53KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.67KB2.37KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)27.64KB9.44KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.26KB0.67KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)4.47KB2.03KB
sdui-parser (parse.js)10.04KB2.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)4.69KB1.48KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.05KB1.52KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@yinlianghuiClaude

Copy link
Copy Markdown
CollaboratorAuthor

CI note: the Test (shard 3/4) failure on head bc89db3 is the base-branch failure tracked as #4642 (QUICK_REFERENCE.md says 17.4.0 after the 17.5.0 release commit) — not this PR's diff. Re-runs once main recovers.


Generated by Claude Code

@yinlianghui
yinlianghui marked this pull request as ready for review August 14, 2026 15:19
@yinlianghui
yinlianghui added this pull request to the merge queueAug 14, 2026
Merged via the queue into main with commit 67b0119Aug 14, 2026
20 of 21 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-8096-manage-entry branch August 14, 2026 15:19
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] single-org users have no UI path to the workspace manage pages — the ?manage=1 avatar-menu entry the code describes does not exist

2 participants

@yinlianghui@claude