Skip to content

bug(storage): non-transactional secret updates in local_db cause password sync failures and undeletable connections #276

Description

@ZhuchkaTriplesix

Summary / Описание проблемы

В local_db.dart сохранение метаданных подключения (в SQLite) и сохранение секретных данных (пароль и строка подключения в ConnectionSecretsStore через FlutterSecureStorage) происходят последовательно без атомарной транзакции и надлежащей обработки ошибок:

  1. В updateConnection (L374): Обновление записи в таблице connections выполняется в транзакции SQLite, после чего вызывается await ConnectionSecretsStore.writeForConnection(...). Если запись в системный хэранилище секретов (Keychain / libsecret) завершается ошибкой, запись в SQLite уже зафиксирована. Данные в UI рассинхронизируются, пароль теряется.
  2. В removeConnection (L397): Сначала вызывается await ConnectionSecretsStore.deleteForConnection(id);. Если удаление ключа из FlutterSecureStorage вызывает исключение (например, если ключ отсутствует или системный демон недоступен), метод прерывается с ошибкой, и удаление строки из SQLite (db.delete('connections')) вообще не выполняется. В результате пользователь не может удалить «битое» подключение из интерфейса приложения.

Scope & Component

  • Scope: desktop
  • Component: Core / Storage & Secrets
  • Kind: bug
  • Severity: high
  • Detected in version: dev / 0.5.0

Местоположение в коде

  • Файлы:
    • lib/core/storage/local_db.dart (строки ~362-401, методы addConnection, updateConnection, removeConnection)
    • lib/core/storage/connection_secrets_store.dart (строки ~19-28, методы write и delete)

Шаги воспроизведения

  1. В Linux отключить демон libsecret (или смоделировать сбой/отсутствие ключа в FlutterSecureStorage при удалении).
  2. Попытаться удалить существующее подключение в UI (removeConnection).
  3. Фактический результат: Исключение в ConnectionSecretsStore.deleteForConnection блокирует выполнение db.delete. Подключение остается в списке таблиц SQLite навсегда.
  4. Ожидаемый результат: Операции удаления из ConnectionSecretsStore должны быть обернуты в try-catch (или не блокировать удаление метаданных из SQLite), а добавление/обновление должно гарантировать согласованность состояния пароля и записи в БД.

Acceptance Criteria / Критерии приемки

  • В removeConnection в local_db.dart удаление секрета из ConnectionSecretsStore.deleteForConnection(id) не блокирует удаление строки подключения из таблицы SQLite при возникновении ошибок хранилища.
  • В addConnection и updateConnection добавлена корректная обработка сбоев записи в ConnectionSecretsStore (с откатом или явным предупреждением пользователя об ошибке сохранения пароля в OS Keychain).

Metadata

Metadata

Labels

bugSomething isn't workingcoreCore library logic and services

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions