diff --git a/lib/app/app_controller_desktop_runtime_helpers.dart b/lib/app/app_controller_desktop_runtime_helpers.dart index cffb3dd8..14002e7b 100644 --- a/lib/app/app_controller_desktop_runtime_helpers.dart +++ b/lib/app/app_controller_desktop_runtime_helpers.dart @@ -801,7 +801,7 @@ extension AppControllerDesktopRuntimeHelpers on AppController { if (bridgeHost.isNotEmpty && normalizedHost == bridgeHost) { final bridgeToken = (await storeInternal.loadAccountManagedSecret( - target: kAccountManagedSecretTargetOpenclawGatewayToken, + target: kAccountManagedSecretTargetBridgeAuthToken, ))?.trim() ?? ''; if (bridgeToken.isNotEmpty) { diff --git a/lib/features/settings/settings_page_core.dart b/lib/features/settings/settings_page_core.dart index aa4f9291..3b310880 100644 --- a/lib/features/settings/settings_page_core.dart +++ b/lib/features/settings/settings_page_core.dart @@ -171,8 +171,8 @@ class _SettingsPageState extends State { Widget _buildTokenConfiguredSummary(AccountSyncState? accountState) { final configured = [ - if (accountState?.tokenConfigured.openclaw == true) - appText('Gateway Token', 'Gateway Token'), + if (accountState?.tokenConfigured.bridge == true) + appText('Bridge Token', 'Bridge Token'), if (accountState?.tokenConfigured.apisix == true) appText('AI Gateway Token', 'AI Gateway Token'), if (accountState?.tokenConfigured.vault == true) 'Vault Token', diff --git a/lib/runtime/runtime_controllers_settings_account.dart b/lib/runtime/runtime_controllers_settings_account.dart index 41aeef6d..03132011 100644 --- a/lib/runtime/runtime_controllers_settings_account.dart +++ b/lib/runtime/runtime_controllers_settings_account.dart @@ -55,7 +55,7 @@ extension SettingsControllerAccountExtension on SettingsController { refName: gatewayTokenRefForProfileInternal(resolvedProfileIndex), fallbackRefName: SecretStore.gatewayTokenRefKey(resolvedProfileIndex), accountTarget: resolvedProfileIndex == kGatewayRemoteProfileIndex - ? kAccountManagedSecretTargetOpenclawGatewayToken + ? kAccountManagedSecretTargetBridgeAuthToken : '', ); } diff --git a/lib/runtime/runtime_controllers_settings_account_impl.dart b/lib/runtime/runtime_controllers_settings_account_impl.dart index 51a09cde..1e9329b0 100644 --- a/lib/runtime/runtime_controllers_settings_account_impl.dart +++ b/lib/runtime/runtime_controllers_settings_account_impl.dart @@ -148,6 +148,7 @@ Future completeAccountSignInSettingsInternal( controller, baseUrl: baseUrl, bridgeTokenOverride: _resolveBridgeAuthorizationToken(payload), + bridgeServerUrlOverride: _resolveBridgeServerUrl(payload), quiet: true, ); await controller.reloadDerivedStateInternal(); @@ -225,6 +226,7 @@ Future syncAccountSettingsInternal( String baseUrl = '', bool quiet = false, String bridgeTokenOverride = '', + String bridgeServerUrlOverride = '', }) async { final sessionToken = (await controller.storeInternal.loadAccountSessionToken())?.trim() ?? ''; @@ -250,7 +252,7 @@ Future syncAccountSettingsInternal( final bridgeToken = bridgeTokenOverride.trim().isNotEmpty ? bridgeTokenOverride.trim() : ((await controller.storeInternal.loadAccountManagedSecret( - target: kAccountManagedSecretTargetOpenclawGatewayToken, + target: kAccountManagedSecretTargetBridgeAuthToken, ))?.trim() ?? ''); if (bridgeToken.isEmpty) { @@ -266,8 +268,33 @@ Future syncAccountSettingsInternal( return result; } + final bridgeServerUrl = bridgeServerUrlOverride.trim().isNotEmpty + ? bridgeServerUrlOverride.trim() + : controller.accountSyncStateInternal?.syncedDefaults.bridgeServerUrl + .trim() + .isNotEmpty == + true + ? controller.accountSyncStateInternal!.syncedDefaults.bridgeServerUrl + .trim() + : controller + .snapshotInternal + .acpBridgeServerModeConfig + .cloudSynced + .remoteServerSummary + .endpoint + .trim() + .isNotEmpty + ? controller + .snapshotInternal + .acpBridgeServerModeConfig + .cloudSynced + .remoteServerSummary + .endpoint + .trim() + : _kProductionBridgeEndpoint; + await controller.storeInternal.saveAccountManagedSecret( - target: kAccountManagedSecretTargetOpenclawGatewayToken, + target: kAccountManagedSecretTargetBridgeAuthToken, value: bridgeToken, ); await controller.storeInternal.clearAccountManagedSecret( @@ -278,14 +305,17 @@ Future syncAccountSettingsInternal( ); final nextState = AccountSyncState.defaults().copyWith( + syncedDefaults: AccountRemoteProfile.defaults().copyWith( + bridgeServerUrl: bridgeServerUrl, + ), syncState: 'ready', syncMessage: 'Bridge access synced', lastSyncAtMs: DateTime.now().millisecondsSinceEpoch, - lastSyncSource: _kProductionBridgeEndpoint, + lastSyncSource: bridgeServerUrl, lastSyncError: '', profileScope: 'bridge', tokenConfigured: const AccountTokenConfigured( - openclaw: true, + bridge: true, vault: false, apisix: false, ), @@ -299,10 +329,7 @@ Future syncAccountSettingsInternal( accountIdentifier: '', lastSyncAt: nextState.lastSyncAtMs, remoteServerSummary: currentModeConfig.cloudSynced.remoteServerSummary - .copyWith( - endpoint: _kProductionBridgeEndpoint, - hasAdvancedOverrides: false, - ), + .copyWith(endpoint: bridgeServerUrl, hasAdvancedOverrides: false), ), ); final sanitizedSettings = _sanitizeBridgeOnlyAccountSyncSettings( @@ -444,13 +471,15 @@ SettingsSnapshot _sanitizeBridgeOnlyAccountSyncSettings( } String _resolveBridgeAuthorizationToken(Map payload) { - final explicit = _stringValue(payload['internalServiceToken']).isNotEmpty - ? _stringValue(payload['internalServiceToken']) - : _stringValue(payload['internal_service_token']).isNotEmpty - ? _stringValue(payload['internal_service_token']) - : _stringValue(payload['bridgeAuthToken']).isNotEmpty - ? _stringValue(payload['bridgeAuthToken']) - : _stringValue(payload['bridge_auth_token']); + final explicit = _stringValue(payload['BRIDGE_AUTH_TOKEN']); + if (explicit.isNotEmpty) { + return explicit; + } + return ''; +} + +String _resolveBridgeServerUrl(Map payload) { + final explicit = _stringValue(payload['BRIDGE_SERVER_URL']); if (explicit.isNotEmpty) { return explicit; } diff --git a/lib/runtime/runtime_controllers_settings_secrets_impl.dart b/lib/runtime/runtime_controllers_settings_secrets_impl.dart index ed5bf742..bb49dbb3 100644 --- a/lib/runtime/runtime_controllers_settings_secrets_impl.dart +++ b/lib/runtime/runtime_controllers_settings_secrets_impl.dart @@ -174,7 +174,7 @@ bool hasStoredGatewayTokenForProfileSettingsInternal( (!controller.snapshotInternal.accountLocalMode && profileIndex == kGatewayRemoteProfileIndex && controller.secureRefsInternal.containsKey( - kAccountManagedSecretTargetOpenclawGatewayToken, + kAccountManagedSecretTargetBridgeAuthToken, )); bool hasStoredGatewayPasswordForProfileSettingsInternal( @@ -195,7 +195,7 @@ String? storedGatewayTokenMaskForProfileSettingsInternal( (!controller.snapshotInternal.accountLocalMode && profileIndex == kGatewayRemoteProfileIndex ? controller - .secureRefsInternal[kAccountManagedSecretTargetOpenclawGatewayToken] + .secureRefsInternal[kAccountManagedSecretTargetBridgeAuthToken] : null); String? storedGatewayPasswordMaskForProfileSettingsInternal( diff --git a/lib/runtime/runtime_models_account.dart b/lib/runtime/runtime_models_account.dart index 6f65e6a0..295a6439 100644 --- a/lib/runtime/runtime_models_account.dart +++ b/lib/runtime/runtime_models_account.dart @@ -67,38 +67,38 @@ class AccountSessionSummary { class AccountTokenConfigured { const AccountTokenConfigured({ - required this.openclaw, + required this.bridge, required this.vault, required this.apisix, }); - final bool openclaw; + final bool bridge; final bool vault; final bool apisix; factory AccountTokenConfigured.defaults() { return const AccountTokenConfigured( - openclaw: false, + bridge: false, vault: false, apisix: false, ); } - AccountTokenConfigured copyWith({bool? openclaw, bool? vault, bool? apisix}) { + AccountTokenConfigured copyWith({bool? bridge, bool? vault, bool? apisix}) { return AccountTokenConfigured( - openclaw: openclaw ?? this.openclaw, + bridge: bridge ?? this.bridge, vault: vault ?? this.vault, apisix: apisix ?? this.apisix, ); } Map toJson() { - return {'openclaw': openclaw, 'vault': vault, 'apisix': apisix}; + return {'bridge': bridge, 'vault': vault, 'apisix': apisix}; } factory AccountTokenConfigured.fromJson(Map json) { return AccountTokenConfigured( - openclaw: json['openclaw'] as bool? ?? false, + bridge: json['bridge'] as bool? ?? false, vault: json['vault'] as bool? ?? false, apisix: json['apisix'] as bool? ?? false, ); @@ -165,16 +165,16 @@ class AccountSecretLocator { class AccountRemoteProfile { const AccountRemoteProfile({ - required this.openclawUrl, - required this.openclawOrigin, + required this.bridgeServerUrl, + required this.bridgeServerOrigin, required this.vaultUrl, required this.vaultNamespace, required this.apisixUrl, required this.secretLocators, }); - final String openclawUrl; - final String openclawOrigin; + final String bridgeServerUrl; + final String bridgeServerOrigin; final String vaultUrl; final String vaultNamespace; final String apisixUrl; @@ -182,8 +182,8 @@ class AccountRemoteProfile { factory AccountRemoteProfile.defaults() { return const AccountRemoteProfile( - openclawUrl: '', - openclawOrigin: '', + bridgeServerUrl: '', + bridgeServerOrigin: '', vaultUrl: '', vaultNamespace: '', apisixUrl: '', @@ -192,16 +192,16 @@ class AccountRemoteProfile { } AccountRemoteProfile copyWith({ - String? openclawUrl, - String? openclawOrigin, + String? bridgeServerUrl, + String? bridgeServerOrigin, String? vaultUrl, String? vaultNamespace, String? apisixUrl, List? secretLocators, }) { return AccountRemoteProfile( - openclawUrl: openclawUrl ?? this.openclawUrl, - openclawOrigin: openclawOrigin ?? this.openclawOrigin, + bridgeServerUrl: bridgeServerUrl ?? this.bridgeServerUrl, + bridgeServerOrigin: bridgeServerOrigin ?? this.bridgeServerOrigin, vaultUrl: vaultUrl ?? this.vaultUrl, vaultNamespace: vaultNamespace ?? this.vaultNamespace, apisixUrl: apisixUrl ?? this.apisixUrl, @@ -211,8 +211,8 @@ class AccountRemoteProfile { Map toJson() { return { - 'openclawUrl': openclawUrl, - 'openclawOrigin': openclawOrigin, + 'BRIDGE_SERVER_URL': bridgeServerUrl, + 'bridgeServerOrigin': bridgeServerOrigin, 'vaultUrl': vaultUrl, 'vaultNamespace': vaultNamespace, 'apisixUrl': apisixUrl, @@ -238,9 +238,10 @@ class AccountRemoteProfile { final defaults = AccountRemoteProfile.defaults(); return AccountRemoteProfile( - openclawUrl: json['openclawUrl'] as String? ?? defaults.openclawUrl, - openclawOrigin: - json['openclawOrigin'] as String? ?? defaults.openclawOrigin, + bridgeServerUrl: + json['BRIDGE_SERVER_URL'] as String? ?? defaults.bridgeServerUrl, + bridgeServerOrigin: + json['bridgeServerOrigin'] as String? ?? defaults.bridgeServerOrigin, vaultUrl: json['vaultUrl'] as String? ?? defaults.vaultUrl, vaultNamespace: json['vaultNamespace'] as String? ?? defaults.vaultNamespace, @@ -690,14 +691,13 @@ class AccountSyncResult { final String message; } -const String kAccountManagedSecretTargetOpenclawGatewayToken = - 'openclaw.gateway_token'; +const String kAccountManagedSecretTargetBridgeAuthToken = 'bridge.auth_token'; const String kAccountManagedSecretTargetAIGatewayAccessToken = 'ai_gateway.access_token'; const String kAccountManagedSecretTargetOllamaCloudApiKey = 'ollama_cloud.api_key'; const List kAccountManagedSecretTargets = [ - kAccountManagedSecretTargetOpenclawGatewayToken, + kAccountManagedSecretTargetBridgeAuthToken, kAccountManagedSecretTargetAIGatewayAccessToken, kAccountManagedSecretTargetOllamaCloudApiKey, ]; diff --git a/test/features/settings/settings_page_core_test.dart b/test/features/settings/settings_page_core_test.dart index 6945efdb..c8adc138 100644 --- a/test/features/settings/settings_page_core_test.dart +++ b/test/features/settings/settings_page_core_test.dart @@ -359,12 +359,12 @@ class _FakeSettingsController extends SettingsController { lastSyncSource: 'https://accounts.svc.plus', profileScope: 'tenant-shared', tokenConfigured: const AccountTokenConfigured( - openclaw: true, + bridge: true, vault: false, apisix: true, ), syncedDefaults: AccountRemoteProfile.defaults().copyWith( - openclawUrl: 'wss://gateway.svc.plus', + bridgeServerUrl: 'https://xworkmate-bridge.svc.plus', apisixUrl: 'https://apisix.svc.plus', ), ); @@ -385,12 +385,12 @@ class _FakeSettingsController extends SettingsController { lastSyncSource: baseUrl, profileScope: 'tenant-shared', tokenConfigured: const AccountTokenConfigured( - openclaw: true, + bridge: true, vault: false, apisix: true, ), syncedDefaults: AccountRemoteProfile.defaults().copyWith( - openclawUrl: 'wss://gateway.svc.plus', + bridgeServerUrl: 'https://xworkmate-bridge.svc.plus', apisixUrl: 'https://apisix.svc.plus', ), ); diff --git a/test/runtime/account_sync_overwrite_test.dart b/test/runtime/account_sync_overwrite_test.dart index 2573daf7..623f9dcd 100644 --- a/test/runtime/account_sync_overwrite_test.dart +++ b/test/runtime/account_sync_overwrite_test.dart @@ -75,7 +75,7 @@ void main() { value: 'stale-ollama-token', ); await store.saveAccountManagedSecret( - target: kAccountManagedSecretTargetOpenclawGatewayToken, + target: kAccountManagedSecretTargetBridgeAuthToken, value: 'bridge-token', ); @@ -113,11 +113,11 @@ void main() { ); expect(controller.snapshot.accountLocalMode, isFalse); expect(controller.accountSyncState?.profileScope, 'bridge'); - expect(controller.accountSyncState?.tokenConfigured.openclaw, isTrue); + expect(controller.accountSyncState?.tokenConfigured.bridge, isTrue); expect(controller.accountSyncState?.tokenConfigured.apisix, isFalse); expect( await store.loadAccountManagedSecret( - target: kAccountManagedSecretTargetOpenclawGatewayToken, + target: kAccountManagedSecretTargetBridgeAuthToken, ), 'bridge-token', ); diff --git a/test/runtime/runtime_controllers_settings_account_test.dart b/test/runtime/runtime_controllers_settings_account_test.dart index cfb94ada..140954e4 100644 --- a/test/runtime/runtime_controllers_settings_account_test.dart +++ b/test/runtime/runtime_controllers_settings_account_test.dart @@ -49,7 +49,7 @@ void main() { value: 'managed-secret', ); await store.saveAccountManagedSecret( - target: kAccountManagedSecretTargetOpenclawGatewayToken, + target: kAccountManagedSecretTargetBridgeAuthToken, value: 'bridge-token', ); await store.saveAccountSyncState( @@ -106,7 +106,7 @@ void main() { ); expect( await store.loadAccountManagedSecret( - target: kAccountManagedSecretTargetOpenclawGatewayToken, + target: kAccountManagedSecretTargetBridgeAuthToken, ), isNull, ); diff --git a/test/runtime/settings_account_auth_flow_test.dart b/test/runtime/settings_account_auth_flow_test.dart index 5f3de8ae..87dbbe2b 100644 --- a/test/runtime/settings_account_auth_flow_test.dart +++ b/test/runtime/settings_account_auth_flow_test.dart @@ -55,16 +55,20 @@ void main() { expect(controller.accountSession?.totpPending, isFalse); expect(controller.accountSyncState?.syncState, 'ready'); expect(controller.accountSyncState?.profileScope, 'bridge'); - expect(controller.accountSyncState?.tokenConfigured.openclaw, isTrue); + expect(controller.accountSyncState?.tokenConfigured.bridge, isTrue); expect(controller.accountSyncState?.tokenConfigured.apisix, isFalse); expect(await store.loadAccountSessionToken(), 'session-token'); expect( await store.loadAccountManagedSecret( - target: kAccountManagedSecretTargetOpenclawGatewayToken, + target: kAccountManagedSecretTargetBridgeAuthToken, ), 'bridge-token', ); expect(client.loadSessionCalls, 0); + expect( + controller.accountSyncState?.syncedDefaults.bridgeServerUrl, + 'https://xworkmate-bridge.svc.plus', + ); expect( controller .snapshot @@ -147,7 +151,8 @@ class _SuccessfulAccountRuntimeClient extends AccountRuntimeClient { expect(password, '***REMOVED-CREDENTIAL***'); return { 'token': 'session-token', - 'internalServiceToken': 'bridge-token', + 'BRIDGE_AUTH_TOKEN': 'bridge-token', + 'BRIDGE_SERVER_URL': 'https://xworkmate-bridge.svc.plus', 'expiresAt': '2026-04-12T00:00:00Z', 'user': { 'id': 'u-1', @@ -198,7 +203,8 @@ class _MfaAccountRuntimeClient extends AccountRuntimeClient { lastVerifiedCode = code; return { 'token': 'session-token', - 'internalServiceToken': 'bridge-token', + 'BRIDGE_AUTH_TOKEN': 'bridge-token', + 'BRIDGE_SERVER_URL': 'https://xworkmate-bridge.svc.plus', 'expiresAt': '2026-04-12T00:00:00Z', 'user': { 'id': 'u-1',