#import "common.typ": pz-fig, pz-table

= Проектирование архитектуры системы

== Схема бизнес-процессов предметной области

=== Организационная структура

Участники процесса: *пользователь*, *мобильное приложение Wallenc*, *внешний провайдер хранения* (облачный API). Сервер приложения отсутствует.

=== Карта процессов

Основные процессы: создание storage в vault → опциональное шифрование storage → открытие storage → работа с файлами → закрытие; для удалённых vault — OAuth → привязка учётной записи → листинг storage провайдера → проектная синхронизация.

=== Диаграмма BPMN

На рисунке @fig-15 представлена диаграмма BPMN основного процесса работы со storage внутри vault.

#pz-fig("fig_15_bpmn_vault.png", [BPMN: storage — создание, шифрование, открытие, содержимое], "fig-15")

=== Карта систем

Wallenc выступает посредником между пользователем и файловыми API провайдера, дополняя взаимодействие локальной БД Room и криптографическим модулем.

== Диаграмма DFD

DFD уровня 0 (рис. @fig-16) отражает потоки между UI, доменной логикой, криптографией, адаптерами хранилищ, Room и внешним API.

#pz-fig("fig_16_dfd_level0.png", [DFD уровень 0: потоки данных в Wallenc], "fig-16")

== Объектно-ориентированный анализ и проектирование (UML)

=== Диаграмма прецедентов

Прецеденты включают управление storage, подключение удалённых vault (OAuth), шифрование и открытие storage, работу с файлами и синхронизацию групп storage (рис. @fig-17).

#pz-fig("fig_17_use_case.png", [Диаграмма прецедентов Wallenc], "fig-17")

=== Диаграмма классов

Доменная модель модуля `:domain` (интерфейсы хранилищ, use case, сущности шифрования) приведена на рисунке @fig-04.

#pz-fig("fig_04_domain_class.png", [Диаграмма классов модуля domain], "fig-04")

=== Доменная иерархия хранения данных

Модель данных приложения строится на трёх уровнях (см. `IVaultsManager`, `IVault`, `IStorage` на рис. @fig-04):

+ *VaultsManager* — единая точка доступа: реактивный список всех vault (`vaults`), агрегированный список storage (`allStorages`) и `IUnlockManager` для открытых storage;
+ *IVault* — контейнер, объединяющий набор storage. *LocalVault* в приложении один (корень на устройстве); удалённые vault (например, `YandexVault`) добавляются по одному на привязанную учётную запись OAuth;
+ *IStorage* — хранилище, которое пользователь создаёт, переименовывает и удаляет в интерфейсе; внутри — файлы и каталоги, доступные через `IStorageAccessor` (с опциональным клиентским шифрованием).

Пользовательские сценарии «создать локальный vault» в UI соответствуют созданию нового *storage* внутри единственного `LocalVault`, а не появлению второго локального vault.

Служебные сущности Room показаны на рисунке @fig-11.

#pz-fig("fig_11_room_schema.png", [Схема служебных сущностей Room], "fig-11")

=== Диаграмма развёртывания

Компоненты развёртывания: устройство Android (приложение, Room), облачный API Яндекса (рис. @fig-18).

#pz-fig("fig_18_deployment.png", [Диаграмма развёртывания], "fig-18")

Архитектурные слои MVVM + Clean Architecture и соответствие модулям Gradle — на рисунке @fig-19.

#pz-fig("fig_19_clean_architecture.png", [Слои Clean Architecture и модули проекта], "fig-19")

== Проектирование локальной базы данных

Служебная БД Room хранит ключи шифрования для пар «исходный storage → зашифрованное представление» (`DbStorageKeyMap`), сериализованные метаданные storage (`DbStorageMetaInfo`), учётные записи Яндекс (`DbYandexAccount`) и группы синхронизации (`DbStorageSyncGroup`). Пользовательский контент в открытом виде в БД не сохраняется — только параметры, необходимые для восстановления состояния приложения при следующем запуске. Доступ инкапсулирован в DAO и репозиториях модуля `:infrastructure-android`.

#pz-table(
  [Сущности Room и назначение],
  3,
  table.header([Сущность], [Назначение], [Связь с тестами]),
  [`DbStorageKeyMap`], [Ключ для `sourceUuid` storage (связь с зашифрованной копией)], [Интеграция],
  [`DbStorageMetaInfo`], [Сериализованные метаданные `IStorage` (имя, путь, шифрование)], [Интеграция],
  [`DbYandexAccount`], [OAuth access token, идентификатор аккаунта], [`YandexAccountRepositoryTest`],
  [`DbStorageSyncGroup`], [Группа UUID для синхронизации], [`StorageSyncEngineTest`],
) <tbl-room-entities>

== Проектирование подсистемы синхронизации

Подсистема синхронизации спроектирована как набор независимых операций над журналом изменений каждого `Storage`. Алгоритм выбирает «победителя» по ревизии, копирует или удаляет файлы на целевом хранилище, не расшифровывая данные на сервере. Блокировки предотвращают одновременную синхронизацию одной группы; при отмене задачи блокировки снимаются (покрыто unit-тестами `syncGroupCooperativeCancellationReleasesLocks` и др., гл. 5). Подробное описание реализации и выбора источника для каждого пути — в гл. 4 (§ алгоритм согласования журналов, рис. @fig-35).

== Нефункциональные архитектурные решения

#pz-table(
  [Нефункциональные решения],
  2,
  table.header([Атрибут], [Решение]),
  [Производительность], [Потоковое шифрование, фоновые задачи в `:task-runtime`],
  [Безопасность], [AES, проверка ключа без полного decrypt, скрытие служебных путей],
  [Расширяемость], [`vault-contracts`, регистрация провайдеров],
  [Сопровождаемость], [Модульные тесты 68 + листинги в приложении А],
  [Надёжность], [Room-транзакции, восстановление журнала после сбоя записи],
) <tbl-nfr-arch>

== Вывод

Спроектирована клиентская архитектура с разделением domain, infrastructure и presentation, единым интерфейсом vault и заделом под синхронизацию без передачи ключей. Диаграммы зафиксированы в приложении Г.
