import 'dart:convert'; import 'dart:io'; import 'file_store_support.dart'; import 'runtime_models.dart'; import 'secret_store.dart'; import 'settings_store.dart'; class SecureConfigStore { SecureConfigStore({ Future Function()? secretRootPathResolver, Future Function()? appDataRootPathResolver, Future Function()? supportRootPathResolver, StoreLayoutResolver? layoutResolver, SettingsStore? settingsStore, SecretStore? secretStore, bool enableSecureStorage = true, }) : _layoutResolver = layoutResolver ?? StoreLayoutResolver( secretRootPathResolver: secretRootPathResolver, appDataRootPathResolver: appDataRootPathResolver, supportRootPathResolver: supportRootPathResolver, ), _settingsStore = settingsStore ?? SettingsStore(layoutResolver ?? StoreLayoutResolver( appDataRootPathResolver: appDataRootPathResolver, supportRootPathResolver: supportRootPathResolver, )), _secretStore = secretStore ?? SecretStore( layoutResolver: layoutResolver ?? StoreLayoutResolver( secretRootPathResolver: secretRootPathResolver, appDataRootPathResolver: appDataRootPathResolver, supportRootPathResolver: supportRootPathResolver, ), enableSecureStorage: enableSecureStorage, ); final StoreLayoutResolver _layoutResolver; final SettingsStore _settingsStore; final SecretStore _secretStore; Future initialize() async { await _settingsStore.initialize(); await _secretStore.initialize(); } Future loadSettingsSnapshot() => _settingsStore.loadSnapshot(); Future saveSettingsSnapshot(SettingsSnapshot snapshot) => _settingsStore.saveSnapshot(snapshot); Future reloadSettingsSnapshotResult() => _settingsStore.reloadSnapshotResult(); Future loadSecretValueByRef(String refName) => _secretStore.loadSecretValueByRef(refName); Future saveSecretValueByRef(String refName, String value) => _secretStore.saveSecretValueByRef(refName, value); Future clearSecretValueByRef(String refName) => _secretStore.clearSecretValueByRef(refName); Future> loadAccountManagedSecrets() => _secretStore.loadAccountManagedSecrets(); Future loadAccountManagedSecret({required String target}) => _secretStore.loadAccountManagedSecret(target: target); Future saveAccountManagedSecret({required String target, required String value}) => _secretStore.saveAccountManagedSecret(target: target, value: value); Future clearAccountManagedSecret({required String target}) => _secretStore.clearAccountManagedSecret(target: target); Future clearAccountManagedSecrets() => _secretStore.clearAccountManagedSecrets(); Future loadAccountSyncState() => _secretStore.loadAccountSyncState(); Future saveAccountSyncState(AccountSyncState value) => _secretStore.saveAccountSyncState(value); Future clearAccountSyncState() => _secretStore.clearAccountSyncState(); Future> loadAuditTrail() => _settingsStore.loadAuditTrail(); Future appendAudit(SecretAuditEntry entry) => _settingsStore.appendAudit(entry); Future loadDeviceIdentity() => _secretStore.loadDeviceIdentity(); Future saveDeviceIdentity(LocalDeviceIdentity identity) => _secretStore.saveDeviceIdentity(identity); Future loadDeviceToken({required String deviceId, required String role}) => _secretStore.loadDeviceToken(deviceId: deviceId, role: role); Future saveDeviceToken({required String deviceId, required String role, required String token}) => _secretStore.saveDeviceToken(deviceId: deviceId, role: role, token: token); Future clearDeviceToken({required String deviceId, required String role}) => _secretStore.clearDeviceToken(deviceId: deviceId, role: role); Future> loadSecureRefs() => _secretStore.loadSecureRefs(); Future loadAccountSessionToken() => _secretStore.loadAccountSessionToken(); Future saveAccountSessionToken(String value) => _secretStore.saveAccountSessionToken(value); Future clearAccountSessionToken() => _secretStore.clearAccountSessionToken(); Future loadAccountSessionExpiresAtMs() => _secretStore.loadAccountSessionExpiresAtMs().then((v) => v == 0 ? null : v); Future saveAccountSessionExpiresAtMs(int value) => _secretStore.saveAccountSessionExpiresAtMs(value); Future clearAccountSessionExpiresAtMs() => _secretStore.clearAccountSessionExpiresAtMs(); Future loadAccountSessionUserId() => _secretStore.loadAccountSessionUserId(); Future saveAccountSessionUserId(String value) => _secretStore.saveAccountSessionUserId(value); Future clearAccountSessionUserId() => _secretStore.clearAccountSessionUserId(); Future loadAccountSessionIdentifier() => _secretStore.loadAccountSessionIdentifier(); Future saveAccountSessionIdentifier(String value) => _secretStore.saveAccountSessionIdentifier(value); Future clearAccountSessionIdentifier() => _secretStore.clearAccountSessionIdentifier(); Future loadAccountSessionSummary() => _secretStore.loadAccountSessionSummary(); Future saveAccountSessionSummary(AccountSessionSummary value) => _secretStore.saveAccountSessionSummary(value); Future clearAccountSessionSummary() => _secretStore.clearAccountSessionSummary(); Future> loadTaskThreads() => _settingsStore.loadTaskThreads(); Future saveTaskThreads(List threads) => _settingsStore.saveTaskThreads(threads); List get lastSkippedInvalidTaskThreadRecords => _settingsStore.lastSkippedInvalidTaskThreadRecords; Future clearAssistantLocalState() => _settingsStore.clearAssistantLocalState(); Future?> loadSupportJson(String relativePath) async { final file = await supportFile(relativePath); if (file == null || !await file.exists()) { return null; } final raw = await file.readAsString(); final decoded = jsonDecode(raw); return decoded is Map ? decoded : null; } Future saveSupportJson( String relativePath, Map payload, ) async { final file = await supportFile(relativePath); if (file == null) { return; } await atomicWriteString(file, jsonEncode(payload), ownerOnly: true); } Future supportFile(String relativePath) async { final normalized = relativePath.trim(); if (normalized.isEmpty) { return null; } final layout = await _layoutResolver.resolve(); return File('${layout.rootDirectory.path}/$normalized'); } Future loadAppUiState() async { final payload = await loadSupportJson('ui/state.json'); if (payload == null) { return AppUiState.defaults(); } try { return AppUiState.fromJson(payload); } catch (_) { return AppUiState.defaults(); } } Future saveAppUiState(AppUiState value) => saveSupportJson('ui/state.json', value.toJson()); Future clearAppUiState() async { final file = await supportFile('ui/state.json'); if (file == null) { return; } await deleteIfExists(file); } PersistentWriteFailures get persistentWriteFailures => PersistentWriteFailures( settings: _settingsStore.auditWriteFailure, tasks: _settingsStore.tasksWriteFailure, secrets: _secretStore.secretsWriteFailure, audit: _settingsStore.auditWriteFailure, ); Future resolvedSettingsFile() => _layoutResolver.resolve().then((l) => File('${l.configDirectory.path}/settings.yaml')); Future resolvedSettingsWatchDirectory() => _layoutResolver.resolve().then((l) => l.configDirectory); Map get secureRefs => _secretStore.secureRefs; PersistentWriteFailure? get settingsWriteFailure => _settingsStore.settingsWriteFailure; void dispose() { _settingsStore.dispose(); _secretStore.dispose(); } static String maskValue(String value) => SecretStore.maskValue(value); }