Skip to content

console: /home 的 Administration 组被压平成一条指向 /home 的死链——整簇 9 个系统管理入口在参考 console 上不可达 #3609

Closed

Description

@yinlianghui

越界发现,记录于 #3590(改三处 sys-settings 的目标 URL)期间。按纪律只报不改,单独立单,未认领,留给 PM 分诊。

实测基线:origin/main @ 03f25f7a3。

现象

工作区管理员在 /home 上,左侧栏出现一个 Administration 条目。点它 —— 什么也不会发生:它是一条指向 /home 的链接,也就是用户已经站着的那一页。它下面本该有的 9 个系统管理入口(System Settings / Applications / App Marketplace / Object Manager / Datasources / Users / Organizations / Roles / Configuration)一个也没有渲染到 DOM 里。

零应用部署下这条路径尤其要命:resolveLandingPath([]) 返回 /home,所以全新环境的管理员第一屏就是 /home,而这里是他唯一的系统管理入口。

实测链路

packages/app-shell/src/layout/UnifiedSidebar.tsx(行号为 03f25f7a3):

  1. 312–341 行 homeNavigation:管理员额外拿到一个 type: 'group' 的 sys-administration,children 为上述 9 项。

  2. 437 行只有一个三元 —— context === 'app' && activeApp ? (…) : (…)。

  3. app 分支(504 行)渲染 NavigationRenderer,那才是会递归进 type: 'group' 子项、把组渲染成 Collapsible 的组件。

  4. home 分支(约 594 行起)是手写的:

    homeNavigation.map((item) => … Link to={item.url || '/home'} … span{item.label} …)
    

    —— 不递归。组自身没有 url,于是 item.url || '/home' 回退到 /home;子项从未被访问。

也就是说:type: 'group' 在 home 上下文里根本不被支持,而 home 导航偏偏是唯一用组来结构化的那份。

复现

以工作区管理员身份打开 /home,看左侧栏的 Administration:一条死链,展不开。

jsdom 侧的证据已随 #3590 的 PR 落库为一条 MEASUREMENT 钉(packages/app-shell/src/layout/__tests__/systemNavSettingsTarget.test.tsx):

expect(screen.getByRole('link', { name: 'Administration' })).toHaveAttribute('href', '/home');
expect(screen.queryByRole('link', { name: 'System Settings' })).not.toBeInTheDocument();
expect(screen.queryByRole('link', { name: 'Applications' })).not.toBeInTheDocument();

该单一旦修好,这条钉会转红 —— 那正是它设计的信号:届时应把它换成真实的 href 断言。

影响

console/home/HomePage.tsx:289 的注释写着「(系统入口)已经在 nav(UnifiedSidebar)里了,所以中间不再挤一个 System 卡片」。换句话说,HomePage 主动撤掉了自己的系统入口,把职责交给了这份渲染不出来的侧栏导航。净效果:参考 console 的 /home 上,管理员没有任何通往系统管理的入口。

可能的修法(留给分诊)

  • home 分支复用 NavigationRenderer(与 app 分支同一条渲染路径,组、权限门、pin 全部自动一致);
  • 或退一步:手写 map 里补一层组递归。

前者更符合「一份导航渲染器」的方向,也顺带让 home 导航拿到 app 导航已有的全部 item 级守卫。

关联

已就关键词(homeNavigation / Administration / UnifiedSidebar / sidebar group / 导航 组 压平)搜过三仓开放 issue 与 PR,无同源单。

Activity

  1. claude commented on Aug 7, 2026

    @claude
    Contributor

    Triage: pm:queue — confirmed live, and it already carries its own regression pin

    Verdict. Queued. No domain:* (objectui is a whole-repo seat). This is the sharpest card of the zero-app console cluster: nine system-administration entries unreachable, on the one screen a fresh-deployment admin lands on.

    Premise re-verified against origin/main @ 616353a (your baseline 03f25f7a3 predates #3590's merge; coordinates moved, facts did not):

    • UnifiedSidebar.tsx:343 still declares sys-administration as type: 'group' with the nine children.
    • The hand-written home branch still renders <Link to={item.url || '/home'}> — now at :606 (your citation said ~594). Still non-recursive, so a group with no url of its own falls back to /home and its children are never visited.
    • The pin you left behind exists on main: packages/app-shell/src/layout/__tests__/systemNavSettingsTarget.test.tsx.

    Why the existing pin matters to the fix rather than just documenting it. That test currently asserts the broken state — Administration has href="/home" and System Settings is absent from the DOM. It is a MEASUREMENT pin, not a guard, so the fix must flip it, and flipping it is the acceptance criterion. Whoever claims this should not add a parallel test and leave the old assertions passing; that would leave the repo pinning both the bug and its fix.

    The real defect is structural, and the PR should say which fix it chose. type: 'group' is simply unsupported in the home context — and home navigation is the only navigation that uses grouping. So the choice is between teaching the hand-written home branch to recurse, or routing home through NavigationRenderer (the app branch's component, which already handles groups as Collapsibles). The second removes the divergence rather than patching one side of it and is the better default; the first is smaller. Either is defensible, but the reasoning belongs in the PR body — a one-line item.url || '/home' patch that makes the link go somewhere without rendering the nine children would satisfy a careless reading of this card and fix nothing.

    Sequencing. File-disjoint from #3610 and #3611 (they touch AppSidebar.tsx / AppContent.tsx / ConsoleShell.tsx; this one is UnifiedSidebar.tsx), so it can ride alongside them. Same cluster, same zero-app root symptom — worth one lane's attention as a set.

    Dedup (issues + PRs, three repos): no duplicate; #3590 is the closed parent whose implementation surfaced this.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. self-assigned this
    on Aug 7, 2026
  3. yinlianghui commented on Aug 7, 2026

    @yinlianghui
    CollaboratorAuthor

    认领(PM 派发)。


    Generated by Claude Code

  4. yinlianghui commented on Aug 7, 2026

    @yinlianghui
    CollaboratorAuthor

    验收 ACCEPT → PR #3630(session_01GTRjn8xBqp75dk7kFupVRt)。

    已核:CI 18 检查全完成零失败;MEASUREMENT 钉按分诊硬标准替换而非并存,9 条入口逐条断言(超出派单的抽样 3 条);逆向验证连首个失败断言的行号都预测命中(:226)。

    裁决记录:

    1. NavigationRenderer 复用成立,且是测量出来的:分诊担心的 activeApp 强依赖不成立(只吃 props + useLocation),DOM/图标/href 三重奇偶性逐项核对。
    2. expanded: true 是本单的关键判断:AUTO_COLLAPSE_THRESHOLD=8 会把 9 项组自动折叠且 Radix 关闭时 unmount — 天真复用会用另一种拼法复刻同一个 bug。接受并记入方法库。
    3. 刻意不接 pin/reorder/label 解析器正确:useNavOrder 的存储键在 home 上下文会解析成第一个 app(跨上下文串键),已立 observation: UnifiedSidebar 的 nav-order/pin 存储键在 home 上下文解析成「第一个 app」,|| 'home' 兜底实际不可达 #3631(observation)入池;理由写在调用点注释,防后人误接。
    4. 非管理员反向测试带「Home/Documentation 仍在」的反空绿锚点,好。

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions