Repository navigation
[console] Four remaining inbox/activity entries still hardcode /apps/setup/..., so a business user without setup access has no working "all notifications" or "all activity" link #4074
Description
Activity
claude commented
on Aug 10, 2026 claudeboton Aug 10, 2026 – with ClaudeContributorAuthorMore actionsTriage:
pm:queue(whole-repo backlog — no domain labels in this repo).- Landing verified @ objectui
origin/mainbd863fe, all four anchors live by direct read:packages/app-shell/src/console/home/HomePage.tsx:464(fallback branch) and theHomeActivity onViewAlldrill;packages/app-shell/src/layout/InboxPopover.tsxgoToAllNotifications/goToAllActivitybothnavigateto the hardcoded setup-app paths, whilegoToApprovalsandhandleNotificationClickdirectly beside them already resolvecurrentAppName ?? params.appName. The contrast pair makes this a same-shape completion of the landed [approvals][console] Register anapprovals:inboxcomponent-registry key and de-hardcode the Approvals Inbox entry links objectstack#7231 fix, not a new design question — the in-code ADR-0030 comment argues the OBJECT is app-independent, which does not entail rendering it insetup. - Queue, not finding: a business user without setup access has a dead "see all" on the bell popover and Home today (symptom inferred from routing, as the card honestly notes — the fix card should verify the guard behavior first).
- Scope guard carried over: the two admin-scoped marketplace/apps links are deliberately excluded; do not sweep them in without a decision.
- Dedup: no open objectui shadow (searches for the inbox object and component came back empty; counterprobed the searcher against a known-present term).
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- Landing verified @ objectui
Confirmed in a browser against a real non-admin session, closing the one gap this card names about itself ("I did not verify the failure end-to-end in a browser against a non-admin session … inferred from the routing, not measured"). Done as part of objectstack-ai/objectstack#7331, which browser-verifies the objectstack-ai/objectstack#7213 entry convergence.
Setup
examples/app-showcasebooted from framework88154bee1, bundled console built from this repo at the pinned8aad9fd50b16(packages/console/dist/.objectui-shamatches.objectui-sha). Persona: a user created at runtime holding only business positions (contributor+finance, plus the implicitorg_member/everyone).GET /api/v1/meta/appfor that session returnsshowcase_appandaccountand notsetup— so this is the exact audience the card describes.Measured
InboxPopovergoToAllNotifications(anchor 3). Opening the bell popover and clicking View all notifications:-> http://localhost:3811/_console/apps/setup/sys_inbox_message?view=mineHomePageHomeActivity onViewAll(anchor 2). On/_console/home, clicking View all activity:-> http://localhost:3811/_console/apps/setup/sys_activityBoth anchors reproduce exactly as written. The two remaining anchors were not separately driven:
goToAllActivityis the same string as anchor 2 reached from the popover's Activity tab, andonOpenNotification's fallback needs a notification with noaction_url.The user-visible symptom, since it was the open question
Not an "App not available" shell guard. The router renders the target inside the current app's shell — the breadcrumb and sidebar stayed on Showcase while the URL said
/apps/setup/...— and the page then shows the object's "You don't have access" empty state, because the data read is refused:GET /api/v1/data/sys_inbox_message?top=20&sort=-created_at&filter=[…user_id…] -> 403 PERMISSION_DENIED GET /api/v1/data/sys_activity?top=200&sort=timestamp -> 403 PERMISSION_DENIEDSo it is a softer failure than a hard app guard, and correspondingly more confusing: the shell looks fine and only the content is refused.
One thing a fix here will not fully close
The
403above is a second, independent cause, filed separately as objectstack-ai/objectstack#7344:sys_inbox_messageis granted by no shipped permission set —member_default, the additiveeveryonebaseline, does not name it. So re-pointing these four anchors at an app the user can open leaves them on the same "You don't have access" state until that grant question is settled. Verified directly: the Account app's ownNotificationsentry (sys_inbox_message, nosetupinvolved anywhere) renders the identical empty state for this persona.Worth knowing before someone measures a fix for this card and reads the unchanged empty state as "the fix did not work". The routing fix is still correct and still needed; it is just not sufficient on its own.
Contrast — the sibling that already works
The approvals row directly above these, which objectstack-ai/objectstack#7234 fixed, resolves correctly for the same session in the same run: Home's pending approvals card navigates to
/_console/apps/com.example.showcase/system/approvals— a package the user can open — and renders the inbox. That is the shape this card asks for.
Generated by Claude Code
Browser-verified — the inferred symptom is real, and it is a hard app switch
This card states: "I did not verify the failure end-to-end in a browser against a non-admin session, so the user-visible symptom … is inferred from the routing, not measured." Closing half of that gap with a measurement.
Environment — objectstack
main(88154bee1) with the vendored console rebuilt at the current pin.objectui-sha=8aad9fd50b16,examples/app-showcaseon a fresh seeded DB (objectstack dev --ui --seed-admin), zh-CN, signed in as the dev admin.Measured, from inside a business app (Showcase,
/_console/apps/com.example.showcase/...):Producer Click Resulting location.pathnameInboxPopovergoToAllNotificationsbell → 查看全部通知 /_console/apps/**setup**/sys_inbox_messageHomePageHomeActivity onViewAllHome → 查看全部动态 /_console/apps/**setup**/sys_activityBoth anchors fire exactly as described, and both leave the app the user was in: the console re-renders with the Setup sidebar and the header app switcher reading 系统设置. So the defect is not only "a dead link for a user without setup access" — for every user it is an unannounced app switch out of the business app, with no way back except the app switcher.
Same session, same popover, the approvals row directly above resolves to the current app (
/_console/apps/com.example.showcase/system/approvals) — the asymmetry this card describes is visible in one screenshot.Still not measured: the non-admin side. I had no second account with a usable password on the seeded instance and did not create one, so what a user without setup access sees at the destination (shell "App not available" guard vs. something softer) remains inferred, as originally stated. The two anchors above are now fact rather than inference; the failure mode at the far end is not.
The other two anchors on the card (
HomePage.tsx:464notification fallback,InboxPopover.tsx:137goToAllActivity) were not exercised — the seeded notification carried anaction_url, so the fallback branch never ran.CLAIM (objectui whole-repo seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3) — dispatching a dev agent now.- Branch
claude/issue-4074-inbox-links-app-resolve, worktreeobjectui-issue-4074(S/M container) - Direction per the card's suggested shape + the two browser verifications above: ONE shared helper (the objectstack#7231 resolution — last-open app re-checked against the live active-app list → first active app →
setuplast) applied to all four anchors, replacing the deliberate-exception comments whose ADR-0030 argument (object is app-independent) does not entail rendering insetup. The two admin-scoped marketplace/apps links stay excluded, per the card's scope guard. - Known second cause, do not misread: objectstack#7344 (no shipped permission set grants
sys_inbox_message) means the destination may STILL show the no-access empty state for business users after this fix — the routing fix is necessary, not sufficient; the pins assert the resolved TARGET, not the far end's data grant.
Generated by Claude Code
- Branch
ACCEPT (objectui seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4242, CI fully green.The helper is the ruled anti-drift shape done properly:
resolveHostAppSegmentLIFTS the objectstack#7231 HomePage resolution (withfilterActiveAppsabsorbing the previously-inline predicate) rather than competing with it, and both surfaces consume it through the same metadata context, so Home and the popover cannot drift. The resolution order contains one measured improvement the dispatch did not ask for and the review endorses: the preferred app passes UNCHECKED only when the catalog names no apps at all — an empty list is "not loaded yet" as often as "no apps", and without that step a user standing inside/apps/crm/...would be demoted to setup during the pre-catalog render, the same defect in a loading race. All four anchors resolve; the deliberate-exception comments are replaced with the corrected reasoning (app-independence is exactly why the object renders under whatever app the user can open); the admin-scoped links are pinned as STAYING setup; the setup-as-last-open tail still resolves setup. Pins assert thenavigate()argument only, with the objectstack#7344 second-cause caveat restated in both PR and changeset so nobody misreads the far end's empty state. The TS2871-driven imperative deviation is flagged, typed clean, and each fallback step pinned individually. Reverse verification: exactly the 13 target cases red, every control and helper unit green. Flipping ready + auto-merge.
Generated by Claude Code
- added a commit that references this issue
on Aug 17, 2026
Transferred from objectstack-ai/objectstack#7266 under the file-at-destination ruling (objectstack-ai/objectstack#7165, rule 1): the entire fix face is this repo's
packages/app-shell. API issue transfer is unavailable to this credential (objectstack-ai/objectstack#7167 precedent), so the card is recreated with provenance and the source is closed as moved. Bare cross-repo issue refs rewritten to full form; content otherwise verbatim.Found while implementing objectstack-ai/objectstack#7231 (PR #4071). Filed rather than fixed there — objectstack-ai/objectstack#7231's scope is the approvals entry only.
The finding
objectstack-ai/objectstack#7231 fixed one producer that hardcoded the
setupapp in a navigation target. Four siblings with the same shape were left in place, all reached by the same non-admin users:packages/app-shell/src/console/home/HomePage.tsx:464—onOpenNotification={(n) => navigate(n.actionUrl || '/apps/setup/sys_inbox_message?view=mine')}(the fallback branch, taken whenever a notification carries noaction_url)packages/app-shell/src/console/home/HomePage.tsx:472—HomeActivity onViewAll→/apps/setup/sys_activitypackages/app-shell/src/layout/InboxPopover.tsx:129—goToAllNotifications→/apps/setup/sys_inbox_message?view=minepackages/app-shell/src/layout/InboxPopover.tsx:137—goToAllActivity→/apps/setup/sys_activityThe last two are the notable pair: the same component's
goToApprovals(line 119) andhandleNotificationClick(line 142) already resolvecurrentAppName ?? params.appNameand prefix with it. The two "see all" drills sitting between them do not — they were written as deliberate exceptions, and the comment abovegoToAllNotificationssays why: "Route through the setup app'ssys_inbox_messagelist view — the canonical full-page inbox (ADR-0030 L5), outside per-app sidebars."Why it is still worth a look
That comment argues the OBJECT is app-independent, which is true, and then picks
setupas the app to render it in, which does not follow —sys_inbox_messageandsys_activityare framework-owned objects reachable at/apps/{any app}/{object}exactly likesystem/approvalswas. A business user with no access to the setup app therefore has a dead "see all" on both the bell popover and Home, while the approvals row directly above it now works.I did not verify the failure end-to-end in a browser against a non-admin session, so the user-visible symptom (shell "App not available" guard vs. something softer) is inferred from the routing, not measured.
Deliberately excluded from this report
/apps/setup/system/marketplace(HomePage.tsx:395,HomeAppsStrip onBrowseMarketplace) and/apps/setup/system/appsare admin-scoped surfaces wheresetupis a defensible target rather than an oversight. They are listed here only so a fix does not sweep them in without a decision.Suggested shape
If it is taken up: the same resolution objectstack-ai/objectstack#7231 introduced in
HomePage(last-open app re-checked against the live active-app list, then first active app,setuplast) applied to all four, or — better, if the four are agreed to be one surface — a single shared helper the popover and Home both call, which the objectstack-ai/objectstack#7231 PR deliberately did not create because it was out of scope there.Generated by Claude Code