web: address rollup review #1 — deep-link reconnect on restored activeServerId

Gate the deep-link connect phase on 'not already connected' rather than on
activeServerId identity: if a prior session restored activeServerId to the
'deep-link' id while disconnected, the old guard marked the ref consumed and
never connected, so reloading the same deep-link URL silently didn't auto-
connect. onToggleConnection only disconnects when the id is active AND status
is connected, so the new condition also avoids toggling a live connection off.

Also documents (rollup review #3) that pre-selecting a deep-linked app
deliberately bypasses AppsScreen.handleSelect's no-input auto-launch — a URL
must not fire a tool call without the token-gated autoOpen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BrihGWcrM9JGRyu41nzZYw
This commit is contained in:
cliffhall 2026-07-11 23:41:10 -04:00
commit 7411fc886e
2 changed files with 18 additions and 1 deletions

View file

@ -2569,7 +2569,16 @@ function App() {
if (deepLinkConnectRef.current) return;
deepLinkConnectRef.current = true;
if (activeServerId !== deepLink.serverId) {
// Connect unless we're already *connected* to the deep-link server. Gating
// on `activeServerId` identity alone would skip the connect when a prior
// session restored `activeServerId` to the `deep-link` id while the socket
// is disconnected — a reload of the same deep-link URL would then silently
// never connect. `onToggleConnection` only disconnects when the id is the
// active one AND the status is connected, so this condition also avoids
// toggling a live connection off.
const alreadyConnected =
activeServerId === deepLink.serverId && connectionStatus === "connected";
if (!alreadyConnected) {
void onToggleConnection(deepLink.serverId).catch((err) => {
// The toast fires from inside `onToggleConnection` for the common
// cases; this catch covers the rest (surfaced on `data-error-message`).
@ -2581,6 +2590,7 @@ function App() {
deepLink,
servers,
activeServerId,
connectionStatus,
addServer,
updateServer,
onToggleConnection,

View file

@ -892,6 +892,13 @@ export function InspectorView({
...collectSchemaDefaults(target.inputSchema),
...deepLink.appArgs,
};
// Seed the selection directly rather than routing through
// AppsScreen.handleSelect. This deliberately bypasses handleSelect's
// no-input-app auto-launch: a deep link must never invoke a tool against
// the target server unless the token-gated `autoOpen` is set — even a
// no-input app waits for that explicit signal (or a manual "Open App"
// click), matching the security stance that a crafted URL alone can't fire
// a tool call.
onActiveTabChange("Apps");
onAppsUiChange({
...appsUi,