Заменены \n на реальный символ переноса
|
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 105 KiB |
@@ -54,7 +54,8 @@ fork
|
||||
:StorageSyncEngine.syncAllGroups;
|
||||
while (Есть группа синхронизации?) is (да)
|
||||
:Слияние журналов → победитель по пути;
|
||||
:findSourceStorage → applyEntry\nна отстающие Storage;
|
||||
:findSourceStorage → applyEntry
|
||||
на отстающие Storage;
|
||||
endwhile (нет)
|
||||
}
|
||||
end fork
|
||||
|
||||
@@ -13,9 +13,9 @@ skinparam state {
|
||||
skinparam noteBackgroundColor #E3F2FD
|
||||
skinparam noteBorderColor #1565C0
|
||||
|
||||
state "(Б) Список storage\n(LocalVault или VaultBrowser)" as List
|
||||
state "(Б) Список storage (LocalVault / VaultBrowser)" as List
|
||||
|
||||
List --> Create : Создать storage\n(FAB)
|
||||
List --> Create : Создать storage (FAB)
|
||||
Create --> List : Storage создан
|
||||
|
||||
List --> EncryptDlg : Включить шифрование storage
|
||||
@@ -36,7 +36,7 @@ OpenDlg --> Opened : Ключ верный
|
||||
OpenDlg --> List : Отмена / неверный ключ
|
||||
|
||||
state Opened {
|
||||
state "Файлы, секреты, 2FA\n(StorageHome)" as Browse
|
||||
state "Файлы, секреты, 2FA (StorageHome)" as Browse
|
||||
}
|
||||
Opened --> List : Закрыть / заблокировать storage
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ skinparam noteBorderColor #C2185B
|
||||
start
|
||||
|
||||
partition "**Main: нижняя навигация**" {
|
||||
:(A) Вкладка LocalVault\n(один LocalVault на устройстве);
|
||||
:(A) Вкладка LocalVault
|
||||
(один LocalVault на устройстве);
|
||||
note right
|
||||
На экране — список **IStorage**,
|
||||
не список vault
|
||||
@@ -25,9 +26,11 @@ partition "**Main: нижняя навигация**" {
|
||||
backward:Назад с вложенного экрана;
|
||||
switch (Действие?)
|
||||
case (FAB)
|
||||
:createStorage()\nновый **storage** в LocalVault;
|
||||
:createStorage()
|
||||
новый **storage** в LocalVault;
|
||||
case (Выбор storage)
|
||||
:StorageHome:\nфайлы, 2FA, текстовые секреты;
|
||||
:StorageHome:
|
||||
файлы, 2FA, текстовые секреты;
|
||||
case (Вкладка «Удалённые vault»)
|
||||
:Список **IVault** (Yandex по OAuth);
|
||||
if (Нужен OAuth?) then (да)
|
||||
|
||||
@@ -4,18 +4,27 @@ title Контекстная диаграмма Wallenc
|
||||
skinparam defaultFontName "DejaVu Sans"
|
||||
|
||||
actor "Пользователь" as User
|
||||
rectangle "Wallenc\n(Android)" as App {
|
||||
component "UI\nCompose" as UI
|
||||
component "Домен и\nкриптография" as Domain
|
||||
component "Room\nметаданные" as Room
|
||||
rectangle "Wallenc (Android)" as App {
|
||||
component UI [
|
||||
UI
|
||||
Compose
|
||||
]
|
||||
component Domain [
|
||||
Домен и
|
||||
криптография
|
||||
]
|
||||
component Room [
|
||||
Room
|
||||
метаданные
|
||||
]
|
||||
}
|
||||
|
||||
cloud "Внешний провайдер\n(Яндекс Диск API)" as Cloud
|
||||
cloud "Внешний провайдер (Яндекс Диск API)" as Cloud
|
||||
|
||||
User --> UI : storage, vault,\nOAuth, файлы
|
||||
User --> UI : storage, vault, OAuth, файлы
|
||||
UI --> Domain
|
||||
Domain --> Room
|
||||
Domain --> Cloud : ciphertext,\nOAuth, метаданные API
|
||||
Domain --> Cloud : ciphertext, OAuth, метаданные API
|
||||
|
||||
note right of Cloud
|
||||
Сервер приложения
|
||||
|
||||
@@ -8,7 +8,8 @@ skinparam activity {
|
||||
}
|
||||
|
||||
start
|
||||
:Создать **storage** в vault\n(createStorage);
|
||||
:Создать **storage** в vault
|
||||
(createStorage);
|
||||
note right
|
||||
Vault (IVault) не шифруется.
|
||||
Шифрование только у **storage**
|
||||
@@ -18,10 +19,13 @@ if (Включить шифрование storage?) then (да)
|
||||
:enableEncryption(storage);
|
||||
else (нет)
|
||||
endif
|
||||
:openStorage(storage)\nпри необходимости;
|
||||
:Работа с содержимым storage:\nфайлы, 2FA, секреты;
|
||||
:openStorage(storage)
|
||||
при необходимости;
|
||||
:Работа с содержимым storage:
|
||||
файлы, 2FA, секреты;
|
||||
if (Storage в группе синхронизации?) then (да)
|
||||
:StorageSyncEngine\n(журнал ревизий);
|
||||
:StorageSyncEngine
|
||||
(журнал ревизий);
|
||||
else (нет)
|
||||
endif
|
||||
:closeStorage / блокировка;
|
||||
|
||||
@@ -4,19 +4,23 @@ title DFD уровень 0: Wallenc
|
||||
skinparam defaultFontName "DejaVu Sans"
|
||||
|
||||
actor User
|
||||
rectangle "Процесс 0\nWallenc" as P0 {
|
||||
rectangle "Процесс 0 — Wallenc" as P0 {
|
||||
usecase "UI" as UI
|
||||
usecase "Домен" as Dom
|
||||
usecase "Крипто" as Crypto
|
||||
usecase "Адаптеры\nхранилищ" as Store
|
||||
usecase Store [
|
||||
Адаптеры
|
||||
----
|
||||
хранилищ
|
||||
]
|
||||
database "Room" as DB
|
||||
}
|
||||
|
||||
cloud Provider
|
||||
|
||||
User --> UI : команды,\nфайлы
|
||||
User --> UI : команды, файлы
|
||||
UI --> Dom
|
||||
Dom --> Crypto : ключ,\nданные
|
||||
Dom --> Crypto : ключ, данные
|
||||
Dom --> Store
|
||||
Dom --> DB : метаданные
|
||||
Store --> Provider : ciphertext
|
||||
|
||||
@@ -6,12 +6,36 @@ left to right direction
|
||||
|
||||
actor "Пользователь" as User
|
||||
rectangle "Wallenc" {
|
||||
usecase "Управление storage\n(локальный vault)" as UC1
|
||||
usecase "Шифрование\nи открытие storage" as UC2
|
||||
usecase "Работа с\nсодержимым" as UC3
|
||||
usecase "OAuth и\nудалённые vault" as UC4
|
||||
usecase "Синхронизация\nгрупп" as UC5
|
||||
usecase "Фоновые\nзадачи" as UC6
|
||||
usecase UC1 [
|
||||
Управление storage
|
||||
----
|
||||
локальный vault
|
||||
]
|
||||
usecase UC2 [
|
||||
Шифрование
|
||||
----
|
||||
и открытие storage
|
||||
]
|
||||
usecase UC3 [
|
||||
Работа с
|
||||
----
|
||||
содержимым
|
||||
]
|
||||
usecase UC4 [
|
||||
OAuth и
|
||||
----
|
||||
удалённые vault
|
||||
]
|
||||
usecase UC5 [
|
||||
Синхронизация
|
||||
----
|
||||
групп
|
||||
]
|
||||
usecase UC6 [
|
||||
Фоновые
|
||||
----
|
||||
задачи
|
||||
]
|
||||
}
|
||||
|
||||
User --> UC1
|
||||
|
||||
@@ -5,14 +5,22 @@ skinparam defaultFontName "DejaVu Sans"
|
||||
|
||||
node "Устройство Android" {
|
||||
artifact "Wallenc.apk" as App
|
||||
database "Room\n(SQLite)" as DB
|
||||
database DB [
|
||||
Room
|
||||
----
|
||||
(SQLite)
|
||||
]
|
||||
}
|
||||
|
||||
node "Облако провайдера" {
|
||||
artifact "REST API\n(Яндекс Диск)" as API
|
||||
artifact API [
|
||||
REST API
|
||||
----
|
||||
(Яндекс Диск)
|
||||
]
|
||||
}
|
||||
|
||||
App --> DB
|
||||
App --> API : HTTPS,\nOAuth 2.0
|
||||
App --> API : HTTPS, OAuth 2.0
|
||||
|
||||
@enduml
|
||||
|
||||
@@ -18,7 +18,11 @@ package ":domain" as DOM {
|
||||
}
|
||||
|
||||
package ":infrastructure-android" as INF {
|
||||
[Room, OAuth,\nадаптеры]
|
||||
component INF_BLOCK [
|
||||
Room, OAuth,
|
||||
----
|
||||
адаптеры
|
||||
]
|
||||
}
|
||||
|
||||
package ":app" as APP {
|
||||
|
||||
@@ -10,11 +10,14 @@ skinparam activity {
|
||||
start
|
||||
:Пользователь включает шифрование;
|
||||
:Сформировать EncryptKey;
|
||||
:Encryptor: шифрование файлов\n**storage** (IStorageAccessor);
|
||||
:storage.setEncInfo → Room\n(DbStorageMetaInfo);
|
||||
:Encryptor: шифрование файлов
|
||||
**storage** (IStorageAccessor);
|
||||
:storage.setEncInfo → Room
|
||||
(DbStorageMetaInfo);
|
||||
:checkKey(ключ);
|
||||
if (Ключ верный?) then (да)
|
||||
:IUnlockManager.open(storage)\nвиртуальное представление;
|
||||
:IUnlockManager.open(storage)
|
||||
виртуальное представление;
|
||||
:Доступ к файлам storage;
|
||||
else (нет)
|
||||
:Ошибка, storage не открыт;
|
||||
|
||||
@@ -10,13 +10,13 @@ skinparam defaultFontName "DejaVu Sans"
|
||||
|Лояльность|
|
||||
|
||||
|Действия|
|
||||
|Понимает риск\nоблака|
|
||||
|Создаёт storage,\nвключает шифрование storage|
|
||||
|Открывает storage,\nработает с файлами|
|
||||
|Синхронизирует storage\nбез передачи ключей|
|
||||
|Понимает риск облака|
|
||||
|Создаёт storage, включает шифрование storage|
|
||||
|Открывает storage, работает с файлами|
|
||||
|Синхронизирует storage без передачи ключей|
|
||||
|
||||
|Ожидания|
|
||||
|Данные не читаются\nпровайдером|
|
||||
|Данные не читаются провайдером|
|
||||
|Простой ввод пароля|
|
||||
|Быстрый доступ|
|
||||
|Надёжная синхронизация|
|
||||
|
||||
@@ -13,10 +13,12 @@ start
|
||||
|
||||
:Группа Storage (≥ 2 UUID из DbStorageSyncGroup);
|
||||
:Захват блокировок sync (lease);
|
||||
:Параллельно: flush + readSyncJournal\nдля каждого Storage;
|
||||
:Параллельно: flush + readSyncJournal
|
||||
для каждого Storage;
|
||||
|
||||
partition "Слияние (StorageSyncJournalMerge)" {
|
||||
:Для каждого пути — запись\nс максимальной ревизией;
|
||||
:Для каждого пути — запись
|
||||
с максимальной ревизией;
|
||||
note right
|
||||
compare: sequence → actorId → createdAt
|
||||
end note
|
||||
@@ -25,14 +27,18 @@ partition "Слияние (StorageSyncJournalMerge)" {
|
||||
while (Есть необработанный путь?) is (да)
|
||||
:winnerEntry = победитель по пути;
|
||||
:sourceStorage = findSourceStorage(winnerEntry);
|
||||
if (operation == UPSERT\nи source == null?) then (да)
|
||||
if (operation == UPSERT
|
||||
и source == null?) then (да)
|
||||
:пропуск пути;
|
||||
else (нет)
|
||||
while (Есть target Storage?) is (да)
|
||||
if (ревизия target ≥ winner?) then (да)
|
||||
:пропуск target;
|
||||
else (нет)
|
||||
:applyEntry:\nUPSERT — copy stream\nDELETE/TRASH — на target\n(recordSyncJournal = false);
|
||||
:applyEntry:
|
||||
UPSERT — copy stream
|
||||
DELETE/TRASH — на target
|
||||
(recordSyncJournal = false);
|
||||
endif
|
||||
endwhile (нет)
|
||||
endif
|
||||
|
||||
@@ -7,24 +7,38 @@ 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
|
||||
component Meta [
|
||||
Метаданные
|
||||
----
|
||||
журнал sync, имена, размеры
|
||||
]
|
||||
component ML [
|
||||
TFLite / ML Kit
|
||||
----
|
||||
(inference)
|
||||
]
|
||||
component Enc [
|
||||
Зашифрованные
|
||||
----
|
||||
файлы storage
|
||||
]
|
||||
}
|
||||
|
||||
cloud "Провайдер\n(недоверенный)" as Cloud {
|
||||
[Зашифрованные\nобъекты] as Obj
|
||||
cloud "Провайдер (недоверенный)" as Cloud {
|
||||
[Зашифрованные объекты] as Obj
|
||||
}
|
||||
|
||||
UI --> Meta : анализ
|
||||
Meta --> ML : признаки\nбез plaintext
|
||||
ML --> UI : решение /\nподсказка
|
||||
Meta --> ML : признаки без plaintext
|
||||
ML --> UI : решение / подсказка
|
||||
Enc --> Cloud : только ciphertext
|
||||
Enc ..> ML : опционально\nлокальные эмбеддинги\nпосле decrypt на устройстве
|
||||
Enc ..> ML : опционально: эмбеддинги после decrypt на устройстве
|
||||
|
||||
note bottom of ML
|
||||
Обучение: офлайн на размеченных\nсинтетических/агрегированных данных;
|
||||
выгрузка содержимого storage\nна облако для train — не используется
|
||||
Обучение: офлайн на размеченных
|
||||
синтетических/агрегированных данных;
|
||||
выгрузка содержимого storage
|
||||
на облако для train — не используется
|
||||
end note
|
||||
|
||||
@enduml
|
||||
|
||||