Repository navigation
V2: Fix left sidebar links opening the classic UI instead of V2 - #1700
Merged
Paul Lizer (paullizer) merged 2 commits intoOct 7, 2026
Merged
Conversation
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>
Paul Lizer (paullizer)
merged commit Oct 7, 2026
56fd78c
into
paullizer-react-v2-ui
11 checks passed
14 of 24 tasks
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>
This was referenced Oct 7, 2026
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>
15 of 24 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/workspaceinstead 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.Sidebar.tsxpassedsafeSameOriginUrl(item.to, window.location.origin)fromlib/adminOperations.tstoNavLink to=. That helper returns an absolute URL. React Router 6.30 treats an absolute URL outside the/v2basename as external, so it rendered a plain<a>without its router click handler.safeNavHrefallowlist. The base already had thesafeSameOriginUrlversion (2d885b8ce), and Add V2 Terms of Use and Approval Requests pages #1687's base-into-branch merge (5939997c2) kept the base's line.safe*Href/safe*Urlpatterns, and the UI tests that would have caught this skip without a deployment.safeNavHref. It returns the path unchanged when it is one of the rail's ownNAV_ITEMS(otherwise/chat), so links stay relative to/v2and still pass the XSS sink check. Also removes the unusedadminOperationsimport and bumps the version to 0.261.290.to=prop in the V2 source is built fromlocation.originorsafeSameOriginUrl.SIMPLECHAT_UI_BASE_URLand a storage state.Reviewer note: these links are unchanged.
normalizeWorkspaceUrl, which returns only a pathname. The new test checks this.Linked issue
Fixes #1698
Release Notes & Latest Features
Is this visible to end users?
Is this admin-facing (Admin Settings, governance, deployment, config)?
Should this become a Latest Feature card?
Screenshot needed for the card?
Version bump
application/single_app/config.pyVERSIONthird segment bumped, or not needed because this is docs-only (0.261.289 -> 0.261.290)deployers/version.txtbumped, or not needed becausedeployers/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-fixSidebar.tsxtemporarily 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-fixSidebar.tsx, the cases fail on the href check, for example: expected/v2/chat, gothttp://127.0.0.1:5174/chat.Manual browser check (a Playwright script, same setup) clicking each of the 7 rail links:
/v2/: every href was absolute, for examplehttp://127.0.0.1:5174/workspace, and every click reloaded the document./v2/and/v2/chat: every href is/v2/<route>, nothing reloads, and the link getsaria-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.d4cfde733with this change stashed, and they cover code this PR does not touch (the chat page's URL sync hook andInlineChart).test_v2_conversation_deep_link.py::test_incoming_link_is_captured_before_any_effect_runsandtest_v2_stats_parity.py::test_charts_use_the_shared_vendored_runtime.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 HEADbefore committing, which checks only the changed lines, as CI does.npm run typecheckinapplication/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 underdocs/explanation/release-notes/are 217 versions behindrelease_notes.mdon the base. Regenerating them rewrites and splits those pages, which is unrelated to this fix.Documentation
docs/explanation/fixes/V2_SIDEBAR_NAV_LINKS_FIX.md)Security checklist
@swagger_route(security=get_auth_security())(no routes added or changed)sanitize_settings_for_user()(no settings exposure changed)