Skip to content

V2: Fix left sidebar links opening the classic UI instead of V2 - #1700

Merged
Paul Lizer (paullizer) merged 2 commits into
paullizer-react-v2-uifrom
paullizer-v2-sidebar-links
Oct 7, 2026
Merged

Paul Lizer (paullizer) merged 2 commits into
paullizer-react-v2-uifrom
paullizer-v2-sidebar-links

Conversation

@paullizer

Copy link
Copy Markdown
Contributor

Summary

  • Problem: Every primary link in the V2 left rail did a full page load into the classic UI at the same path, for example /workspace instead of /v2/workspace. That covers Chats, Agents, My Workspace, Group Workspaces, Public Workspaces, Approval requests and Content review. The rail's active highlight never matched either.
  • Cause: Sidebar.tsx passed safeSameOriginUrl(item.to, window.location.origin) from lib/adminOperations.ts to NavLink to=. That helper returns an absolute URL. React Router 6.30 treats an absolute URL outside the /v2 basename as external, so it rendered a plain <a> without its router click handler.
  • Fix: Restore safeNavHref. It returns the path unchanged when it is one of the rail's own NAV_ITEMS (otherwise /chat), so links stay relative to /v2 and still pass the XSS sink check. Also removes the unused adminOperations import and bumps the version to 0.261.290.
  • Regression guards:
    • A source-level functional test that runs without a deployment. It also fails if any to= prop in the V2 source is built from location.origin or safeSameOriginUrl.
    • A Playwright UI test that clicks each rail link. Like the other V2 UI tests, it needs SIMPLECHAT_UI_BASE_URL and a storage state.

Reviewer note: these links are unchanged.

  • Custom Pages, External Links, Latest Features and "Back to classic UI" are deliberately plain anchors to server-rendered or external pages.
  • The account menu links were already relative.
  • The workspace section rail uses normalizeWorkspaceUrl, which returns only a pathname. The new test checks this.

Linked issue

Fixes #1698

Release Notes & Latest Features

  • New Feature
  • Bug Fix
  • UI Enhancement
  • Breaking Change
  • Internal only

Is this visible to end users?

  • Yes
  • No

Is this admin-facing (Admin Settings, governance, deployment, config)?

  • Yes
  • No

Should this become a Latest Feature card?

  • Yes
  • No
  • Already added

Screenshot needed for the card?

  • Yes
  • No
  • Attached

Version bump

  • application/single_app/config.py VERSION third segment bumped, or not needed because this is docs-only (0.261.289 -> 0.261.290)
  • deployers/version.txt bumped, or not needed because deployers/ was not changed (not changed)

Testing / validation

Setup for the UI test and the manual browser check: SIMPLECHAT_UI_BASE_URL=http://127.0.0.1:5174, pointing at the Vite dev server (npx vite --host 127.0.0.1 --port 5174 --strictPort). The dev server was proxied to a local stub of /api/v2/bootstrap, with an empty storage-state file because the stub does not authenticate.

  • python functional_tests\test_v2_sidebar_primary_nav_stays_in_v2.py: 5/5 passed. With the pre-fix Sidebar.tsx temporarily restored, 2/5 passed. The three checks on how the rail links are built fail, as intended.

  • python -m pytest -q -p no:cacheprovider ui_tests\test_v2_sidebar_primary_nav_links.py: 7 passed. With the pre-fix Sidebar.tsx, the cases fail on the href check, for example: expected /v2/chat, got http://127.0.0.1:5174/chat.

  • Manual browser check (a Playwright script, same setup) clicking each of the 7 rail links:

    • Before, starting from /v2/: every href was absolute, for example http://127.0.0.1:5174/workspace, and every click reloaded the document.
    • After, starting from both /v2/ and /v2/chat: every href is /v2/<route>, nothing reloads, and the link gets aria-current="page". Approval requests lands on its default category, /v2/approvals/all.
  • All existing functional tests that reference Sidebar.tsx, plus the new one: 102 passed, 2 failed.

    • Both failures also fail on base d4cfde733 with this change stashed, and they cover code this PR does not touch (the chat page's URL sync hook and InlineChart).
    • The failing tests are test_v2_conversation_deep_link.py::test_incoming_link_is_captured_before_any_effect_runs and test_v2_stats_parity.py::test_charts_use_the_shared_vendored_runtime.
    python -m pytest -q -p no:cacheprovider functional_tests\test_v2_sidebar_primary_nav_stays_in_v2.py functional_tests\test_v2_new_chat_scoping.py functional_tests\test_v2_sidebar_account_menu.py functional_tests\test_v2_brand_mark_home_link.py functional_tests\test_v2_sidebar_conversation_scroll.py functional_tests\test_v2_admin_review_pages.py functional_tests\test_v2_terms_and_approvals.py functional_tests\test_v2_public_workspace_labels_pin.py functional_tests\test_v2_user_settings_tutorials_latest_features.py functional_tests\test_v2_control_center_foundation.py functional_tests\test_v2_conversation_deep_link.py functional_tests\test_v2_conversation_drawer.py functional_tests\test_v2_conversation_export.py functional_tests\test_v2_notifications_bell.py functional_tests\test_v2_stats_parity.py
    
  • python scripts\check_xss_sinks.py application/v2_ui/src/components/layout/Sidebar.tsx application/single_app/config.py: passed for 2 files. It also passed with --base-sha HEAD before committing, which checks only the changed lines, as CI does.

  • npm run typecheck in application/v2_ui: passed.

  • python -m pytest -q -p no:cacheprovider functional_tests\test_docs_site_quality.py -W ignore: 6 passed.

  • python -m pytest -q -p no:cacheprovider functional_tests\test_docs_app_surface_coverage.py -W ignore: 7 passed.

  • Not fixed here (fails on the base too): python functional_tests\test_docs_release_notes_integrity.py. The generated pages under docs/explanation/release-notes/ are 217 versions behind release_notes.md on the base. Regenerating them rewrites and splits those pages, which is unrelated to this fix.

Documentation

  • Release notes updated, or not needed (v0.261.290 Bug Fixes entry)
  • Feature documentation updated, or not needed (not needed, no feature change)
  • Fix documentation updated, or not needed (docs/explanation/fixes/V2_SIDEBAR_NAV_LINKS_FIX.md)

Security checklist

  • New Flask routes include @swagger_route(security=get_auth_security()) (no routes added or changed)
  • Settings sent to non-admin frontends use sanitize_settings_for_user() (no settings exposure changed)
  • Browser JavaScript is served from local SimpleChat static assets only; no CDN-hosted JS (no new browser assets)
  • No secrets, keys, connection strings, or local-only artifacts are included (the stub backend and browser script used for validation are not committed)

Paul Lizer (paullizer) and others added 2 commits October 7, 2026 14:43
Every primary link in the V2 left rail opened the classic interface. The rail
built its links with the safeSameOriginUrl helper from lib/adminOperations,
which returns a full URL. React Router treats an absolute URL outside the /v2
basename as external, so it rendered a plain anchor and each click loaded the
classic page at that path. The active highlight never matched either.

Two parallel XSS sink fixes had edited the same line, and the merge kept that
helper instead of the relative safeNavHref allowlist reviewed in #1687.

- Restore safeNavHref so rail links stay relative to /v2.
- Add a functional test that also flags router links built from the page
  origin anywhere in the V2 source.
- Add a Playwright UI test that clicks each rail link and checks it routes
  inside the SPA.
- Document the fix and bump the version to 0.261.290.

Fixes #1698

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Refs #1698

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@paullizer
Paul Lizer (paullizer) merged commit 56fd78c into paullizer-react-v2-ui Oct 7, 2026
11 checks passed
Paul Lizer (paullizer) added a commit that referenced this pull request Oct 7, 2026
…lizer-control-center-v2-fixes

The base took 0.261.290 for the V2 sidebar links fix (#1700), so this change
moves to 0.261.291. The release notes keep both sections.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 7, 2026
Brings in V2 at 56fd78c (microsoft#1700, VERSION 0.261.290).

Conflicts:
- docs/explanation/release_notes.md: V2's file byte-for-byte, with this
  branch's own (v0.261.290) section inserted at the very top, above V2's
  first section, its own (v0.261.290). Every V2 section is unchanged.

application/single_app/config.py merged cleanly: V2 and this branch both
set VERSION to 0.261.290.

V2's other changes, to Sidebar.tsx plus microsoft#1700's fix doc and two tests,
don't touch this branch's files.

The next commit renumbers this branch's section and VERSION to
0.261.291, above V2's 0.261.290.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 7, 2026
V2 now uses 0.261.290 (microsoft#1700) and has its own 0.261.290 release notes
section, so this branch's version moves above it. Renumbers the same 20
lines in 15 files as the previous bump: config.py, this branch's
release-notes section, the documentation version notes and the new
tests' headers. V2's own (v0.261.290) release-notes section and microsoft#1700's
fix doc and tests are untouched. The tests' version floor stays
0.261.253.

Refs microsoft#1549

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 7, 2026
Brings in microsoft#1700 (V2 sidebar links, 0.261.290). The only conflict was VERSION;
this branch keeps 0.261.291, the next free patch number.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 7, 2026
Brings in microsoft#1700 (V2 sidebar links, 0.261.290) and microsoft#1701 (Ask an agent
steps, 0.261.291). VERSION keeps 0.261.292, the next free patch number.
The admin troubleshooting table keeps the base's 0.261.289 and 0.261.291
rows, followed by this fix's chart rows.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant