# Отчёт по 2-му предварительному этапу производственной практики  
**Проект:** Wallenc — универсальный кошелёк для безопасного хранения данных на небезопасных хранилищах без собственного сервера.  
**Период выполнения этапа:** 29.03.2026–19.04.2026

## Введение

На втором этапе производственной практики выполнена реализация функционального ядра мобильного приложения Wallenc и ключевых пользовательских сценариев работы с локальными и удалёнными хранилищами.  
Основной фокус этапа — перевод проектных решений первого этапа в рабочий код: управление vault, шифрование, хранение метаданных и ключевой информации, а также реализация интерфейсов для повседневной работы пользователя.

В рамках этапа обеспечена практическая готовность базовой версии приложения к использованию: реализованы операции создания, просмотра, переименования, удаления и защиты vault, а также подготовлена инфраструктура для дальнейшего расширения удалённых сценариев.

Практический результат этапа выражается не только в наличии отдельных модулей, но и в их совместной работе в рамках одного приложения: пользователь может создавать хранилища, включать защиту, открывать и закрывать зашифрованные представления, видеть состояние vault в интерфейсе и выполнять основные операции сопровождения. Все ключевые сценарии выполнены в рамках единой архитектуры, выбранной на первом этапе.

## Краткая характеристика выполненного этапа

За период 29.03.2026–19.04.2026 реализован целостный набор функций, закрывающий требования второго предварительного этапа:

- разработано рабочее ядро управления локальными и удалёнными vault;
- реализованы пользовательские экраны и диалоговые сценарии для основных операций;
- добавлена авторизация в Яндекс как часть удалённого контура;
- внедрено хранение метаданных и служебной информации в Room;
- проведено unit-тестирование криптографии и ручное тестирование экранов.

Таким образом, второй этап завершён с заметным приростом прикладной готовности проекта: архитектура первого этапа переведена в рабочее приложение с подтверждённой функциональностью базового уровня.

## Реализация основных работ (п. 2.1 ТЗ)

### 1) Разработка модуля ядра приложения Wallenc

В рамках ядра приложения реализованы следующие возможности:

- создание и управление локальными vault;
- хранение метаданных vault на устройстве;
- включение шифрования выбранного vault с формированием параметров шифрования;
- открытие и закрытие зашифрованного представления vault с проверкой корректности ключа;
- доступ к содержимому vault через слой абстракции хранилищ;
- сокрытие служебных объектов и фильтрация системных директорий при отображении данных пользователю.

Ядро реализовано в логике модульной архитектуры (domain/data/presentation), что обеспечило разделение бизнес-логики, доступа к данным и UI-слоя.

Для предотвращения конфликтов при параллельных операциях в ядре используется контроль запущенных задач (например, защита от повторного запуска шифрования одного и того же vault до завершения предыдущей операции). Это повысило устойчивость работы приложения при активном пользовательском взаимодействии.

**Скриншот локальных vault:**  
![Локальные vault](images/СКРИНШОТ №1 — локальные vault в приложении.jpg)

### 2) Разработка мобильного приложения на Kotlin (Android)

В пользовательском интерфейсе реализованы ключевые операции работы с vault:

- отображение списка vault;
- переименование и удаление vault;
- включение шифрования vault;
- открытие зашифрованного vault с использованием мастер-ключа;
- просмотр параметров vault (состояние, служебные сведения, статус шифрования);
- модуль работы с содержимым vault;
- блокировка/закрытие vault.

Реализованы диалоговые сценарии подтверждения и настройки операций, что повысило управляемость и предсказуемость действий пользователя.

Интерфейсная часть построена таким образом, чтобы пользователь видел текущее состояние хранилища (зашифровано/не зашифровано, открыто/закрыто) и мог выполнить требуемое действие без перехода в технические служебные экраны. Это улучшило эргономику взаимодействия и снизило число лишних шагов в типовых сценариях.

**Скриншоты диалогов и операций:**  
![Включение шифрования](images/СКРИНШОТ №2 — диалог включения шифрования vault.jpg)  
![Открытие и закрытие vault](images/СКРИНШОТ №3 — диалог открытия⁄закрытия зашифрованного vault.jpg)  
![Переименование и удаление](images/СКРИНШОТ №4 — диалог переименования⁄удаления vault.jpg)

### 3) Реализация модуля работы с небезопасными хранилищами через адаптеры

Реализован модуль адаптерного взаимодействия с типами хранилищ, не требующий собственного серверного контура приложения.  
Подход через адаптеры позволил сохранить единый интерфейс работы с vault и упростить расширение списка поддерживаемых провайдеров.

Технически это важно для дальнейшего масштабирования проекта: добавление нового типа внешнего провайдера не требует переработки пользовательской логики и не нарушает принципы слоистой архитектуры.

### 4) Взаимодействие мобильного клиента с внешними провайдерами через API/SDK

На текущем этапе реализована авторизация через Яндекс (OAuth-сценарий) и интеграция соответствующего пользовательского потока в приложение.  
Выполнена подготовка слоя удалённых vault и связанных сущностей для дальнейшего расширения удалённых операций.

Важно, что реализованный контур уже обеспечивает прикладной сценарий идентификации пользователя во внешнем провайдере и формирует корректную основу для дальнейшего расширения функциональности удалённых операций.

**Скриншоты удалённого контура:**  
![Экран удалённых vault](images/СКРИНШОТ №5 — экран удалённых vault.jpg)  
![Добавление удалённого vault и авторизация](images/СКРИНШОТ №6 — диалог добавления удалённого vault ⁄ авторизация через Яндекс.jpg)

### 5) Реализация хранения ключевой информации и метаданных с использованием Room

Реализован слой локальной БД на Room для хранения:

- таблиц сопоставления ключевой информации и идентификаторов хранилищ;
- таблиц метаданных vault и состояния хранилищ;
- данных, необходимых для восстановления состояния приложения.

Структура БД интегрирована в общий цикл работы приложения и используется как системный слой управления состоянием.

Использование Room позволило обеспечить устойчивое хранение служебной информации между запусками приложения и централизовать доступ к данным через DAO-слой.

**Визуализация Room БД:**  
![Схема Room базы данных](images/ИЗОБРАЖЕНИЕ №7 — визуализация Room базы данных.png)

### 6) Проведение тестирования приложения

По итогам этапа проведено тестирование реализованного функционала:

- выполнено unit-тестирование криптографических компонентов (проверка корректности шифрования/дешифрования и валидации ключа);
- выполнено ручное тестирование экранов и основных пользовательских сценариев работы с vault.

Проведённые проверки подтвердили работоспособность базового функционального ядра второго этапа.

## Фрагменты реализованного кода

Ниже приведены показательные фрагменты кода, отражающие ключевые результаты второго этапа.

### 1) Room-база приложения и состав сущностей

```kotlin
@Database(
    entities = [DbStorageKeyMap::class, DbStorageMetaInfo::class, DbYandexAccount::class],
    version = 4,
    exportSchema = false,
)
abstract class AppDb : IAppDb, RoomDatabase() {
    abstract override val storageKeyMapDao: StorageKeyMapDao
    abstract override val storageMetaInfoDao: StorageMetaInfoDao
    abstract override val yandexAccountDao: YandexAccountDao
}
```

Фрагмент демонстрирует, что на этапе реализована целевая модель хранения метаданных и удалённой учётной информации в Room с разделением доступа через DAO.

### 2) Логика шифрования и открытия зашифрованного vault в ViewModel

```kotlin
fun enableEncryption(storage: IStorageInfo, password: String, encryptPath: Boolean) {
    val key = EncryptKey(password)
    viewModelScope.launch {
        when (manageStoragesEncryptionUseCase.canEncrypt(storage)) {
            ManageStoragesEncryptionUseCase.CanEncryptResult.Allowed -> {
                manageStoragesEncryptionUseCase.enableEncryption(storage, key, encryptPath)
                manageStoragesEncryptionUseCase.openStorage(storage, key, true)
                _messages.emit("Encryption enabled")
            }
            ManageStoragesEncryptionUseCase.CanEncryptResult.AlreadyEncrypted ->
                _messages.emit("Storage is already encrypted")
            else -> _messages.emit("Unsupported operation")
        }
    }
}
```

Фрагмент иллюстрирует, что включение шифрования реализовано как управляемый сценарий с валидацией состояния, запуском шифрования и последующим открытием зашифрованного представления.

### 3) UI-операции над удалёнными vault

```kotlin
FloatingActionButton(
    onClick = {
        if (!uiState.isBusy) viewModel.setAddChoiceVisible(true)
    },
) {
    Icon(Icons.Filled.Add, contentDescription = stringResource(R.string.remote_vaults_add_cd))
}
...
FilledTonalButton(
    onClick = {
        viewModel.setAddChoiceVisible(false)
        viewModel.yandexSignIn.launch { outcome ->
            when (outcome) {
                is RemoteYandexAuthResult.Success ->
                    viewModel.onYandexAuthSuccess(outcome.accessToken)
                is RemoteYandexAuthResult.Failure -> { /* сообщение об ошибке */ }
                RemoteYandexAuthResult.Cancelled -> { }
            }
        }
    }
)
```

В данном фрагменте отражён завершённый пользовательский путь запуска авторизации для удалённого провайдера непосредственно из интерфейса приложения.

### 4) Unit-тесты криптографического контура

```kotlin
@Test
fun `test correct key for StorageEncryptionInfo`() {
    val encInfo = Encryptor.generateEncryptionInfo(key1)
    val res = Encryptor.checkKey(key = key1, encInfo = encInfo)
    assertEquals(true, res)
}

@Test
fun `test incorrect key for StorageEncryptionInfo`() {
    val encInfo = Encryptor.generateEncryptionInfo(key1)
    val res = Encryptor.checkKey(key = key2, encInfo = encInfo)
    assertEquals(false, res)
}
```

Тесты подтверждают корректную проверку ключа и являются частью подтверждения работоспособности криптографической логики второго этапа.

## Реализация дополнительных работ (п. 2.2 ТЗ)

### 1) Синхронизация зашифрованных данных с удалёнными хранилищами без передачи ключей на сервер

В рамках второго этапа подготовлена и реализована безопасная база для удалённых сценариев:

- внедрён поток авторизации пользователя через Яндекс;
- реализованы сущности и механизм учёта удалённых vault;
- сохранён принцип клиентской защиты данных, при котором ключевая логика шифрования остаётся на стороне приложения.

Это обеспечивает корректную архитектурную основу для дальнейшего развития синхронизационных операций без передачи ключей на сторону внешних сервисов.

### 2) Тестирование пользовательского интерфейса

Проведено ручное тестирование пользовательского интерфейса с проверкой:

- отображения списков локальных и удалённых vault;
- корректности вызова и отработки диалоговых окон;
- стабильности выполнения операций создания, переименования, удаления, шифрования, открытия и закрытия vault.

Ручная проверка проводилась на последовательностях реальных пользовательских действий, что позволило проверить не только отдельные функции, но и их связную работу в рамках типового использования приложения.

## Итоги второго этапа

По результатам второго этапа сформировано и протестировано работоспособное ядро мобильного приложения Wallenc.  
Реализованы ключевые функции управления vault, включения и использования шифрования, хранения служебных данных через Room, а также пользовательские интерфейсы для локальных и удалённых сценариев.

Этап завершён с практическим результатом в виде функционирующего Android-приложения на Kotlin, готового к дальнейшему расширению функциональности удалённой работы с хранилищами и развитию синхронизационных механизмов.

В целом второй этап можно считать успешно завершённым: ключевые задачи реализованы, протестированы и представлены в форме, пригодной для демонстрации и последующего развития проекта на следующем этапе практики.
