Repository navigation
[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 #8096
Description
Activity
- addedbugSomething isn't workingSomething isn't workingand removed
on Aug 12, 2026 Finding-grading round: promoted to
pm:queue(lanerepo:objectui, type Bug — lands in objectuipackages/app-shell).All three doors re-verified shut in objectui
origin/main:WorkspaceSwitcher.tsx:87returns null fororgList.length <= 1,AppHeader.tsx:896-907kept only?create=1(comment claims "My Organizations" moved to the switcher — the switcher single-org users never see),OrganizationsPage.tsxstill documents the?manage=1avatar entry that no longer exists. Narrowest fix is what the code's own comment declares should exist: restore the avatar-menu "My Organizations" →/organizations?manage=1. Invariant-restoring, no product call. Siblings: walkthrough cards #8090–#8094.
Generated by Claude Code
- addedpriority:p0Critical: blocker, must ship before MVPCritical: blocker, must ship before MVP
on Aug 13, 2026 Claim: PM loop round 1
Session:session_01RnQd8iMMUwXQEV1crFmQiQ
Branch:claude/issue-8096-manage-entry
Worktree:objectui-issue-8096
Domain:repo:objectui
File surface:packages/app-shell/src/layout/AppHeader.tsx(avatar menu) +packages/app-shell/src/console/organizations/OrganizationsPage.tsx(stale-comment reconciliation only) + app-shell locale resources if the menu label key does not already exist + matching tests (stop on breach; explain in the report)
Container & model: S–M,mode:subagent,model: opus
Serial constraints cleared: in-flight this batch: #8500 declarespackages/app-shell/src/views/(disjoint files, same package — no barrel edits expected on either side); #8282/#8270 touch the same console/organizations + locale surfaces and are deliberately held for a later round (serial); no open dev PR touchespackages/app-shell/src/layout/(checkedorigin/mainlog + open PR list this round).
Generated by Claude Code
{ "issue": 8096, "status": "done", "branch": "claude/issue-8096-manage-entry", "pr": "https://github.com/objectstack-ai/objectui/pull/4638", "premise_still_valid": true, "summary": "Restored the avatar-menu \"My Workspaces\" entry navigating to /organizations?manage=1 in packages/app-shell/src/layout/AppHeader.tsx — the narrowest declared fix. WorkspaceSwitcher.tsx was not touched and no Setup-side links were added, per the 裁决. All three doors re-verified shut on origin/main (5bf5d2cb6) before implementing. One premise sub-detail is WRONG and the PM should note it: `?manage=1` does NOT suppress the single-org auto-skip as OrganizationsPage:42's comment claims — the manage-mode branch at :130 RE-TARGETS the auto-skip at /organizations/<slug>/members instead. That is better than the card assumed, not worse: the restored entry deep-links a single-org user straight into member management rather than showing a pointless one-item picker, so it does not dead-end and the 裁决's stop-condition was not triggered. Route confirmed end-to-end (apps/console/src/App.tsx:298-307 → members/invitations/settings). Reused the existing `organizations.mine` key — already shipped in all ten locale packs and left dormant when the entry was removed — so NO locale files were touched. Entry deliberately not gated on `multiOrgDisabled` (that flag governs CREATE; where self-service creation is off this entry is the only door).", "tests": "All at HEAD bc89db3 (verification run followed the final commit; nothing pushed after). Repo convention followed per objectui AGENTS.md §'怎么跑测试': repo-root `pnpm exec vitest run <path>`, NOT `pnpm --filter <pkg> test` (that form is a documented silent-false-green trap here — it runs apps/console's 22 files and reports green). Build closure first: `pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build` → exit 0.\n\n(1) New test packages/app-shell/src/layout/__tests__/AppHeader.myOrganizations.test.tsx, 5 cases → with WorkspaceSwitcher.test.tsx + OrganizationsPage.test.tsx: 'Test Files 3 passed (3) / Tests 11 passed (11)'.\n(2) REVERSE VERIFICATION, direction predicted before running: all 5 cases assert on the `header-my-organizations` testid, so reverting AppHeader to origin/main must fail all 5 — not 1, not 4. Observed exactly 'Test Files 1 failed (1) / Tests 5 failed (5)'. Fix was COMMITTED first, so restore was `git checkout claude/issue-8096-manage-entry -- <path>`, confirmed byte-identical via `git diff --quiet HEAD`.\n(3) Blast radius `vitest run packages/app-shell/src/layout/ packages/app-shell/src/console/organizations/` → 'Test Files 36 passed (36) / Tests 255 passed (255)'.\n(4) `pnpm --filter @object-ui/app-shell type-check` (tsc --noEmit && tsc -p tsconfig.test.json) → exit 0.\n(5) eslint on the 3 changed files → 0 errors, 44 warnings (all `any`/unused-destructure inside the test's mock factories, identical in kind to sibling AppHeader.inboxVariant.test.tsx).\n(6) Gates re-derived against actual changed paths, beyond the ones named in dispatch: check:control-bytes OK (4174 files), check:i18n-keys OK (confirms `organizations.mine` resolves against the en pack AND the inline defaultValue matches its value exactly — this is what validates the key reuse), check:i18n-drift OK (0 en values changed), check-changeset-presence OK (1 changeset for 2 changed source files of a released package). check:i18n-keys/i18n-drift were NOT in the dispatch gate list; they are implicated because the change adds a t() call site, and both are green.\n\nNOTE — one self-inflicted lap worth recording: the new test first died with a V8 heap OOM ('Worker exited unexpectedly'), not an assertion failure. Cause was in my test harness, not the fix: the mocked `useAuth` returned a fresh `getAuthConfig` arrow per call, and BOTH AppHeader and WorkspaceSwitcher have `useEffect(..., [getAuthConfig])` ending in setState — new identity every render ⇒ effect ⇒ setState ⇒ render, until the heap died. Same defect via a per-call `useAdapter` object. Fixed by hoisting both to stable module-level identities (the sibling inbox test dodges this by passing `getAuthConfig: undefined`). Recorded because the failure mode reads like an environment problem and is not one.", "open_questions": [], "out_of_scope_findings": [ "filed as #8669: the `organizations.*` locale family is half-renamed — 8 of 10 packs (ar/de/es/fr/ja/ko/pt/ru) followed the workspace rename for `create` ONLY, so e.g. de now renders 'Meine Organisationen' two lines above 'Workspace erstellen' in the same dropdown. Newly visible because this PR revives the dormant `organizations.mine` key. Labeled `finding` (observation-class), no pm:queue. Existing gates are structurally blind to it: key-parity sees every key present, i18n-drift only follows en changes, i18n-keys only compares against en." ] }Lock/scope notes for the PM:
- Shared verification lock contention was significant this round.
/tmp/os-heavy-verify.lockwas held ~30 min by PID 12098 running an unfiltered full-repo suite (flock … -c 'pnpm exec vitest run --maxWorkers=2', no path filter). I queued through three bounded-wwindows (~27 min total), spending each interval on lock-free work (changeset, cheap gates, commit, PR body), then batched every remaining heavy step into a single acquisition. Not blocked in the end, but if full-repo runs under the lock are routine this round's card latency was mostly queueing, not work. - Sibling-agent boundary respected:
packages/app-shell/src/views/and the barrelsrc/index.tswere not touched. Final diff is 4 files:layout/AppHeader.tsx,console/organizations/OrganizationsPage.tsx(comments only), the new test, and.changeset/tidy-donkeys-attack.md. - The
testslabel on PR feat(spec)!: 双源 C3 收敛 — 通知语汇归 ./api,./ui 与 ./system 侧死删 (#4610) #4638 was applied by another actor, not me — left as-is per ground rule 2. Noskip-changesetlabel is needed: this is a user-visible change in a published package and carries a changeset. - CI was still converging (
mergeable_state: unstable) at report time; per the 2026-08-10 ruling the convergence wait is the PM's.
Generated by Claude Code
Generated by Claude Code
- Shared verification lock contention was significant this round.
ACCEPT — PR objectstack-ai/objectui#4638 (reviewer of record: seat session
session_01RnQd8iMMUwXQEV1crFmQiQ).Verified against GitHub: diff is 4 files exactly as claimed (AppHeader.tsx, OrganizationsPage.tsx comments-only, the new 5-case test, one changeset); the declared narrowest fix and nothing else — WorkspaceSwitcher untouched, no Setup links, no locale files (existing
organizations.minekey reused, validated bycheck:i18n-keys). Reverse verification predicted 5/5 RED on revert and measured exactly that. Premise sub-correction accepted and publicly recorded:?manage=1re-targets the single-org auto-skip at/organizations/<slug>/members(a deep-link into member management) rather than "showing the picker" as the code comment claimed — better than the card assumed; the restored entry does not dead-end. Changeset present (user-visible change in a published package). The earlier shard-3 CI red was the base-branch failure (objectui#4642), fixed and merged — the PR now goes ready + auto-merge through the queue.Fixesfirst line is correct: merge closes this card.Out-of-scope finding #8669 (half-renamed
organizations.*locale family) verified filed, unassigned, observation-class — enters this seat's grading pool.
Generated by Claude Code
- added a commit that references this issue
on Aug 17, 2026
Recording an observation for the platform to rule on.
A user who belongs to exactly one organization appears to have no UI path to the workspace management pages (
/organizations/<slug>/members·/invitations·/settings). Three mechanisms that are each individually reasonable close every door at once:/organizationsauto-skips. Deliberate, and documented as such:Confirmed empirically: with one org,
GET /_console/organizationslands on the last app page; after creating a second org, the same URL renders the picker.The workspace switcher is hidden with a single org. Verified: the top bar shows no workspace control until the user has ≥2 organizations, at which point the switcher (with its Manage members item) appears. Sensible on its own — but it is the only entry point to the manage pages.
The avatar menu has no "My Organizations" item. The comment right above the auto-skip explains that this is what should reopen the picker:
Observed avatar menu (zh, both a single-org and a two-org user): 个人资料 / 创建工作区 / 主题 / 语言 / 注销.
创建工作区is the?create=1entry and works; there is no?manage=1entry.Net effect: a single-org owner cannot reach Members / Invitations / Organization settings without hand-typing
/_console/organizations?manage=1. Inviting still works from Setup → Users → Invite user, so the workspace is not unusable — but role changes, invitation cancellation, renaming the org and deleting it are all only in those pages.The decision
Either restore the
?manage=1avatar-menu item the comment describes, or show the workspace switcher unconditionally (a one-org switcher is a bit redundant but carries Manage members), or point Setup at the manage pages. If single-org users are intentionally not meant to reach these pages at all, the stale comment should go instead.Environment
Local dev server
http://localhost:8080, multi-org enabled, zh locale, observed 2026-08-12. The server was started by the maintainer and its exact commit is not verified; the source quoted is the currentobjectuimain checkout.