# Rosetta Android — Architecture > Документ отражает текущее состояние `rosetta-android` (ветка `dev`) по коду на 2026-04-19. ## 1. Архитектурный профиль Приложение сейчас устроено как layered + service-oriented архитектура: - UI: `MainActivity` + Compose-экраны + ViewModel. - Chat feature orchestration: `ChatViewModel` (host-state) + feature-facade VM + coordinators. - DI: Hilt (`@HiltAndroidApp`, `@AndroidEntryPoint`, модули в `di/AppContainer.kt`). - Runtime orchestration: `ProtocolGateway`/`ProtocolRuntime` -> `RuntimeComposition` (+ legacy facade `ProtocolManager`), `CallManager`, `TransportManager`, `UpdateManager`. - Session/Identity runtime state: `SessionStore`, `SessionReducer`, `IdentityStore`. - Domain сценарии отправки чата: `domain/chats/usecase/*` (text/media/forward/voice/typing/read-receipt/attachments/upload). - Data: `MessageRepository`, `GroupRepository`, `AccountManager`, `PreferencesManager`. - Persistence: Room (`RosettaDatabase`) + DataStore/SharedPreferences. Основная runtime-логика сети вынесена в `RuntimeComposition`, а DI-вход в runtime идет напрямую через `ProtocolRuntime`. `ProtocolManager` переведен в минимальный legacy compatibility facade поверх `ProtocolRuntimeAccess`. DI-вход в network core идет через `ProtocolRuntime` (Hilt singleton). --- ## 2. Слои и границы ```mermaid flowchart TB subgraph ENTRY["Android Entry Points"] E1["RosettaApplication"] E2["MainActivity"] E3["RosettaFirebaseMessagingService"] E4["IncomingCallActivity / CallForegroundService"] end subgraph DI["Hilt Singleton Graph"] D1["ProtocolGateway"] D1A["ProtocolRuntime"] D2["SessionCoordinator"] D3["IdentityGateway"] D4["AccountManager / PreferencesManager"] D5["MessageRepository / GroupRepository"] end subgraph CHAT_UI["Chat UI Orchestration"] C1["ChatDetailScreen / ChatsListScreen"] C2["ChatViewModel (host)"] C3["Messages/Voice/Attachments/Typing ViewModel"] C4["Messages/Forward/Attachments Coordinator"] end subgraph CHAT_DOMAIN["Chat Domain UseCases"] U1["SendText / SendMedia / SendForward"] U2["SendVoice / SendTyping / SendReadReceipt"] U3["CreateAttachment / EncryptAndUpload"] end subgraph SESSION["Session / Identity Runtime"] S1["SessionStore"] S2["SessionReducer"] S3["IdentityStore"] S4["AppSessionCoordinator"] end subgraph NET["Network Runtime"] N0["ProtocolRuntime"] N1C["RuntimeComposition"] N1A["ProtocolManager (compat facade)"] N2["Protocol"] N3["PacketSubscriptionRegistry"] N4["ReadyPacketGate"] end subgraph DATA["Data + Persistence"] R1["MessageRepository"] R2["GroupRepository"] R3["Room: RosettaDatabase"] end ENTRY --> DI DI --> SESSION DI --> NET DI --> DATA DI --> CHAT_UI CHAT_UI --> CHAT_DOMAIN CHAT_UI --> DATA CHAT_DOMAIN --> D1 D1 --> D1A D1A --> N1C N1A --> N1C SESSION --> NET DATA --> NET DATA --> R3 N1C --> N2 ``` --- ## 3. DI и composition root ### 3.1 Hilt - `RosettaApplication` помечен `@HiltAndroidApp`. - Entry points уровня Android-компонентов: `MainActivity`, `IncomingCallActivity`, `CallForegroundService`, `RosettaFirebaseMessagingService`. - Основные модули: - `AppDataModule`: `AccountManager`, `PreferencesManager`. - `AppGatewayModule`: биндинги `ProtocolGateway`, `SessionCoordinator`, `IdentityGateway`, `ProtocolClient`. - `ProtocolGateway` теперь биндится напрямую на `ProtocolRuntime` (без отдельного `ProtocolGatewayImpl` proxy-класса). - `ProtocolClientImpl` остается узким техническим adapter-слоем для repository (`send/sendWithRetry/addLog/wait/unwait`) и делегирует в `ProtocolRuntime` через `Provider`. ### 3.2 UI bridge для composable-слоя UI-композаблы больше не получают runtime-зависимости через `UiEntryPoint`/`EntryPointAccessors`. `UiDependencyAccess.get(...)` из `ui/*` удален (DoD: 0 вхождений). Для non-Hilt `object`-ов (`CallManager`, `TransportManager`, `UpdateManager`, utils) используется `ProtocolRuntimeAccess` + `ProtocolRuntimePort`: - runtime ставится в `RosettaApplication` через `ProtocolRuntimeAccess.install(protocolRuntime)`; - доступ до install запрещен (fail-fast), чтобы не было тихого отката в legacy facade. ### 3.3 Разрыв DI-cycle (Hilt) После перехода на `ProtocolRuntime` был закрыт цикл зависимостей: `MessageRepository -> ProtocolClient -> ProtocolRuntime -> MessageRepository`. Текущее решение: - `ProtocolClientImpl` получает `Provider` (ленивая резолюция). - `ProtocolRuntime` остается singleton-композицией для `MessageRepository/GroupRepository/AccountManager`. - На `assembleDebug/assembleRelease` больше нет `Dagger/DependencyCycle`. --- ## 4. Session lifecycle: единый source of truth ### 4.1 Модель состояния `SessionState`: - `LoggedOut` - `AuthInProgress(publicKey?, reason)` - `Ready(account, reason)` ### 4.2 Модель событий `SessionAction`: - `LoggedOut` - `AuthInProgress` - `Ready` - `SyncFromCachedAccount` ### 4.3 Контур изменения состояния - Только `SessionStore` владеет `MutableStateFlow`. - Только `SessionReducer` вычисляет next-state. - `SessionCoordinator`/`AppSessionCoordinator` больше не мутируют состояние напрямую, а делают `dispatch(action)`. - `SessionStore.dispatch(...)` синхронно обновляет `IdentityStore` для консистентности account/profile/auth-runtime. ```mermaid flowchart LR A["AuthFlow / MainActivity / Unlock / SetPassword"] --> B["SessionCoordinator.dispatch(action)"] B --> C["SessionStore.dispatch(action)"] C --> D["SessionReducer.reduce(current, action)"] D --> E["StateFlow"] C --> F["IdentityStore sync"] ``` ### 4.4 State machine ```mermaid stateDiagram-v2 [*] --> LoggedOut LoggedOut --> AuthInProgress: dispatch(AuthInProgress) AuthInProgress --> Ready: dispatch(Ready) AuthInProgress --> LoggedOut: dispatch(LoggedOut) Ready --> LoggedOut: dispatch(LoggedOut) Ready --> Ready: dispatch(SyncFromCachedAccount(account)) ``` --- ## 5. Network orchestration после декомпозиции `ProtocolRuntime` — DI-фасад runtime слоя и реализация `ProtocolGateway`/`ProtocolRuntimePort`. `RuntimeComposition` — composition-root runtime слоя (сборка service graph + orchestration wiring) и делегирует отдельные зоны ответственности: - Публичные runtime API proxy-методы (connect/auth/directory/packet I/O) убраны из `RuntimeComposition`; публичный runtime surface теперь удерживается в `ProtocolRuntime` + `Runtime*Facade`. - `RuntimeTransportAssembly`: отдельный assembly-блок transport/network wiring (`NetworkReconnectWatcher`, `NetworkConnectivityFacade`, `ProtocolInstanceManager`, `PacketSubscriptionRegistry/Facade`). - `RuntimeMessagingAssembly`: отдельный assembly-блок packet/message/sync wiring (`PacketRouter`, `OutgoingMessagePipelineService`, `PresenceTypingService`, `SyncCoordinator`, `CallSignalBridge`, `InboundPacketHandlerRegistrar`). - `RuntimeStateAssembly`: отдельный assembly-блок connection-state wiring (`ReadyPacketGate`, `BootstrapCoordinator`, `RuntimeLifecycleStateMachine`, `OwnProfileFallbackTimerService`, `ProtocolLifecycleStateStoreImpl`). - `RuntimeRoutingAssembly`: отдельный assembly-блок event-routing wiring (`ConnectionEventRouter` + `ProtocolConnectionSupervisor` как единый orchestration-шаг). - `RuntimeConnectionControlFacade`: high-level connection/session control API (`initialize*`, `connect/reconnect/sync/auth`, `disconnect/destroy`, auth/connect checks). - `RuntimeDirectoryFacade`: directory/device/typing API (`resolve/search user`, cached user lookup, own-profile signal, device accept/decline, typing snapshot by dialog). - `RuntimePacketIoFacade`: packet I/O API (`send/sendWithRetry/resolveRetry`, call/webrtc/ice bridge, `wait/unwait/packetFlow`). - `ProtocolInstanceManager`: singleton lifecycle `Protocol` (create/state/lastError/disconnect/destroy/isAuthenticated/isConnected). - `RuntimeLifecycleStateMachine`: runtime lifecycle state (`ConnectionLifecycleState` + `ConnectionBootstrapContext`) и пересчет transition-логики через `BootstrapCoordinator`. - `RuntimeInitializationCoordinator`: one-time bootstrap runtime (`initialize`, регистрация packet handlers, старт state monitoring, проверка bound DI dependencies). - `ProtocolLifecycleStateStoreImpl`: отдельное lifecycle-state хранилище (`bootstrapContext`, `sessionGeneration`, last-subscribed-token clear hooks, own-profile fallback timer hooks). - `OwnProfileFallbackTimerService`: управление таймером own-profile fallback (`schedule/cancel`) с генерацией timeout-события. - `AuthRestoreService`: восстановление auth-handshake credentials из локального кеша аккаунта (`preferredPublicKey`/fallback + validation + authenticate trigger). - `RuntimeShutdownCoordinator`: централизованный graceful runtime shutdown (`stop watcher`, `destroy subscriptions/protocol`, `clear runtime state/services`, `cancel scope`). - `ConnectionEventRouter`: маршрутизация `ConnectionEvent` к соответствующим coordinator/service handlers без `when(event)` внутри core. - `NetworkConnectivityFacade`: единая обертка network-availability/wait/stop policy поверх `NetworkReconnectWatcher`. - `ConnectionOrchestrator`: connect/reconnect/authenticate + network-aware поведение. - `ProtocolLifecycleCoordinator`: lifecycle/auth/bootstrap transitions (`ProtocolStateChanged`, `SyncCompleted`, own-profile resolved/fallback). - `ProtocolAccountSessionCoordinator`: account-bound transitions (`InitializeAccount`, `Disconnect`) и reset account/session state. - `ReadyPacketDispatchCoordinator`: обработка `SendPacket` через ready-gate (`bypass/enqueue/flush trigger + reconnect policy`). - `ProtocolPostAuthBootstrapCoordinator`: post-auth orchestration (`canRun/tryRun bootstrap`, own profile fetch, push subscribe, post-sync retry/missing-user-info). - `BootstrapCoordinator`: пересчет lifecycle (`AUTHENTICATED`/`BOOTSTRAPPING`/`READY`) и работа с `ReadyPacketGate`. - `SyncCoordinator`: sync state machine (request/timeout, BATCH_START/BATCH_END/NOT_NEEDED, foreground/manual sync). - `PresenceTypingService`: in-memory typing presence с TTL и snapshot `StateFlow`. - `PacketRouter`: user/search cache + resolve/search continuation routing. - `OwnProfileSyncService`: применение собственного профиля из search и синхронизация `IdentityStore`. - `RetryQueueService`: retry очереди отправки `PacketMessage`. - `AuthBootstrapCoordinator`: session-aware post-auth bootstrap (transport/update/profile/sync/push). - `NetworkReconnectWatcher`: единый watcher ожидания сети и fast-reconnect триггеры. - `DeviceVerificationService`: состояние списка устройств + pending verification + resolve packets. - `DeviceRuntimeService`: device-id/handshake device + device verification orchestration. - `CallSignalBridge`: call/webrtc/ice signal send+subscribe bridge. - `PacketSubscriptionFacade`: thin bridge `waitPacket/unwaitPacket/packetFlow` API поверх `PacketSubscriptionRegistry`. - `PacketSubscriptionRegistry`: централизованные подписки на пакеты и fan-out. - `InboundPacketHandlerRegistrar`: централизованная регистрация inbound packet handlers (`0x03/0x05/0x06/0x07/0x08/0x09/0x0B/0x0F/0x14/0x17/0x19`) и делегирование в sync/repository/device/typing/profile сервисы. - `InboundTaskQueueService`: sequential inbound task queue (`enqueue` + `whenTasksFinish`) для Desktop parity (`dialogQueue` semantics). - `OutgoingMessagePipelineService`: отправка `PacketMessage` с retry/error policy. - `ProtocolDebugLogService`: буферизация UI-логов, throttle flush и персистентный protocol trace. На hot-path `ProtocolRuntime` берет runtime API (`RuntimeConnectionControlFacade`/`RuntimeDirectoryFacade`/`RuntimePacketIoFacade`) напрямую из `RuntimeComposition`, поэтому лишний proxy-hop через публичные методы composition не используется. ```mermaid flowchart TB PR["ProtocolRuntime (ProtocolGateway impl)"] --> RC["RuntimeComposition"] RC --> RCC["RuntimeConnectionControlFacade"] RC --> RDF["RuntimeDirectoryFacade"] RC --> RPF["RuntimePacketIoFacade"] RC --> CO["ConnectionOrchestrator"] RC --> PIM["ProtocolInstanceManager"] RC --> RLSM["RuntimeLifecycleStateMachine"] RC --> RIC["RuntimeInitializationCoordinator"] RC --> PLSS["ProtocolLifecycleStateStoreImpl"] RC --> OPFT["OwnProfileFallbackTimerService"] RC --> ARS["AuthRestoreService"] RC --> RSC["RuntimeShutdownCoordinator"] RC --> CER["ConnectionEventRouter"] RC --> NCF["NetworkConnectivityFacade"] RC --> PLC["ProtocolLifecycleCoordinator"] RC --> PAC["ProtocolAccountSessionCoordinator"] RC --> RPDC["ReadyPacketDispatchCoordinator"] RC --> PABC["ProtocolPostAuthBootstrapCoordinator"] RC --> BC["BootstrapCoordinator"] RC --> SC["SyncCoordinator"] RC --> PT["PresenceTypingService"] RC --> PR["PacketRouter"] RC --> OPS["OwnProfileSyncService"] RC --> RQ["RetryQueueService"] RC --> ABC["AuthBootstrapCoordinator"] RC --> NRW["NetworkReconnectWatcher"] RC --> DVS["DeviceVerificationService"] RC --> CSB["CallSignalBridge"] RC --> PSF["PacketSubscriptionFacade"] RC --> PSR["PacketSubscriptionRegistry"] RC --> IPR["InboundPacketHandlerRegistrar"] RC --> IQ["InboundTaskQueueService"] RC --> SUP["ProtocolConnectionSupervisor"] RC --> RPG["ReadyPacketGate"] PIM --> P["Protocol (WebSocket + packet codec)"] ``` --- ## 6. Централизация packet-subscriptions Проблема дублирующихся low-level подписок закрыта через `PacketSubscriptionRegistry`: - На каждый `packetId` создается один bus и один bridge на `Protocol.waitPacket(...)`. - Дальше packet fan-out идет в: - callback API (`waitPacket/unwaitPacket`), - `SharedFlow` (`packetFlow(packetId)`). ```mermaid sequenceDiagram participant Feature as Feature/Service participant PM as Runtime API (Core/Facade) participant REG as PacketSubscriptionRegistry participant P as Protocol Feature->>PM: waitPacket(0x03, callback) PM->>REG: addCallback(0x03, callback) REG->>P: waitPacket(0x03, protocolBridge) [once per packetId] P-->>REG: Packet(0x03) REG-->>Feature: callback(packet) REG-->>Feature: packetFlow(0x03).emit(packet) ``` --- ## 7. Чат-модуль: декомпозиция и message pipeline ### 7.1 Domain слой для сценариев отправки Use-case слой вынесен из UI-пакета в `domain/chats/usecase`: - `SendTextMessageUseCase` - `SendMediaMessageUseCase` - `SendForwardUseCase` - `SendVoiceMessageUseCase` - `SendTypingIndicatorUseCase` - `SendReadReceiptUseCase` - `CreateFileAttachmentUseCase` - `CreateAvatarAttachmentUseCase` - `CreateVideoCircleAttachmentUseCase` - `EncryptAndUploadAttachmentUseCase` Роли use-case слоя: - `SendTextMessageUseCase`/`SendMediaMessageUseCase`: сборка `PacketMessage` + dispatch через `ProtocolGateway` (с учетом `isSavedMessages`). - `SendForwardUseCase`: сборка forward-reply JSON, сборка forward attachment и dispatch. - `SendVoiceMessageUseCase`/`SendTypingIndicatorUseCase`: normalization/decision логика (preview waveform, throttle/guard). - `SendReadReceiptUseCase`: отдельный сценарий отправки `PacketRead`. - `Create*AttachmentUseCase`: типобезопасная сборка attachment-моделей. - `EncryptAndUploadAttachmentUseCase`: общий шаг `encrypt + upload` с возвратом `transportTag/transportServer`. Текущий поток отправки: 1. Feature VM/Coordinator через `ChatViewModel`-host формирует command + encryption context. 2. UseCase строит payload/decision (`PacketMessage` или typed decision model). 3. `ProtocolGateway.sendMessageWithRetry(...)` уводит пакет в network runtime. 4. `RuntimeComposition` (через `ProtocolRuntime`) регистрирует пакет в `RetryQueueService` и отправляет в сеть. 5. До `READY` пакет буферизуется через `ReadyPacketGate`, затем flush. ```mermaid flowchart LR FVM["Feature ViewModel"] --> CVM["ChatViewModel (host)"] CVM --> COORD["Messages/Forward/Attachments Coordinator"] CVM --> UC["domain/chats/usecase/*"] COORD --> UC UC --> GW["ProtocolGateway.sendMessageWithRetry"] GW --> PR["ProtocolRuntime"] PR --> RC["RuntimeComposition"] RC --> RQ["RetryQueueService"] RC --> RG["ReadyPacketGate"] RC --> P["Protocol.sendPacket"] ``` ### 7.2 Декомпозиция ChatViewModel (host + feature/coordinator слой) Для UI-слоя введены feature-facade viewmodel-классы: - `MessagesViewModel` - `VoiceRecordingViewModel` - `AttachmentsViewModel` - `TypingViewModel` Они живут в `ui/chats/ChatFeatureViewModels.kt` и компонуются внутри `ChatViewModel`. Текущий статус: - `VoiceRecordingViewModel` содержит реальный send-pipeline голосовых сообщений. - `TypingViewModel` содержит реальную отправку typing indicator (throttle + packet send). - `MessagesViewModel` содержит orchestration-level entrypoint (`sendMessage`, `retryMessage`), а core text send pipeline вынесен в `MessagesCoordinator` (pending recovery/throttle + reply/forward packet assembly). - `ForwardCoordinator` вынесен из `ChatViewModel`: `sendForwardDirectly` + forward rewrite/re-upload helper-ветка (включая payload resolve из cache/download). - `AttachmentsCoordinator` вынесен из `ChatViewModel`: `updateOptimisticImageMessage`, `sendImageMessageInternal`, `sendVideoCircleMessageInternal` + local cache/update (`localUri` cleanup после отправки). - `AttachmentsFeatureCoordinator` вынесен из `AttachmentsViewModel`: high-level media orchestration для `sendImageGroup*`, `sendFileMessage`, `sendVideoCircleFromUri`, `sendAvatarMessage`. - `AttachmentsViewModel` теперь концентрируется на facade-методах и `sendImageFromUri`/`sendImageMessage`, делегируя крупные media-ветки в coordinator-слой. ```mermaid flowchart TB CD["ChatDetailScreen"] --> MVM["MessagesViewModel"] CD --> TVM["TypingViewModel"] CD --> VVM["VoiceRecordingViewModel"] CD --> AVM["AttachmentsViewModel"] MVM --> CVM["ChatViewModel"] TVM --> CVM VVM --> CVM AVM --> CVM CVM --> MCO["MessagesCoordinator"] CVM --> FCO["ForwardCoordinator"] CVM --> ACO["AttachmentsCoordinator"] CVM --> U["domain/chats/usecase/*"] MCO --> U FCO --> U ACO --> U ``` Важно: после вынесения `MessagesCoordinator`, `ForwardCoordinator` и `AttachmentsCoordinator` `ChatViewModel` выступает как host-state и bridge для feature/coordinator подсистем. ### 7.3 Декомпозиция ChatsListScreen Из `ChatsListScreen.kt` вынесены отдельные composable-секции: - `ChatItem` -> `ChatsListChatItem.kt` - `RequestsSection` -> `ChatsListRequestsSection.kt` - `DrawerContent` -> `ChatsListDrawerContent.kt` Результат: - основной файл экрана меньше и проще для навигации; - повторно используемые куски UI имеют явные file boundaries; - дальнейший рефакторинг drawer/request/chat list можно делать независимо. --- ## 8. Auth/bootstrap: фактический runtime flow ```mermaid sequenceDiagram participant UI as Auth UI (SetPassword/Unlock) participant SC as SessionCoordinatorImpl participant SS as SessionStore participant PG as ProtocolGateway participant RC as RuntimeComposition participant AM as AccountManager UI->>SC: bootstrapAuthenticatedSession(account, reason) SC->>SS: dispatch(AuthInProgress) SC->>PG: initializeAccount(public, private) SC->>PG: connect() SC->>PG: authenticate(public, privateHash) SC->>PG: reconnectNowIfNeeded(...) SC->>AM: setCurrentAccount(public) SC->>SS: dispatch(Ready) RC-->>RC: HANDSHAKE -> AUTHENTICATED -> BOOTSTRAPPING RC-->>RC: SyncCompleted + OwnProfileResolved RC-->>RC: connectionLifecycleState = READY ``` Важно: `SessionState.Ready` (app-session готова) и `connectionLifecycleState = READY` (сеть готова) — это разные state-модели. --- ## 9. Состояния соединения (network lifecycle) `RuntimeComposition.connectionLifecycleState`: - `DISCONNECTED` - `CONNECTING` - `HANDSHAKING` - `AUTHENTICATED` - `BOOTSTRAPPING` - `READY` - `DEVICE_VERIFICATION_REQUIRED` ```mermaid stateDiagram-v2 [*] --> DISCONNECTED DISCONNECTED --> CONNECTING CONNECTING --> HANDSHAKING HANDSHAKING --> DEVICE_VERIFICATION_REQUIRED HANDSHAKING --> AUTHENTICATED AUTHENTICATED --> BOOTSTRAPPING BOOTSTRAPPING --> READY READY --> DISCONNECTED DEVICE_VERIFICATION_REQUIRED --> CONNECTING ``` --- ## 10. Ключевые файлы новой архитектуры - `app/src/main/java/com/rosetta/messenger/di/AppContainer.kt` - `app/src/main/java/com/rosetta/messenger/network/ProtocolRuntime.kt` - `app/src/main/java/com/rosetta/messenger/network/RuntimeComposition.kt` - `app/src/main/java/com/rosetta/messenger/network/RuntimeTransportAssembly.kt` - `app/src/main/java/com/rosetta/messenger/network/RuntimeMessagingAssembly.kt` - `app/src/main/java/com/rosetta/messenger/network/RuntimeStateAssembly.kt` - `app/src/main/java/com/rosetta/messenger/network/RuntimeRoutingAssembly.kt` - `app/src/main/java/com/rosetta/messenger/network/RuntimeConnectionControlFacade.kt` - `app/src/main/java/com/rosetta/messenger/network/RuntimeDirectoryFacade.kt` - `app/src/main/java/com/rosetta/messenger/network/RuntimePacketIoFacade.kt` - `app/src/main/java/com/rosetta/messenger/network/ProtocolClient.kt` - `app/src/main/java/com/rosetta/messenger/network/ProtocolRuntimeAccess.kt` - `app/src/main/java/com/rosetta/messenger/session/AppSessionCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/session/SessionStore.kt` - `app/src/main/java/com/rosetta/messenger/session/SessionReducer.kt` - `app/src/main/java/com/rosetta/messenger/session/SessionAction.kt` - `app/src/main/java/com/rosetta/messenger/session/IdentityStore.kt` - `app/src/main/java/com/rosetta/messenger/network/ProtocolManager.kt` - `app/src/main/java/com/rosetta/messenger/network/PacketSubscriptionRegistry.kt` - `app/src/main/java/com/rosetta/messenger/network/ProtocolConnectionModels.kt` - `app/src/main/java/com/rosetta/messenger/network/ProtocolConnectionSupervisor.kt` - `app/src/main/java/com/rosetta/messenger/network/ReadyPacketGate.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/ConnectionOrchestrator.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/ProtocolInstanceManager.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/RuntimeLifecycleStateMachine.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/RuntimeInitializationCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/ProtocolLifecycleStateStoreImpl.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/OwnProfileFallbackTimerService.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/AuthRestoreService.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/RuntimeShutdownCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/ConnectionEventRouter.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/NetworkConnectivityFacade.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/PacketSubscriptionFacade.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/ProtocolLifecycleCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/ProtocolAccountSessionCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/ReadyPacketDispatchCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/ProtocolPostAuthBootstrapCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/BootstrapCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/SyncCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/PresenceTypingService.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/AuthBootstrapCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/NetworkReconnectWatcher.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/DeviceVerificationService.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/DeviceRuntimeService.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/CallSignalBridge.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/InboundPacketHandlerRegistrar.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/InboundTaskQueueService.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/OutgoingMessagePipelineService.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/ProtocolDebugLogService.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/PacketRouter.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/OwnProfileSyncService.kt` - `app/src/main/java/com/rosetta/messenger/network/connection/RetryQueueService.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/ChatViewModel.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/ChatFeatureViewModels.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/MessagesCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/ForwardCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/AttachmentsCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/AttachmentsFeatureCoordinator.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/OutgoingEncryptionContext.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/OutgoingSendContext.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/ChatDetailScreen.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListScreen.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListChatItem.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListRequestsSection.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListDrawerContent.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListDrawerSections.kt` - `app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListRequestsScreen.kt` - `app/src/main/java/com/rosetta/messenger/domain/chats/usecase/SendTextMessageUseCase.kt` - `app/src/main/java/com/rosetta/messenger/domain/chats/usecase/SendMediaMessageUseCase.kt` - `app/src/main/java/com/rosetta/messenger/domain/chats/usecase/SendForwardUseCase.kt` - `app/src/main/java/com/rosetta/messenger/domain/chats/usecase/SendVoiceMessageUseCase.kt` - `app/src/main/java/com/rosetta/messenger/domain/chats/usecase/SendTypingIndicatorUseCase.kt` - `app/src/main/java/com/rosetta/messenger/domain/chats/usecase/SendReadReceiptUseCase.kt` - `app/src/main/java/com/rosetta/messenger/domain/chats/usecase/CreateAttachmentUseCases.kt` - `app/src/main/java/com/rosetta/messenger/domain/chats/usecase/EncryptAndUploadAttachmentUseCase.kt` - `app/src/main/java/com/rosetta/messenger/domain/chats/usecase/VideoCircleMediaUseCases.kt` --- ## 11. Что осталось как технический долг Актуальные открытые хвосты: - `RuntimeComposition` остается composition-root, но уже существенно сжат (около 501 строки) после выноса `RuntimeTransportAssembly`, `RuntimeMessagingAssembly`, `RuntimeStateAssembly`, `RuntimeRoutingAssembly` и удаления публичных proxy-методов; следующий шаг — перенос части lifecycle/orchestration helper-кода в отдельные domain-oriented service/adapters. - `ProtocolRuntime` и `ProtocolRuntimePort` все еще имеют широкий proxy-surface; нужен audit методов и дальнейшее сужение публичного API по use-case группам. - `ChatViewModel` остается крупным host-классом (state + bridge/proxy API к feature/coordinator/use-case слоям). - High-level media сценарии теперь в `AttachmentsFeatureCoordinator`, но остаются крупными и требуют дальнейшей декомпозиции на более узкие coordinator/service/use-case блоки. - Тестовое покрытие архитектурных слоев все еще недостаточно: - сейчас в `app/src/test` всего 7 unit-тестов (в основном crypto/data/helpers), в `app/src/androidTest` — 1 тест; - не покрыты network runtime/coordinator слои (`RuntimeComposition`, `ConnectionEventRouter`, `ProtocolLifecycle*`, `ReadyPacketDispatchCoordinator`) и chat orchestration (`Messages/Forward/Attachments*`). Уже закрыто и больше не считается техдолгом: - `UiDependencyAccess.get(...)` удален из `ui/*`. - `UiEntryPoint`/`EntryPointAccessors` убраны из UI-экранов (явная передача зависимостей через `MainActivity`/`ViewModel`). - DI-cycle `MessageRepository -> ProtocolClient -> ProtocolRuntime -> MessageRepository` закрыт через `Provider`. - `ProtocolManager` переведен в минимальный legacy compatibility API (тонкие прокси к `ProtocolRuntimeAccess`). --- ## 12. Guardrails против переусложнения Чтобы декомпозиция не превращалась в «архитектуру ради архитектуры», применяются следующие правила: 1. Лимит глубины runtime-цепочки вызова: не более 3 логических слоев после DI-entry (`ProtocolRuntime -> Runtime*Facade -> service`; `RuntimeComposition` остается composition-root/wiring-слоем, а не обязательным proxy-hop). 2. Новый слой/класс допускается только если он дает измеримый выигрыш: - убирает минимум 80-120 строк связанной orchestration-логики из текущего класса, или - убирает минимум 2 внешние зависимости из текущего класса. 3. Каждый шаг рефакторинга считается завершенным только после: `compileDebugKotlin` + минимум одного smoke-сценария по затронутому флоу + обновления `Architecture.md`. 4. Если после выноса сложность чтения/изменения не снизилась (по факту код не стал проще), такой вынос считается кандидатом на откат/консолидацию. 5. Для event-driven runtime-chain (`ProtocolConnectionSupervisor` + `ConnectionEventRouter`) эти два элемента считаются одним orchestration-этапом при анализе hop-depth. 6. `ProtocolClientImpl` трактуется как инфраструктурный DI-adapter и учитывается отдельно от business-flow hop budget. --- ## 13. Плюсы и минусы текущей архитектуры ### 13.1 Плюсы - Четко выделены слои: UI, domain use-cases, network runtime, session/identity, data/persistence. - DI через Hilt и `ProtocolGateway`/`SessionCoordinator` снижает прямую связанность между UI и transport/runtime. - Убраны `UiEntryPoint`/`EntryPointAccessors` из UI-экранов, что улучшило явность зависимостей. - Закрыт критичный DI-cycle `MessageRepository -> ProtocolClient -> ProtocolRuntime -> MessageRepository` через `Provider`. - Network runtime декомпозирован на отдельные сервисы/coordinator-ы с более узкими зонами ответственности. - Сокращен DI runtime path: `ProtocolGateway` биндится напрямую на `ProtocolRuntime`, runtime работает напрямую с `RuntimeComposition`. - Централизован packet subscription fan-out (`PacketSubscriptionRegistry` + `PacketSubscriptionFacade`), что снижает риск дублирующих low-level подписок. - В chat-модуле выделен domain use-case слой и вынесены крупные сценарии в coordinators. ### 13.2 Минусы - `RuntimeComposition` и `ChatViewModel` остаются очень крупными hotspot-классами и концентрируют много связей. - Runtime API-слой пока широкий: много proxy-методов усложняют контроль границ и эволюцию surface API. - В части chat/media orchestration (`AttachmentsFeatureCoordinator`, `MessagesCoordinator`, `ForwardCoordinator`) сохраняются большие high-level сценарии. - Мало unit/integration тестов на архитектурно-критичные runtime/chat orchestration компоненты. - В проекте остаются несколько точек доступа к runtime (`ProtocolRuntime`, `ProtocolRuntimePort`, `ProtocolManager` legacy), что повышает cognitive load для новых разработчиков. - Стоимость входа в кодовую базу выросла: для трассировки одного бизнес-флоу нужно проходить больше слоев, чем раньше. ### 13.3 Итог оценки - Текущая архитектура стала заметно лучше по управляемости зависимостей и изоляции ответственности. - Главные риски сместились из “монолитного класса” в “размер composition/API surface и недотестированность orchestration”. - При соблюдении guardrails (секция 12) и фокусе на тестах/дальнейшей локальной декомпозиции архитектура остается управляемой и не уходит в избыточную сложность.