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
This commit is contained in:
ObitaBot 2026-03-16 13:43:26 +08:00 committed by Peter Steinberger
parent fb47777d38
commit f100c96b53

View File

@ -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<string, ScopedSessionSelection> = {};
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));
}