#4154: fix(control-ui): preserve URL session parameter over localStorage defaults
app: web-ui
Cluster:
UI Enhancements and Security Fixes
## Summary
When opening the dashboard with a `?session=` URL parameter, the session was being overwritten by `applySessionDefaults()` after the gateway connected. This broke direct links to specific sessions.
## Problem
External tools (like Kanban boards with per-project sessions) open dashboard URLs like:
```
/chat?session=agent:main:project-6
```
The URL session was correctly parsed in `applySettingsFromUrl()`, but then immediately overwritten when `applySnapshot()` → `applySessionDefaults()` ran after the gateway connection succeeded.
## Solution
Added a `sessionFromUrl` flag that's set when a session is explicitly provided via URL parameter. The `applySessionDefaults()` function now checks for this flag and skips overriding URL-provided sessions.
The flag is cleared after the first connection so that future reconnects can apply defaults if needed.
## Testing
- Verified typecheck passes (`npx tsc --noEmit`)
- Manual testing: open `/chat?session=agent:main:project-X` and verify the correct session loads
Fixes #4150
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR ensures `?session=` URL parameters win over session defaults loaded after the gateway connects. It does this by setting a transient `sessionFromUrl` flag when `applySettingsFromUrl()` parses an explicit session, and having `applySessionDefaults()` skip overriding the session when that flag is set (then clearing it after the first successful connect).
The change is localized to the control UI gateway/settings flow: URL parsing happens in `ui/src/ui/app-settings.ts`, and the session-default application happens in `ui/src/ui/app-gateway.ts` when the hello snapshot includes `sessionDefaults`.
Issues to address before merge:
- `syncUrlWithSessionKey`’s signature appears to have changed (now missing the `host` parameter), which will break any existing call sites expecting the old API.
- The new `sessionFromUrl` flag is added via type casts rather than being part of the host types, which makes the behavior brittle and easy to regress during refactors.
<h3>Confidence Score: 3/5</h3>
- Mostly safe, but has at least one behavior-affecting bug to fix before merge.
- Core intent (preserve URL-provided session over defaults) is implemented, but the `sessionFromUrl` marker isn’t applied consistently (e.g., popstate path), and the change introduces brittle state via ad-hoc type casts. These can cause URL sessions to still be overridden or the behavior to regress during refactors.
- ui/src/ui/app-settings.ts and ui/src/ui/app-gateway.ts
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#10800: fix(ui): apply token from URL param to settings
by callebtc · 2026-02-07
77.8%
#18694: fix(ui): reset session key to main after /new in webchat
by Phineas1500 · 2026-02-17
77.5%
#6653: fix: persist archived session entry on /new or /reset
by leicao-me · 2026-02-01
75.7%
#10093: fix: import gateway token from URL param into localStorage
by devjiro76 · 2026-02-06
75.4%
#8774: Fix/frontend session key normalization
by zhaodageng · 2026-02-04
75.0%
#14358: fix: preserve session overrides (verbose, model) across /new or /rese…
by WyattSanders · 2026-02-12
74.5%
#11109: fix(tui): prefer config contextTokens over persisted session value
by marezgui · 2026-02-07
74.4%
#5097: fix(ui): prefer session label over displayName in dropdown
by d-init-d · 2026-01-31
74.0%
#19343: Refactor chat state management: reset chat messages and queue on se...
by saurav470 · 2026-02-17
73.9%
#18273: fix: extract token from URL query string for Control UI websocket auth
by MisterGuy420 · 2026-02-16
73.7%