Добавлены разделы о ВПК, алгоритме, ИИ
This commit is contained in:
@@ -53,6 +53,8 @@
|
|||||||
| 32 | `fig_32_manual_test_checklist.png` | PlantUML Salt | ready | гл. 5.3 | Таблица-чек-лист T-7…T-12 (как @tbl-testres). **PUML** `fig_32_manual_test_checklist.puml` | fig-32 |
|
| 32 | `fig_32_manual_test_checklist.png` | PlantUML Salt | ready | гл. 5.3 | Таблица-чек-лист T-7…T-12 (как @tbl-testres). **PUML** `fig_32_manual_test_checklist.puml` | fig-32 |
|
||||||
| 33 | `fig_33_storage_secrets_2fa.jpg` | Скриншот UI | ready | гл. 1, 3.4, 5, прил. Б, В | Экран storage: вкладки/разделы секретов и 2FA | fig-33 |
|
| 33 | `fig_33_storage_secrets_2fa.jpg` | Скриншот UI | ready | гл. 1, 3.4, 5, прил. Б, В | Экран storage: вкладки/разделы секретов и 2FA | fig-33 |
|
||||||
| 34 | `fig_34_2fa_single_token.jpg` | Скриншот UI | ready | гл. 1, 3.4, 5, прил. Б, В | Экран 2FA с одним TOTP-токеном | fig-34 |
|
| 34 | `fig_34_2fa_single_token.jpg` | Скриншот UI | ready | гл. 1, 3.4, 5, прил. Б, В | Экран 2FA с одним TOTP-токеном | fig-34 |
|
||||||
|
| 35 | `fig_35_sync_merge_algorithm.png` | PlantUML | ready | гл. 4 | Алгоритм согласования журналов синхронизации. **PUML** `fig_35_sync_merge_algorithm.puml` | fig-35 |
|
||||||
|
| 36 | `fig_36_ml_on_device.png` | PlantUML | ready | гл. 7 | Контур on-device ML без выгрузки plaintext. **PUML** `fig_36_ml_on_device.puml` | fig-36 |
|
||||||
|
|
||||||
## Нумерация в PDF
|
## Нумерация в PDF
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 255 KiB After Width: | Height: | Size: 190 KiB |
BIN
Report/images/fig_35_sync_merge_algorithm.png
Normal file
BIN
Report/images/fig_35_sync_merge_algorithm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
BIN
Report/images/fig_36_ml_on_device.png
Normal file
BIN
Report/images/fig_36_ml_on_device.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
@@ -82,7 +82,7 @@ DFD уровня 0 (рис. @fig-16) отражает потоки между UI
|
|||||||
|
|
||||||
== Проектирование подсистемы синхронизации
|
== Проектирование подсистемы синхронизации
|
||||||
|
|
||||||
Подсистема синхронизации спроектирована как набор независимых операций над журналом изменений каждого `Storage`. Алгоритм выбирает «победителя» по ревизии, копирует или удаляет файлы на целевом хранилище, не расшифровывая данные на сервере. Блокировки предотвращают одновременную синхронизацию одной группы; при отмене задачи блокировки снимаются (покрыто unit-тестами `syncGroupCooperativeCancellationReleasesLocks` и др., гл. 5).
|
Подсистема синхронизации спроектирована как набор независимых операций над журналом изменений каждого `Storage`. Алгоритм выбирает «победителя» по ревизии, копирует или удаляет файлы на целевом хранилище, не расшифровывая данные на сервере. Блокировки предотвращают одновременную синхронизацию одной группы; при отмене задачи блокировки снимаются (покрыто unit-тестами `syncGroupCooperativeCancellationReleasesLocks` и др., гл. 5). Подробное описание реализации и выбора источника для каждого пути — в гл. 4 (§ алгоритм согласования журналов, рис. @fig-35).
|
||||||
|
|
||||||
== Нефункциональные архитектурные решения
|
== Нефункциональные архитектурные решения
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#import "common.typ": pz-fig
|
#import "common.typ": pz-fig, pz-table
|
||||||
|
|
||||||
= Программная реализация
|
= Программная реализация
|
||||||
|
|
||||||
@@ -40,11 +40,72 @@ fun enableEncryption(storage: IStorageInfo, password: String, encryptPath: Boole
|
|||||||
|
|
||||||
`VaultsManager` агрегирует один `LocalVault` и удалённые vault; адаптеры реализуют доступ к файлам внутри каждого `IStorage`. Регистрация удалённых vault — через модуль `:vault-contracts`.
|
`VaultsManager` агрегирует один `LocalVault` и удалённые vault; адаптеры реализуют доступ к файлам внутри каждого `IStorage`. Регистрация удалённых vault — через модуль `:vault-contracts`.
|
||||||
|
|
||||||
=== Проект модуля синхронизации
|
=== Модуль синхронизации хранилищ
|
||||||
|
|
||||||
В Room добавлена сущность `DbStorageSyncGroup`; спроектирован `SyncWorker` и очередь UUID для фонового сравнения историй коммитов (рис. @fig-01–@fig-03). Реализация синхронизации находится в стадии развития.
|
В Room хранится сущность `DbStorageSyncGroup` — набор UUID `Storage`, которые должны иметь согласованное состояние. Запуск синхронизации выполняется через `RunStorageSyncUseCase` / `WorkManager` и debounce при изменении файлов (рис. @fig-01–@fig-03). Движок `StorageSyncEngine` (модуль `:usecases`) реализует согласование журналов изменений; доработка касается в основном политики фонового расписания и UX отображения прогресса.
|
||||||
|
|
||||||
Модель синхронизации опирается на аналогию с распределённой системой контроля версий: для каждого `Storage` ведётся история коммитов; сервис по таймеру или через `WorkManager` сравнивает локальную и удалённую истории и приводит зашифрованное содержимое к согласованному состоянию. Ключи шифрования в этот обмен не включаются — провайдер видит только зашифрованные объекты. Модуль `:task-runtime` зарезервирован для фоновых задач длительного шифрования и синхронизации без блокировки UI.
|
Для каждого `Storage` ведётся журнал изменений по относительным путям пользовательских файлов. Запись журнала (`StorageSyncJournalEntry`) содержит операцию (`UPSERT`, `TRASH`, `DELETE`) и ревизию (`sequence`, `actorId`, `createdAt`). Ключи шифрования в обмен не включаются — провайдер видит только зашифрованные объекты. Модуль `:task-runtime` обслуживает длительные задачи шифрования и синхронизации без блокировки UI.
|
||||||
|
|
||||||
|
=== Алгоритм согласования журналов синхронизации
|
||||||
|
|
||||||
|
Синхронизация одной группы выполняется в несколько этапов (рис. @fig-35).
|
||||||
|
|
||||||
|
#pz-fig("fig_35_sync_merge_algorithm.png", [Алгоритм согласования журналов (StorageSyncEngine)], "fig-35")
|
||||||
|
|
||||||
|
*Подготовка.* По UUID из `DbStorageSyncGroup` загружаются объекты `IStorage`. Если в группе меньше двух хранилищ или несовместимы параметры шифрования, синхронизация пропускается. На каждом accessor запрашивается блокировка sync (lease на удалённом диске — best-effort; внутри процесса группа сериализуется `Mutex`). Параллельно для каждого storage вызываются `flushPendingSyncJournal()` и `readSyncJournal()`; служебные пути отфильтровываются (`StorageSyncPaths.isSyncableUserPath`).
|
||||||
|
|
||||||
|
*Слияние журналов.* Объект `StorageSyncJournalMerge` объединяет журналы в отображение «путь → победитель». Для каждого пути остаётся запись с наибольшей ревизией. Сравнение реализовано функцией `compareEntries`: сначала `revision.sequence`, при равенстве — `actorId`, затем `createdAt`. Такой порядок обеспечивает детерминированный выбор одной записи при конкурентных изменениях на разных устройствах.
|
||||||
|
|
||||||
|
*Выбор источника для пути.* После слияния для каждой пары (путь, `winnerEntry`) вызывается `findSourceStorage`:
|
||||||
|
|
||||||
|
+ при `UPSERT` — первый `Storage`, у которого запись по этому пути *совпадает* с победителем (`compareEntries == 0`): оттуда читаются байты для копирования;
|
||||||
|
+ при `DELETE` или `TRASH` — первый `Storage`, где путь ещё присутствует в журнале (или любой storage группы, если записей нет): оттуда инициируется удаление на целях.
|
||||||
|
|
||||||
|
Если для `UPSERT` источник не найден, путь пропускается (файл уже отсутствует на всех носителях).
|
||||||
|
|
||||||
|
*Распространение на цели.* Для каждого `target` в группе, отличного от источника, сравнивается ревизия записи на цели с `winnerEntry`. Если цель уже не слабее победителя (`compareEntries(target, winner) >= 0`), шаг пропускается. Иначе вызывается `applyEntry`: для `UPSERT` — потоковое копирование `openRead` → `openWrite`; для `DELETE` / `TRASH` — `delete` или `moveToTrash`. Все операции выполняются с `recordSyncJournal = false`, чтобы не порождать цикл повторной синхронизации. Ошибки отдельных путей учитываются счётчиком `applyFailures`, отмена кооперативная (проверка `syncGeneration`, снятие блокировок в `finally`).
|
||||||
|
|
||||||
|
Фрагмент сравнения ревизий и выбора источника:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
private fun compareEntries(a: StorageSyncJournalEntry, b: StorageSyncJournalEntry): Int {
|
||||||
|
val seqCmp = a.revision.sequence.compareTo(b.revision.sequence)
|
||||||
|
if (seqCmp != 0) return seqCmp
|
||||||
|
val actorCmp = a.revision.actorId.compareTo(b.revision.actorId)
|
||||||
|
if (actorCmp != 0) return actorCmp
|
||||||
|
return a.revision.createdAt.compareTo(b.revision.createdAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findSourceStorage(..., winnerEntry: StorageSyncJournalEntry): IStorage? {
|
||||||
|
if (winnerEntry.operation == DELETE || winnerEntry.operation == TRASH) {
|
||||||
|
return storages.firstOrNull { entriesByStorage[it.uuid]?.get(path) != null }
|
||||||
|
?: storages.firstOrNull()
|
||||||
|
}
|
||||||
|
return storages.firstOrNull { storage ->
|
||||||
|
val entry = entriesByStorage[storage.uuid]?.get(path) ?: return@firstOrNull false
|
||||||
|
compareEntries(entry, winnerEntry) == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Ограничения модели.* Механизм не является полноценным CRDT: конфликты снимаются фиксированным порядком ревизий, а не автоматическим слиянием содержимого. Содержимое файла при расхождении версий без роста `sequence` на одном пути не анализируется побайтно. Шифротекст передаётся как есть; расшифровка на стороне провайдера не предполагается. Корректность алгоритма проверена unit-тестами `StorageSyncEngineTest` (гл. 5): слияние одной записи на путь, пропуск цели с актуальной ревизией, копирование и удаление, cooperative cancellation.
|
||||||
|
|
||||||
|
=== Использование средств ИИ при разработке
|
||||||
|
|
||||||
|
Разработка Wallenc велась в два этапа. На первом этапе исполнитель самостоятельно спроектировал доменную модель (иерархия vault → storage → файлы, единый `VaultsManager`), навигацию между экранами, визуальный стиль UI на Jetpack Compose, границы Gradle-модулей и каркас use case-слоя. Криптографический контур (`Encryptor`, привязка ключей к storage), журнал синхронизации и сценарии OAuth проектировались и проверялись вручную.
|
||||||
|
|
||||||
|
На втором этапе, после готовности архитектурного каркаса, наращивание функционала выполнялось с помощью среды Cursor (модели семейства Composer): адаптеры Yandex Disk и локального storage, движок `StorageSyncEngine`, экраны 2FA и текстовых секретов, unit-тесты. После каждой генерации код просматривался в diff, запускались модульные тесты (`./gradlew :usecases:test` и смежные модули), критичные сценарии проверялись на устройстве.
|
||||||
|
|
||||||
|
#pz-table(
|
||||||
|
[Роли при разработке (фрагмент)],
|
||||||
|
3,
|
||||||
|
table.header([Этап], [Исполнитель], [Инструмент / метод]),
|
||||||
|
[Домен, навигация, UI-концепция], [Исполнитель ВКР], [Ручное проектирование, Compose],
|
||||||
|
[Адаптеры, sync, тесты, доработка UI], [Исполнитель ВКР + ревью], [Cursor, Gradle test],
|
||||||
|
[Шифрование, OAuth, ревизии журнала], [Исполнитель ВКР], [Ручная ревизия, без автогенерации «вслепую»],
|
||||||
|
) <tbl-ai-dev>
|
||||||
|
|
||||||
|
ИИ использовался как ускоритель шаблонного и повторяющегося кода, а не как замена проектных решений. Риски (неверные сигнатуры API, лишние зависимости, утечки в логи) снижались обязательной проверкой сборки, отсутствием секретов в репозитории и правилами `.gitignore` для локальных конфигураций.
|
||||||
|
|
||||||
== Разработка мобильного приложения на Kotlin (Android)
|
== Разработка мобильного приложения на Kotlin (Android)
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,7 @@
|
|||||||
|
|
||||||
=== Синхронизация, 2FA и use cases
|
=== Синхронизация, 2FA и use cases
|
||||||
|
|
||||||
`StorageSyncEngineTest` моделирует группы синхронизации, копирование и удаление файлов, soft-delete, отмену и блокировки (строки 52–64 табл. @tbl-unit-all). `TwoFaTotpTest` сверяет TOTP с эталоном Java OTP. `StorageDomainUseCasesTest` проверяет CRUD текстовых секретов и 2FA.
|
`StorageSyncEngineTest` моделирует группы синхронизации, копирование и удаление файлов, soft-delete, отмену и блокировки (строки 52–64 табл. @tbl-unit-all); отдельно проверяются слияние журнала (`mergeKeepsSingleEntryPerPath`) и пропуск цели с актуальной ревизией (`syncSkipsWhenTargetRevisionAlreadyWinner`) — см. алгоритм в гл. 4. `TwoFaTotpTest` сверяет TOTP с эталоном Java OTP. `StorageDomainUseCasesTest` проверяет CRUD текстовых секретов и 2FA.
|
||||||
|
|
||||||
#pz-fig("fig_28_gradle_usecases_test.png", [Отчёт Gradle: модуль :usecases], "fig-28")
|
#pz-fig("fig_28_gradle_usecases_test.png", [Отчёт Gradle: модуль :usecases], "fig-28")
|
||||||
|
|
||||||
|
|||||||
45
Report/includes/ch07-vpk.typ
Normal file
45
Report/includes/ch07-vpk.typ
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#import "common.typ": pz-fig, pz-table
|
||||||
|
|
||||||
|
= Вариативная профессиональная компетенция (ВПК-2)
|
||||||
|
|
||||||
|
В рамках образовательной программы по направлению 09.03.04 «Программная инженерия» формируется вариативная профессиональная компетенция (ВПК-2):
|
||||||
|
|
||||||
|
#emph[Способен решать прикладные задачи анализа данных и принятия решений с использованием искусственного интеллекта.]
|
||||||
|
|
||||||
|
В текущей версии Wallenc модели машинного обучения в runtime не внедрены: продукт строится на zero-knowledge модели, отсутствует доверенный сервер приложения, а выгрузка расшифрованного содержимого vault на облако для обучения противоречила бы заявленным требованиям безопасности. Ниже рассмотрено, какие прикладные задачи анализа данных и автоматизированных решений *могли бы* быть добавлены в перспективе без нарушения клиентской модели угроз.
|
||||||
|
|
||||||
|
== Связь компетенции с предметом ВКР
|
||||||
|
|
||||||
|
Wallenc уже оперирует структурированными данными, пригодными для анализа: журнал синхронизации (пути, операции, ревизии, метки времени), метаданные файлов (имя, размер, тип по расширению), события фоновых задач. Это не «сырой» пользовательский контент, а агрегаты, которые можно обрабатывать локально. Компетенция ВПК-2 в контексте ВКР раскрывается постановкой задач, выбором данных и моделей, метриками качества и правилами принятия решений — даже если в MVP остаётся только проектный анализ.
|
||||||
|
|
||||||
|
== Прикладные задачи анализа данных и принимаемые решения
|
||||||
|
|
||||||
|
#pz-table(
|
||||||
|
[Гипотетические задачи ИИ в экосистеме Wallenc],
|
||||||
|
(1.05fr, 1.15fr, 1.05fr, 0.82fr, 1.08fr),
|
||||||
|
table.header([Задача], [Данные для анализа], [Тип модели], [Где inference], [Решение для пользователя]),
|
||||||
|
[Классификация и теги файлов], [Имя, расширение, размер; опционально эмбеддинг после локального decrypt], [#text(hyphenate: true, lang: "ru")[Лёгкий класси#sym.zws фикатор / k-NN]], [On-device (TFLite)], [Предложить теги, группировку в vault],
|
||||||
|
[Аномалии в журнале sync], [Частота операций по путям, время, actorId], [Isolation Forest, пороговые правила], [On-device], [Предупреждение о подозрительной активности],
|
||||||
|
[Похожие имена / дубликаты], [Нормализованные имена, размер], [Эмбеддинги строк + косинусная близость], [On-device], [Подсказка при синхронизации или импорте],
|
||||||
|
[Импорт секрета со скриншота], [Изображение экрана (только по действию пользователя)], [OCR (ML Kit)], [On-device], [Заполнить поле текстового секрета],
|
||||||
|
) <tbl-vpk-ml-tasks>
|
||||||
|
|
||||||
|
Каждая строка таблицы связывает *анализ данных* (входные признаки) с *решением* (действие системы или рекомендация), что соответствует формулировке компетенции.
|
||||||
|
|
||||||
|
== Модели, обучение и развёртывание
|
||||||
|
|
||||||
|
*Классификация файлов.* Обучающая выборка может формироваться из синтетических имён и публичных датасетов типов файлов без доступа к реальным vault пользователей. Пайплайн: разметка классов (документ, изображение, архив) → обучение компактной сети (MobileNet-подобный backbone) → квантизация → конвертация в TensorFlow Lite @tflite-docs. Метрики: accuracy, F1 по классам на hold-out.
|
||||||
|
|
||||||
|
*Детектор аномалий sync.* Признаки: число UPSERT/DELETE за окно времени, доля новых путей, смена `actorId`. Обучение на журналах, сгенерированных unit-тестами и симуляциями `StorageSyncEngineTest`, плюс размеченные «нормальные» и «атакующие» сценарии. Метрики: precision/recall для класса «аномалия». Решение: показать уведомление, не блокировать sync автоматически без подтверждения.
|
||||||
|
|
||||||
|
*OCR.* Google ML Kit Text Recognition @mlkit-text позволяет извлечь текст без собственного обучения; дообучение нужно только для специфичных шрифтов. Решение: предзаполнить поле секрета с возможностью редактирования.
|
||||||
|
|
||||||
|
Общая схема on-device inference приведена на рис. @fig-36: метаданные и признаки не покидают устройство в открытом виде; обучение на расшифрованном содержимом всех пользователей в облаке для Wallenc неприемлемо. Альтернатива — *федеративное обучение* только на агрегированных градиентах по opt-in, без централизованного хранения файлов.
|
||||||
|
|
||||||
|
#pz-fig("fig_36_ml_on_device.png", [Гипотетический контур on-device ML], "fig-36")
|
||||||
|
|
||||||
|
== Этика, ограничения и вывод по ВПК-2
|
||||||
|
|
||||||
|
Любой модуль ИИ должен быть отключаемым (opt-in), объяснять пользователю основание рекомендации (например, «похожее имя файла») и не подменять явное действие при удалении или синхронизации. Конфликт с E2E возникает, если отправлять ciphertext или ключи на внешний API inference — в проекте такой путь не рассматривается.
|
||||||
|
|
||||||
|
*Вывод.* Компетенция «решать прикладные задачи анализа данных и принятия решений с использованием искусственного интеллекта» в пояснительной записке раскрыта анализом применимости ML к Wallenc: сформулированы задачи, источники данных, типы моделей, метрики обучения и границы развёртывания on-device. Внедрение в текущий MVP не выполнялось осознанно — в соответствии с целями ВКР по защищённому хранению без доверенного backend.
|
||||||
@@ -160,11 +160,19 @@
|
|||||||
let start-page = state("pz-table-start-page", none)
|
let start-page = state("pz-table-start-page", none)
|
||||||
figure(
|
figure(
|
||||||
kind: table,
|
kind: table,
|
||||||
|
{
|
||||||
|
show table: set text(hyphenate: true, lang: "ru")
|
||||||
|
show table.cell: it => {
|
||||||
|
set align(left + top)
|
||||||
|
set par(justify: false)
|
||||||
|
it
|
||||||
|
}
|
||||||
context {
|
context {
|
||||||
let fig-loc = here()
|
let fig-loc = here()
|
||||||
let tab-num = counter(figure.where(kind: table)).at(fig-loc).first()
|
let tab-num = counter(figure.where(kind: table)).at(fig-loc).first()
|
||||||
start-page.update(none)
|
start-page.update(none)
|
||||||
pz-table-inner(columns, header-cells, tab-num, start-page, ..arguments(..tail))
|
pz-table-inner(columns, header-cells, tab-num, start-page, ..arguments(..tail))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
caption: caption,
|
caption: caption,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
В пояснительной записке рассмотрены анализ предметной области, проектирование и реализация мобильного приложения для защищённого хранения пользовательских данных (Wallenc).
|
В пояснительной записке рассмотрены анализ предметной области, проектирование и реализация мобильного приложения для защищённого хранения пользовательских данных (Wallenc).
|
||||||
|
|
||||||
По главе 1 сформированы требования и выполнен сравнительный анализ аналогов; обоснован выбор стека Kotlin/Compose/Room/Hilt. По главе 2 спроектированы бизнес-процессы, DFD, UML-диаграммы и модель данных Room. Глава 3 описывает пользовательские сценарии и интерфейсные решения. Глава 4 представляет реализованные модули; полный исходный код приведён в приложении А. Глава 5 документирует план и результаты тестирования. Глава 6 содержит краткую экономическую оценку.
|
По главе 1 сформированы требования и выполнен сравнительный анализ аналогов; обоснован выбор стека Kotlin/Compose/Room/Hilt. По главе 2 спроектированы бизнес-процессы, DFD, UML-диаграммы и модель данных Room. Глава 3 описывает пользовательские сценарии и интерфейсные решения. Глава 4 представляет реализованные модули, алгоритм `StorageSyncEngine` и методологию разработки с применением ИИ-ассистента Cursor; полный исходный код приведён в приложении А. Глава 5 документирует план и результаты тестирования. Глава 6 содержит краткую экономическую оценку. Глава 7 раскрывает ВПК-2: прикладные задачи анализа данных и принятия решений с использованием ИИ в перспективном развитии Wallenc.
|
||||||
|
|
||||||
*Цель работы достигнута*: разработан и протестирован прототип Android-приложения с иерархией vault → storage → файлы, клиентским шифрованием, OAuth Яндекс и проектным контуром синхронизации.
|
*Цель работы достигнута*: разработан и протестирован прототип Android-приложения с иерархией vault → storage → файлы, клиентским шифрованием, OAuth Яндекс и реализованным движком синхронизации по журналам ревизий.
|
||||||
|
|
||||||
*Перспективы развития*: завершение синхронизации по модели коммитов; поддержка дополнительных провайдеров; расширение автоматизированных UI-тестов.
|
*Перспективы развития*: расширение фонового расписания sync; поддержка дополнительных провайдеров; опциональные on-device модели по сценариям гл. 7; расширение автоматизированных UI-тестов.
|
||||||
|
|
||||||
Программная документация приведена в приложении Б; иллюстрации интерфейса — в приложении В.
|
Программная документация приведена в приложении Б; иллюстрации интерфейса — в приложении В.
|
||||||
|
|
||||||
|
|||||||
@@ -23,4 +23,4 @@
|
|||||||
|
|
||||||
*Практическая значимость* — использование результатов при дальнейшей разработке продукта и в учебных проектах по мобильной разработке и информационной безопасности.
|
*Практическая значимость* — использование результатов при дальнейшей разработке продукта и в учебных проектах по мобильной разработке и информационной безопасности.
|
||||||
|
|
||||||
Пояснительная записка состоит из введения, шести глав, заключения, списка использованных источников и трёх приложений (листинги исходного кода, программная документация, скриншоты интерфейса). В главе 1 обоснована актуальность и приведено сравнение аналогов; глава 2 описывает архитектуру и модель Room; глава 3 — UX и пользовательские сценарии; глава 4 — реализацию по модулям; глава 5 — тестирование; глава 6 — экономическую оценку.
|
Пояснительная записка состоит из введения, семи глав, заключения, списка использованных источников и трёх приложений (листинги исходного кода, программная документация, скриншоты интерфейса). В главе 1 обоснована актуальность и приведено сравнение аналогов; глава 2 описывает архитектуру и модель Room; глава 3 — UX и пользовательские сценарии; глава 4 — реализацию по модулям, алгоритм синхронизации журналов и применение ИИ-ассистента при разработке; глава 5 — тестирование; глава 6 — экономическую оценку; глава 7 — вариативную профессиональную компетенцию по анализу данных и решениям с использованием ИИ.
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
' Увеличенный растр для вставки в отчёт (Word / печать)
|
' Увеличенный растр для вставки в отчёт (Word / печать)
|
||||||
scale 3
|
scale 3
|
||||||
title
|
title
|
||||||
Wallenc — старт приложения и параллельная синхронизация
|
Wallenc — старт приложения и фоновая синхронизация
|
||||||
(проектное решение; фоновая синхронизация к реализации)
|
|
||||||
end title
|
end title
|
||||||
|
|
||||||
skinparam defaultFontName "DejaVu Sans"
|
skinparam defaultFontName "DejaVu Sans"
|
||||||
@@ -45,32 +44,18 @@ partition "**Основной поток (UI)**" {
|
|||||||
fork
|
fork
|
||||||
partition "**Фон: синхронизация (по таймеру)**" #E8F5E9 {
|
partition "**Фон: синхронизация (по таймеру)**" #E8F5E9 {
|
||||||
note right
|
note right
|
||||||
**Проектная механика (не реализовано в коде)**
|
**Реализовано:** StorageSyncEngine,
|
||||||
• Таймер / WorkManager Android
|
журнал изменений по путям, merge ревизий
|
||||||
• Таблица в Room: UUID **storage_id**
|
• Room: DbStorageSyncGroup (UUID группы)
|
||||||
для очереди синхронизации
|
• WorkManager / debounce — запуск sync
|
||||||
• Для каждого storage — **история коммитов**
|
• Ключи шифрования провайдеру не передаются
|
||||||
(аналог git): дерево/цепочка снимков
|
Подробный алгоритм — гл. 4, рис. 35
|
||||||
• Сервис: сравнение коммитов
|
|
||||||
локально vs удалённо → вычисление diff
|
|
||||||
• Применение изменений →
|
|
||||||
**одинаковое зашифрованное содержимое**
|
|
||||||
на клиенте и у провайдера
|
|
||||||
(ключи на сервер не передаются)
|
|
||||||
end note
|
end note
|
||||||
:По срабатыванию таймера:
|
:Запуск sync (Worker / debounce);
|
||||||
запуск **SyncService** / Worker;
|
:StorageSyncEngine.syncAllGroups;
|
||||||
:Чтение из БД списка
|
while (Есть группа синхронизации?) is (да)
|
||||||
**UUID storage** из очереди;
|
:Слияние журналов → победитель по пути;
|
||||||
while (Есть необработанный UUID?) is (да)
|
:findSourceStorage → applyEntry\nна отстающие Storage;
|
||||||
:Загрузить историю **коммитов**
|
|
||||||
для этого Storage (локально + у провайдера);
|
|
||||||
:Найти расхождения
|
|
||||||
(common ancestor / merge);
|
|
||||||
:Свести содержимое
|
|
||||||
к единому состоянию;
|
|
||||||
:Обновить очередь /
|
|
||||||
метаданные синхронизации;
|
|
||||||
endwhile (нет)
|
endwhile (нет)
|
||||||
}
|
}
|
||||||
end fork
|
end fork
|
||||||
|
|||||||
44
Report/puml/fig_35_sync_merge_algorithm.puml
Normal file
44
Report/puml/fig_35_sync_merge_algorithm.puml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
@startuml fig_35_sync_merge_algorithm
|
||||||
|
scale 2.5
|
||||||
|
title Wallenc — алгоритм согласования журналов синхронизации (StorageSyncEngine)
|
||||||
|
|
||||||
|
skinparam defaultFontName "DejaVu Sans"
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor #F8F8F8
|
||||||
|
BorderColor #333333
|
||||||
|
DiamondBackgroundColor #E8F4FF
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
|
||||||
|
:Группа Storage (≥ 2 UUID из DbStorageSyncGroup);
|
||||||
|
:Захват блокировок sync (lease);
|
||||||
|
:Параллельно: flush + readSyncJournal\nдля каждого Storage;
|
||||||
|
|
||||||
|
partition "Слияние (StorageSyncJournalMerge)" {
|
||||||
|
:Для каждого пути — запись\nс максимальной ревизией;
|
||||||
|
note right
|
||||||
|
compare: sequence → actorId → createdAt
|
||||||
|
end note
|
||||||
|
}
|
||||||
|
|
||||||
|
while (Есть необработанный путь?) is (да)
|
||||||
|
:winnerEntry = победитель по пути;
|
||||||
|
:sourceStorage = findSourceStorage(winnerEntry);
|
||||||
|
if (operation == UPSERT\nи source == null?) then (да)
|
||||||
|
:пропуск пути;
|
||||||
|
else (нет)
|
||||||
|
while (Есть target Storage?) is (да)
|
||||||
|
if (ревизия target ≥ winner?) then (да)
|
||||||
|
:пропуск target;
|
||||||
|
else (нет)
|
||||||
|
:applyEntry:\nUPSERT — copy stream\nDELETE/TRASH — на target\n(recordSyncJournal = false);
|
||||||
|
endif
|
||||||
|
endwhile (нет)
|
||||||
|
endif
|
||||||
|
endwhile (нет)
|
||||||
|
|
||||||
|
:Снятие блокировок;
|
||||||
|
stop
|
||||||
|
|
||||||
|
@enduml
|
||||||
30
Report/puml/fig_36_ml_on_device.puml
Normal file
30
Report/puml/fig_36_ml_on_device.puml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
@startuml fig_36_ml_on_device
|
||||||
|
scale 2.5
|
||||||
|
title Wallenc — гипотетический контур on-device ML (без расшифровки на сервере)
|
||||||
|
|
||||||
|
skinparam defaultFontName "DejaVu Sans"
|
||||||
|
skinparam componentStyle rectangle
|
||||||
|
|
||||||
|
package "Приложение Wallenc" {
|
||||||
|
[UI / use cases] as UI
|
||||||
|
[Метаданные:\nжурнал sync, имена,\nразмеры] as Meta
|
||||||
|
[TFLite / ML Kit\n(inference)] as ML
|
||||||
|
[Зашифрованные\nфайлы storage] as Enc
|
||||||
|
}
|
||||||
|
|
||||||
|
cloud "Провайдер\n(недоверенный)" as Cloud {
|
||||||
|
[Зашифрованные\nобъекты] as Obj
|
||||||
|
}
|
||||||
|
|
||||||
|
UI --> Meta : анализ
|
||||||
|
Meta --> ML : признаки\nбез plaintext
|
||||||
|
ML --> UI : решение /\nподсказка
|
||||||
|
Enc --> Cloud : только ciphertext
|
||||||
|
Enc ..> ML : опционально\nлокальные эмбеддинги\nпосле decrypt на устройстве
|
||||||
|
|
||||||
|
note bottom of ML
|
||||||
|
Обучение: офлайн на размеченных\nсинтетических/агрегированных данных;
|
||||||
|
выгрузка содержимого vault\nна облако для train — не используется
|
||||||
|
end note
|
||||||
|
|
||||||
|
@enduml
|
||||||
@@ -92,3 +92,25 @@
|
|||||||
year = {2026},
|
year = {2026},
|
||||||
note = {Приватный репозиторий GitLab ЮФУ; доступ для проверки по запросу руководителя ВКР},
|
note = {Приватный репозиторий GitLab ЮФУ; доступ для проверки по запросу руководителя ВКР},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@misc{tflite-docs,
|
||||||
|
title = {TensorFlow Lite},
|
||||||
|
author = {{Google}},
|
||||||
|
year = {2026},
|
||||||
|
url = {https://www.tensorflow.org/lite},
|
||||||
|
}
|
||||||
|
|
||||||
|
@misc{mlkit-text,
|
||||||
|
title = {ML Kit: Text recognition},
|
||||||
|
author = {{Google}},
|
||||||
|
year = {2026},
|
||||||
|
url = {https://developers.google.com/ml-kit/vision/text-recognition},
|
||||||
|
}
|
||||||
|
|
||||||
|
@book{goodfellow-dl,
|
||||||
|
title = {Deep Learning},
|
||||||
|
author = {Goodfellow, I. and Bengio, Y. and Courville, A.},
|
||||||
|
year = {2016},
|
||||||
|
publisher = {MIT Press},
|
||||||
|
url = {https://www.deeplearningbook.org/},
|
||||||
|
}
|
||||||
|
|||||||
1552600
Report/Пояснительная_записка_ПытковРЕ.pdf
Normal file
1552600
Report/Пояснительная_записка_ПытковРЕ.pdf
Normal file
File diff suppressed because one or more lines are too long
@@ -46,6 +46,7 @@
|
|||||||
#include "includes/ch04.typ"
|
#include "includes/ch04.typ"
|
||||||
#include "includes/ch05.typ"
|
#include "includes/ch05.typ"
|
||||||
#include "includes/ch06.typ"
|
#include "includes/ch06.typ"
|
||||||
|
#include "includes/ch07-vpk.typ"
|
||||||
#include "includes/conclusion.typ"
|
#include "includes/conclusion.typ"
|
||||||
|
|
||||||
// Заголовок списка источников задаётся в gost (bibliography.title).
|
// Заголовок списка источников задаётся в gost (bibliography.title).
|
||||||
|
|||||||
Reference in New Issue
Block a user