From 5ece9afa8b57b51dea3a7aac45d4e788507bcad1 Mon Sep 17 00:00:00 2001 From: ObitaBot Date: Mon, 16 Mar 2026 13:43:26 +0800 Subject: [PATCH] fix: scope localStorage settings key by basePath to prevent cross-deployment conflicts - Add settingsKeyForGateway() function similar to tokenSessionKeyForGateway() - Use scoped key format: openclaw.control.settings.v1:https://example.com/gateway-a - Add migration from legacy static key on load - Fixes #47481 --- ui/src/ui/storage.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ui/src/ui/storage.ts b/ui/src/ui/storage.ts index 0b23b3436a4..fcd9c4469c8 100644 --- a/ui/src/ui/storage.ts +++ b/ui/src/ui/storage.ts @@ -1,8 +1,12 @@ -const KEY = "openclaw.control.settings.v1"; +const SETTINGS_KEY_PREFIX = "openclaw.control.settings.v1:"; const LEGACY_TOKEN_SESSION_KEY = "openclaw.control.token.v1"; const TOKEN_SESSION_KEY_PREFIX = "openclaw.control.token.v1:"; const MAX_SCOPED_SESSION_ENTRIES = 10; +function settingsKeyForGateway(gatewayUrl: string): string { + return `${SETTINGS_KEY_PREFIX}${normalizeGatewayTokenScope(gatewayUrl)}`; +} + type ScopedSessionSelection = { sessionKey: string; lastActiveSessionKey: string; @@ -188,7 +192,9 @@ export function loadSettings(): UiSettings { }; try { - const raw = storage?.getItem(KEY); + // First check for legacy key (no scope), then check for scoped key + const scopedKey = settingsKeyForGateway(defaults.gatewayUrl); + const raw = storage?.getItem(scopedKey) ?? storage?.getItem(SETTINGS_KEY_PREFIX + "default") ?? storage?.getItem("openclaw.control.settings.v1"); if (!raw) { return defaults; } @@ -256,9 +262,11 @@ function persistSettings(next: UiSettings) { persistSessionToken(next.gatewayUrl, next.token); const storage = getSafeLocalStorage(); const scope = normalizeGatewayTokenScope(next.gatewayUrl); + const scopedKey = settingsKeyForGateway(next.gatewayUrl); let existingSessionsByGateway: Record = {}; try { - const raw = storage?.getItem(KEY); + // Try to migrate from legacy key or other scopes + const raw = storage?.getItem(scopedKey) ?? storage?.getItem(SETTINGS_KEY_PREFIX + "default") ?? storage?.getItem("openclaw.control.settings.v1"); if (raw) { const parsed = JSON.parse(raw) as PersistedUiSettings; if (parsed.sessionsByGateway && typeof parsed.sessionsByGateway === "object") { @@ -294,5 +302,5 @@ function persistSettings(next: UiSettings) { sessionsByGateway, ...(next.locale ? { locale: next.locale } : {}), }; - storage?.setItem(KEY, JSON.stringify(persisted)); + storage?.setItem(scopedKey, JSON.stringify(persisted)); }