import 'dart:convert'; class AccountSessionSummary { const AccountSessionSummary({ required this.userId, required this.email, required this.name, required this.role, required this.mfaEnabled, this.totpEnabled = false, this.totpPending = false, }); final String userId; final String email; final String name; final String role; final bool mfaEnabled; final bool totpEnabled; final bool totpPending; AccountSessionSummary copyWith({ String? userId, String? email, String? name, String? role, bool? mfaEnabled, bool? totpEnabled, bool? totpPending, }) { return AccountSessionSummary( userId: userId ?? this.userId, email: email ?? this.email, name: name ?? this.name, role: role ?? this.role, mfaEnabled: mfaEnabled ?? this.mfaEnabled, totpEnabled: totpEnabled ?? this.totpEnabled, totpPending: totpPending ?? this.totpPending, ); } Map toJson() { return { 'userId': userId, 'email': email, 'name': name, 'role': role, 'mfaEnabled': mfaEnabled, 'totpEnabled': totpEnabled, 'totpPending': totpPending, }; } factory AccountSessionSummary.fromJson(Map json) { return AccountSessionSummary( userId: json['userId'] as String? ?? '', email: json['email'] as String? ?? '', name: json['name'] as String? ?? '', role: json['role'] as String? ?? '', mfaEnabled: json['mfaEnabled'] as bool? ?? false, totpEnabled: json['totpEnabled'] as bool? ?? false, totpPending: json['totpPending'] as bool? ?? false, ); } } class AccountTokenConfigured { const AccountTokenConfigured({required this.bridge, required this.vault}); final bool bridge; final bool vault; factory AccountTokenConfigured.defaults() { return const AccountTokenConfigured(bridge: false, vault: false); } AccountTokenConfigured copyWith({bool? bridge, bool? vault}) { return AccountTokenConfigured( bridge: bridge ?? this.bridge, vault: vault ?? this.vault, ); } Map toJson() { return {'bridge': bridge, 'vault': vault}; } factory AccountTokenConfigured.fromJson(Map json) { return AccountTokenConfigured( bridge: json['bridge'] as bool? ?? false, vault: json['vault'] as bool? ?? false, ); } } class AccountSecretLocator { const AccountSecretLocator({ required this.id, required this.provider, required this.secretPath, required this.secretKey, required this.target, required this.required, }); final String id; final String provider; final String secretPath; final String secretKey; final String target; final bool required; AccountSecretLocator copyWith({ String? id, String? provider, String? secretPath, String? secretKey, String? target, bool? required, }) { return AccountSecretLocator( id: id ?? this.id, provider: provider ?? this.provider, secretPath: secretPath ?? this.secretPath, secretKey: secretKey ?? this.secretKey, target: target ?? this.target, required: required ?? this.required, ); } Map toJson() { return { 'id': id, 'provider': provider, 'secretPath': secretPath, 'secretKey': secretKey, 'target': target, 'required': required, }; } factory AccountSecretLocator.fromJson(Map json) { return AccountSecretLocator( id: json['id'] as String? ?? '', provider: json['provider'] as String? ?? 'vault', secretPath: json['secretPath'] as String? ?? '', secretKey: json['secretKey'] as String? ?? '', target: json['target'] as String? ?? '', required: json['required'] as bool? ?? false, ); } } class AccountRemoteProfile { const AccountRemoteProfile({ required this.bridgeServerUrl, required this.bridgeServerOrigin, required this.vaultUrl, required this.vaultNamespace, required this.secretLocators, }); final String bridgeServerUrl; final String bridgeServerOrigin; final String vaultUrl; final String vaultNamespace; final List secretLocators; factory AccountRemoteProfile.defaults() { return const AccountRemoteProfile( bridgeServerUrl: '', bridgeServerOrigin: '', vaultUrl: '', vaultNamespace: '', secretLocators: [], ); } AccountRemoteProfile copyWith({ String? bridgeServerUrl, String? bridgeServerOrigin, String? vaultUrl, String? vaultNamespace, List? secretLocators, }) { return AccountRemoteProfile( bridgeServerUrl: bridgeServerUrl ?? this.bridgeServerUrl, bridgeServerOrigin: bridgeServerOrigin ?? this.bridgeServerOrigin, vaultUrl: vaultUrl ?? this.vaultUrl, vaultNamespace: vaultNamespace ?? this.vaultNamespace, secretLocators: secretLocators ?? this.secretLocators, ); } Map toJson() { return { 'BRIDGE_SERVER_URL': bridgeServerUrl, 'bridgeServerOrigin': bridgeServerOrigin, 'vaultUrl': vaultUrl, 'vaultNamespace': vaultNamespace, 'secretLocators': secretLocators .map((item) => item.toJson()) .toList(growable: false), }; } factory AccountRemoteProfile.fromJson(Map json) { List decodeLocators(Object? value) { if (value is! List) { return const []; } return value .whereType() .map( (item) => AccountSecretLocator.fromJson(item.cast()), ) .toList(growable: false); } final defaults = AccountRemoteProfile.defaults(); return AccountRemoteProfile( 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, secretLocators: decodeLocators(json['secretLocators']), ); } AccountSecretLocator? locatorForTarget(String target) { final normalized = target.trim(); if (normalized.isEmpty) { return null; } for (final locator in secretLocators) { if (locator.target.trim() == normalized) { return locator; } } return null; } } class AcpBridgeServerRemoteServerSummary { const AcpBridgeServerRemoteServerSummary({required this.endpoint}); final String endpoint; factory AcpBridgeServerRemoteServerSummary.defaults() { return const AcpBridgeServerRemoteServerSummary(endpoint: ''); } AcpBridgeServerRemoteServerSummary copyWith({String? endpoint}) { return AcpBridgeServerRemoteServerSummary( endpoint: endpoint ?? this.endpoint, ); } Map toJson() { return {'endpoint': endpoint}; } factory AcpBridgeServerRemoteServerSummary.fromJson( Map json, ) { return AcpBridgeServerRemoteServerSummary( endpoint: json['endpoint'] as String? ?? '', ); } } class AcpBridgeServerCloudSyncConfig { const AcpBridgeServerCloudSyncConfig({ required this.accountBaseUrl, required this.accountIdentifier, required this.lastSyncAt, required this.remoteServerSummary, }); final String accountBaseUrl; final String accountIdentifier; final int lastSyncAt; final AcpBridgeServerRemoteServerSummary remoteServerSummary; factory AcpBridgeServerCloudSyncConfig.defaults() { return AcpBridgeServerCloudSyncConfig( accountBaseUrl: '', accountIdentifier: '', lastSyncAt: 0, remoteServerSummary: AcpBridgeServerRemoteServerSummary.defaults(), ); } AcpBridgeServerCloudSyncConfig copyWith({ String? accountBaseUrl, String? accountIdentifier, int? lastSyncAt, AcpBridgeServerRemoteServerSummary? remoteServerSummary, }) { return AcpBridgeServerCloudSyncConfig( accountBaseUrl: accountBaseUrl ?? this.accountBaseUrl, accountIdentifier: accountIdentifier ?? this.accountIdentifier, lastSyncAt: lastSyncAt ?? this.lastSyncAt, remoteServerSummary: remoteServerSummary ?? this.remoteServerSummary, ); } Map toJson() { return { 'accountBaseUrl': accountBaseUrl, 'accountIdentifier': accountIdentifier, 'lastSyncAt': lastSyncAt, 'remoteServerSummary': remoteServerSummary.toJson(), }; } factory AcpBridgeServerCloudSyncConfig.fromJson(Map json) { return AcpBridgeServerCloudSyncConfig( accountBaseUrl: json['accountBaseUrl'] as String? ?? '', accountIdentifier: json['accountIdentifier'] as String? ?? '', lastSyncAt: (json['lastSyncAt'] as num?)?.toInt() ?? 0, remoteServerSummary: AcpBridgeServerRemoteServerSummary.fromJson( (json['remoteServerSummary'] as Map?)?.cast() ?? const {}, ), ); } } class AcpBridgeServerSelfHostedConfig { const AcpBridgeServerSelfHostedConfig({ required this.serverUrl, required this.username, required this.passwordRef, }); final String serverUrl; final String username; final String passwordRef; factory AcpBridgeServerSelfHostedConfig.defaults() { return const AcpBridgeServerSelfHostedConfig( serverUrl: '', username: '', passwordRef: 'acp_bridge_server_password', ); } AcpBridgeServerSelfHostedConfig copyWith({ String? serverUrl, String? username, String? passwordRef, }) { return AcpBridgeServerSelfHostedConfig( serverUrl: (serverUrl ?? this.serverUrl).trim(), username: (username ?? this.username).trim(), passwordRef: (passwordRef ?? this.passwordRef).trim(), ); } bool get isConfigured => serverUrl.trim().isNotEmpty && username.trim().isNotEmpty; Map toJson() { return { 'serverUrl': serverUrl, 'username': username, 'passwordRef': passwordRef, }; } factory AcpBridgeServerSelfHostedConfig.fromJson(Map json) { return AcpBridgeServerSelfHostedConfig( serverUrl: json['serverUrl'] as String? ?? '', username: json['username'] as String? ?? '', passwordRef: json['passwordRef'] as String? ?? AcpBridgeServerSelfHostedConfig.defaults().passwordRef, ); } } class AcpBridgeServerEffectiveConfig { const AcpBridgeServerEffectiveConfig({ required this.endpoint, required this.tokenRef, required this.source, required this.reason, }); final String endpoint; final String tokenRef; final String source; // 'bridge' | 'cloud' | 'default' final String reason; factory AcpBridgeServerEffectiveConfig.defaults() { return const AcpBridgeServerEffectiveConfig( endpoint: '', tokenRef: '', source: 'default', reason: 'No active source configured', ); } AcpBridgeServerEffectiveConfig copyWith({ String? endpoint, String? tokenRef, String? source, String? reason, }) { return AcpBridgeServerEffectiveConfig( endpoint: endpoint ?? this.endpoint, tokenRef: tokenRef ?? this.tokenRef, source: source ?? this.source, reason: reason ?? this.reason, ); } Map toJson() { return { 'endpoint': endpoint, 'tokenRef': tokenRef, 'source': source, 'reason': reason, }; } factory AcpBridgeServerEffectiveConfig.fromJson(Map json) { return AcpBridgeServerEffectiveConfig( endpoint: json['endpoint'] as String? ?? '', tokenRef: json['tokenRef'] as String? ?? '', source: json['source'] as String? ?? 'default', reason: json['reason'] as String? ?? '', ); } } class AcpBridgeServerModeConfig { const AcpBridgeServerModeConfig({ required this.effective, required this.cloudSynced, required this.selfHosted, }); final AcpBridgeServerEffectiveConfig effective; final AcpBridgeServerCloudSyncConfig cloudSynced; final AcpBridgeServerSelfHostedConfig selfHosted; factory AcpBridgeServerModeConfig.defaults() { return AcpBridgeServerModeConfig( effective: AcpBridgeServerEffectiveConfig.defaults(), cloudSynced: AcpBridgeServerCloudSyncConfig.defaults(), selfHosted: AcpBridgeServerSelfHostedConfig.defaults(), ); } AcpBridgeServerModeConfig copyWith({ AcpBridgeServerEffectiveConfig? effective, AcpBridgeServerCloudSyncConfig? cloudSynced, AcpBridgeServerSelfHostedConfig? selfHosted, }) { return AcpBridgeServerModeConfig( effective: effective ?? this.effective, cloudSynced: cloudSynced ?? this.cloudSynced, selfHosted: selfHosted ?? this.selfHosted, ); } String toJsonString() => jsonEncode(toJson()); Map toJson() { return { 'effective': effective.toJson(), 'cloudSynced': cloudSynced.toJson(), 'selfHosted': selfHosted.toJson(), }; } factory AcpBridgeServerModeConfig.fromJson(Map json) { return AcpBridgeServerModeConfig( effective: AcpBridgeServerEffectiveConfig.fromJson( (json['effective'] as Map?)?.cast() ?? const {}, ), cloudSynced: AcpBridgeServerCloudSyncConfig.fromJson( (json['cloudSynced'] as Map?)?.cast() ?? const {}, ), selfHosted: AcpBridgeServerSelfHostedConfig.fromJson( (json['selfHosted'] as Map?)?.cast() ?? const {}, ), ); } } class AccountSyncState { const AccountSyncState({ required this.syncedDefaults, required this.syncState, required this.syncMessage, required this.lastSyncAtMs, required this.lastSyncSource, required this.lastSyncError, required this.profileScope, required this.tokenConfigured, }); final AccountRemoteProfile syncedDefaults; final String syncState; final String syncMessage; final int lastSyncAtMs; final String lastSyncSource; final String lastSyncError; final String profileScope; final AccountTokenConfigured tokenConfigured; factory AccountSyncState.defaults() { return AccountSyncState( syncedDefaults: AccountRemoteProfile.defaults(), syncState: 'idle', syncMessage: 'Remote config not synced yet', lastSyncAtMs: 0, lastSyncSource: '', lastSyncError: '', profileScope: '', tokenConfigured: AccountTokenConfigured.defaults(), ); } AccountSyncState copyWith({ AccountRemoteProfile? syncedDefaults, String? syncState, String? syncMessage, int? lastSyncAtMs, String? lastSyncSource, String? lastSyncError, String? profileScope, AccountTokenConfigured? tokenConfigured, }) { return AccountSyncState( syncedDefaults: syncedDefaults ?? this.syncedDefaults, syncState: syncState ?? this.syncState, syncMessage: syncMessage ?? this.syncMessage, lastSyncAtMs: lastSyncAtMs ?? this.lastSyncAtMs, lastSyncSource: lastSyncSource ?? this.lastSyncSource, lastSyncError: lastSyncError ?? this.lastSyncError, profileScope: profileScope ?? this.profileScope, tokenConfigured: tokenConfigured ?? this.tokenConfigured, ); } Map toJson() { return { 'syncedDefaults': syncedDefaults.toJson(), 'syncState': syncState, 'syncMessage': syncMessage, 'lastSyncAtMs': lastSyncAtMs, 'lastSyncSource': lastSyncSource, 'lastSyncError': lastSyncError, 'profileScope': profileScope, 'tokenConfigured': tokenConfigured.toJson(), }; } factory AccountSyncState.fromJson(Map json) { return AccountSyncState( syncedDefaults: AccountRemoteProfile.fromJson( (json['syncedDefaults'] as Map?)?.cast() ?? const {}, ), syncState: json['syncState'] as String? ?? 'idle', syncMessage: json['syncMessage'] as String? ?? 'Remote config not synced yet', lastSyncAtMs: (json['lastSyncAtMs'] as num?)?.toInt() ?? 0, lastSyncSource: json['lastSyncSource'] as String? ?? '', lastSyncError: json['lastSyncError'] as String? ?? '', profileScope: json['profileScope'] as String? ?? '', tokenConfigured: AccountTokenConfigured.fromJson( (json['tokenConfigured'] as Map?)?.cast() ?? const {}, ), ); } } class AccountSyncResult { const AccountSyncResult({required this.state, required this.message}); final String state; final String message; } const String kManagedBridgeServerUrl = 'https://xworkmate-bridge.svc.plus'; const String kAccountManagedSecretTargetBridgeAuthToken = 'bridge.auth_token'; const String kAccountManagedSecretTargetAIGatewayAccessToken = 'ai_gateway.access_token'; const String kAccountManagedSecretTargetOllamaCloudApiKey = 'ollama_cloud.api_key'; const List kAccountManagedSecretTargets = [ kAccountManagedSecretTargetBridgeAuthToken, kAccountManagedSecretTargetAIGatewayAccessToken, kAccountManagedSecretTargetOllamaCloudApiKey, ]; bool isSupportedAccountManagedSecretTarget(String target) { return kAccountManagedSecretTargets.contains(target.trim()); }