# 02. YAKKI SMART v2.3 PROJECT ARCHITECTURE
**Created:** November 30, 2025
**Last Updated:** December 5, 2025
**Version:** 2.3 (Production Beta)
**Status:** Active Development
**v2.3 Changes:** Table formatting conversion (Markdown → stable ASCII format)
---
## 🏗️ Architectural Overview
YAKKI SMART is built on **three key architectural patterns**:
1. **Clean Architecture** (Uncle Bob) - separation into layers with clear boundaries
2. **MVI (Model-View-Intent)** - unidirectional data flow in UI
3. **Scenario-based Architecture** - domain logic organized by business scenarios
### Conceptual Diagram
```
┌─────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Compose │ │ViewModel │ │ MVI │ │ UiState │ │
│ │ UI │◄─┤ │◄─┤ Intent │◄─┤ Mapper │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└────────────────────────┬────────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────────┐
│ DOMAIN LAYER │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Use Cases │ │ Domain │ │ Domain │ │
│ │ (Scenarios) │ │ Models │ │ Errors │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ SCENARIO ORCHESTRATION │ │
│ │ Translator │ Document │ Conference │ Life Coach │ │
│ └────────────────────────────────────────────────────┘ │
└────────────────────────┬────────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────────┐
│ DATA LAYER │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Repositories │ │ Data Sources │ │ Mappers │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ EXTERNAL SERVICES │ │
│ │ STT │ TTS │ Translation │ LLM │ RAG │ Database │ │
│ └────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
```
---
## 📦 Modular Structure (32 modules)
### Module Grouping by Purpose
```
YAKKI SMART v2.2 (32 modules)
│
├── 📱 CORE APPLICATION (1 module)
│ └── :app - Main application, Hilt DI, scenarios, UI
│
├── 🧠 INTELLIGENCE & ROUTING (2 modules)
│ ├── :conductor - Adaptive routing, Circuit Breaker, voice commands
│ └── :llmorchestrator - LLM orchestration layer
│
├── 💾 RAG SYSTEM - SmartRAG v3 (15 modules)
│ ├── :smartrag3:core - ObjectBox 5.0.1, HNSW indexing
│ ├── :smartrag3:common - SmartRAGResult wrappers
│ ├── :smartrag3:domain - Use cases
│ ├── :smartrag3:di - Koin DI modules
│ ├── :smartrag3:data - RAGRepositoryImpl, compression, quantization
│ ├── :smartrag3:embeddings - ONNX Runtime, EmbeddingGemma 300M
│ ├── :smartrag3:language - CLD3 language detection
│ ├── :smartrag3:parsing - Text parsing, chunking
│ ├── :smartrag3:ingestion - ML Kit Scanner, OCR
│ ├── :smartrag3:entities - Persona entities
│ ├── :smartrag3:datasources - SMS/Contacts adapters
│ ├── :smartrag3:ner - Named Entity Recognition
│ ├── :smartrag3:security - Keystore, credentials
│ ├── :smartrag3:search - Search infrastructure
│ └── :smartrag3:summarization - Text summarization
│
├── 📄 DOCUMENT PROCESSING (3 modules)
│ ├── :docparser:core - Parser interfaces (~50KB)
│ ├── :docparser:pdf - PDF parser (Dynamic Feature, ~5-10MB)
│ └── :docparser:office - Office parser (Dynamic Feature, ~15-20MB)
│
├── 📧 EMAIL CLIENT (3+ modules)
│ ├── :yakki-mail:core:models - Email, Account, Folder
│ ├── :yakki-mail:core:protocol - IMAP/SMTP clients
│ ├── :yakki-mail:core:security - MailCredentialManager
│ └── :yakki-mail:ui - UI components (NOT IMPLEMENTED)
│
├── 📡 BLUETOOTH (2 modules)
│ ├── :yakkibluetooth:core - Bluetooth LE core
│ └── :yakkibluetooth:leaudio - LE Audio support (PARTIAL)
│
├── 🛠️ UTILITIES (5 modules)
│ ├── :latency - HTTP latency measurement
│ ├── :archivelib - ZIP unarchiving
│ ├── :smartrag-v2 - Legacy RAG (DEPRECATED)
│ └── (others)
```
---
## 🎨 Clean Architecture - Detailed
### Layer 1: Presentation (UI + ViewModels)
**Responsibility:** Display data and handle user interactions
**Technologies:**
- Jetpack Compose (100% declarative UI)
- Material 3 Design System
- Compose Navigation
- StateFlow for state management
**Pattern: MVI (Model-View-Intent)**
```kotlin
// Intent - user intention
sealed class TranslatorIntent {
data class StartListening(val language: Language) : TranslatorIntent()
data class TranslateText(val text: String) : TranslatorIntent()
object StopListening : TranslatorIntent()
}
// State - UI state
data class TranslatorUiState(
val isListening: Boolean = false,
val partialTranscription: String = "",
val quickTranslation: String = "",
val refinedTranslation: String = "",
val error: ErrorUiState? = null,
val isLoading: Boolean = false
)
// View - Composable function
@Composable
fun TranslatorScreen(
state: TranslatorUiState,
onIntent: (TranslatorIntent) -> Unit
) {
// Declarative UI based on state
}
// ViewModel - handles intents, updates state
class TranslatorViewModel @Inject constructor(
private val translateUseCase: TranslateUseCase
) : ViewModel() {
private val _state = MutableStateFlow(TranslatorUiState())
val state: StateFlow<TranslatorUiState> = _state.asStateFlow()
fun handleIntent(intent: TranslatorIntent) {
when (intent) {
is TranslatorIntent.StartListening -> startListening(intent.language)
is TranslatorIntent.TranslateText -> translate(intent.text)
is TranslatorIntent.StopListening -> stopListening()
}
}
}
```
**MVI Advantages:**
- Unidirectional data flow (easy to trace bugs)
- Immutable state (predictability)
- Time-travel debugging (can reproduce states)
- Easy to test (pure functions)
### Layer 2: Domain (Use Cases + Models)
**Responsibility:** Business logic of the application, independent of UI and data sources
**Structure:**
```kotlin
// Domain Model - pure business entity
data class Translation(
val originalText: String,
val translatedText: String,
val sourceLanguage: Language,
val targetLanguage: Language,
val confidence: Float,
val model: String,
val timestamp: Instant
)
// Use Case - business operation
class TranslateTextUseCase @Inject constructor(
private val translationRepository: TranslationRepository,
private val qualityChecker: QualityChecker
) {
suspend operator fun invoke(
text: String,
sourceLanguage: Language,
targetLanguage: Language
): DomainResult<Translation> {
// 1. Validate input
if (text.isBlank()) {
return DomainResult.Error(DomainError.ValidationError("Text is empty"))
}
// 2. Translate
val result = translationRepository.translate(text, sourceLanguage, targetLanguage)
// 3. Check quality
return result.map { translation ->
val quality = qualityChecker.assess(translation)
translation.copy(confidence = quality.score)
}
}
}
// Repository Interface - abstraction for data layer
interface TranslationRepository {
suspend fun translate(
text: String,
sourceLanguage: Language,
targetLanguage: Language
): DomainResult<Translation>
}
```
**Key Domain Layer Principles:**
1. **Framework independence** - pure Kotlin, no Android APIs
2. **UI independence** - domain models != UI models
3. **DB independence** - domain models != database entities
4. **Testability** - all use cases covered by unit tests
5. **Single Responsibility** - one use case = one business operation
### Layer 3: Data (Repositories + Data Sources)
**Responsibility:** Fetch and save data from various sources
**Structure:**
```kotlin
// Repository Implementation
class TranslationRepositoryImpl @Inject constructor(
private val deepInfraService: DeepInfraTranslationService,
private val geminiService: GeminiTranslationService,
private val localCache: TranslationCacheDataSource,
private val mapper: TranslationMapper
) : TranslationRepository {
override suspend fun translate(
text: String,
sourceLanguage: Language,
targetLanguage: Language
): DomainResult<Translation> = withContext(Dispatchers.IO) {
// 1. Check cache
val cached = localCache.get(text, sourceLanguage, targetLanguage)
if (cached != null) {
return@withContext DomainResult.Success(mapper.toDomain(cached))
}
// 2. Try primary provider (DeepInfra)
val result = deepInfraService.translate(text, sourceLanguage, targetLanguage)
// 3. Fallback to Gemini if DeepInfra fails
return@withContext result.flatMapError { error ->
Log.w(TAG, "DeepInfra failed: $error, falling back to Gemini")
geminiService.translate(text, sourceLanguage, targetLanguage)
}.map { dto ->
// 4. Cache result
localCache.save(dto)
// 5. Map to domain
mapper.toDomain(dto)
}
}
}
// Data Source - concrete implementation for external API
class DeepInfraTranslationService @Inject constructor(
private val api: DeepInfraApi,
private val config: DeepInfraConfig
) {
suspend fun translate(
text: String,
sourceLanguage: Language,
targetLanguage: Language
): DomainResult<TranslationDto> {
return try {
val request = buildRequest(text, sourceLanguage, targetLanguage)
val response = api.translate(request)
DomainResult.Success(response.toDto())
} catch (e: Exception) {
DomainResult.Error(mapException(e))
}
}
}
```
**Data Layer Patterns:**
1. **Repository pattern** - single point of access to data
2. **Data Source pattern** - encapsulation of concrete source
3. **Mapper pattern** - DTO ↔ Domain models transformation
4. **Cache-aside pattern** - cache checked before network request
5. **Circuit Breaker** - protection from cascading failures
---
## 🎭 Scenario-based Architecture
### Concept
Instead of monolithic architecture, business logic is organized by **usage scenarios**.
Each scenario is a self-contained module with:
- Its own UI (Composable screens)
- Its own ViewModel
- Its own Use Cases
- Its own Domain Models
### Scenario Structure
```
📁 presentation/scenarios/translator/
├── 📄 TranslatorScenario.kt // Main Composable
├── 📄 TranslatorViewModel.kt // State management
├── 📄 TranslatorUiState.kt // UI state definition
├── 📁 ui/components/
│ ├── StreamingSTTView.kt // STT component
│ ├── ModelBadge.kt // Model badge
│ ├── TTSReplayButton.kt // TTS replay button
│ └── ErrorView.kt // Error display
└── 📁 navigation/
└── TranslatorRoutes.kt // Navigation graph
```
### Implemented Scenarios (4/12)
**1. Translator Scenario** (95% readiness)
- Real-time voice translation
- Streaming STT → Translation → TTS pipeline
- Adaptive quality control
- Cost optimization
**2. Document Analyzer Scenario** (100% readiness)
- 8 document types (Contract, Invoice, Email, etc.)
- AI-based structured data extraction
- Integration with SmartRAG v3
**3. Chat with RAG Scenario** (70% readiness)
- Chat UI with Material 3
- Context-aware responses (SmartRAG)
- Message history
**4. SMS Integration Scenario** (100% readiness)
- Send/receive SMS
- Persona linking
- Message templates
### Planned Scenarios (8)
**5. Multilingual Conference** (spec ready)
- QR-code connection
- 50+ participants support
- Real-time sync
**6. Meeting Summary** (spec ready)
- Audio recording
- AI transcription
- Action items extraction
**7. Lecture Notes** (spec ready)
- Structured note-taking
- Quiz generation
- Export to Markdown/PDF
**8. Tour Guide** (spec ready)
- Multi-language tours
- Group sync
- Offline mode
**9-12. Life Coach, YouTube, Email Analysis, etc.** (concepts)
---
## 🔧 Dependency Injection
### Hybrid Strategy: Hilt + Koin
**Why hybrid?**
- **Hilt** - for :app module (Android-specific, ViewModels)
- **Koin** - for library modules (SmartRAG v3, no Android dependencies)
### Hilt DI (:app module)
```kotlin
// Application class
@HiltAndroidApp
class YakkiApplication : Application() {
override fun onCreate() {
super.onCreate()
// Initialize Koin for SmartRAG
startKoin {
androidContext(this@YakkiApplication)
modules(smartRAGModules)
}
// Initialize ObjectBox
ObjectBoxStore.init(this)
}
}
// Module definition
@Module
@InstallIn(SingletonComponent::class)
object ServiceModule {
@Provides
@Singleton
fun provideDeepInfraService(
api: DeepInfraApi,
config: DeepInfraConfig
): DeepInfraTranslationService {
return DeepInfraTranslationService(api, config)
}
@Provides
@Singleton
fun provideTranslationRepository(
deepInfra: DeepInfraTranslationService,
gemini: GeminiTranslationService,
cache: TranslationCacheDataSource
): TranslationRepository {
return TranslationRepositoryImpl(deepInfra, gemini, cache)
}
}
// ViewModel injection
@HiltViewModel
class TranslatorViewModel @Inject constructor(
private val translateUseCase: TranslateTextUseCase,
private val sttService: STTService,
private val ttsService: TTSService
) : ViewModel() {
// ...
}
```
### Koin DI (SmartRAG v3)
```kotlin
// Module definition
val storageModule = module {
// Singletons
single { ObjectBoxStore }
singleOf(::RAGRepositoryImpl)
// With bindings
singleOf(::ZstdCompressionProvider) { bind<ICompressionProvider>() }
// Factory
factory { (context: Context) ->
RAGIndexManager(context, get())
}
}
val smartRAGModules = listOf(
storageModule,
embeddingsModule,
parsingModule,
// ... other modules
)
// Usage in :app
class MyService @Inject constructor() {
private val ragRepository: RAGRepository by inject() // Koin
}
```
**Hybrid Approach Advantages:**
- Hilt for compile-time safety in app
- Koin for flexibility in library modules
- Clear separation: app concerns vs library concerns
---
## ❌ Centralized Error Handling
### DomainError - 24 error types
```kotlin
sealed class DomainError {
abstract val message: String
abstract val recoverable: Boolean
abstract val technicalDetails: String?
// Permission & Hardware (2 types)
data class PermissionDenied(
override val message: String,
val permissionName: String,
override val recoverable: Boolean = true,
override val technicalDetails: String? = null
) : DomainError()
data class MicrophoneError(
override val message: String,
val errorCode: Int? = null,
override val recoverable: Boolean = true,
override val technicalDetails: String? = null
) : DomainError()
// Speech Services (2 types)
data class SpeechRecognitionError(...) : DomainError()
data class SpeechSynthesisError(...) : DomainError()
// Translation (1 type)
data class TranslationError(...) : DomainError()
// Network & API (3 types)
data class NetworkError(
override val message: String,
val errorType: NetworkErrorType, // NO_INTERNET, TIMEOUT, DNS_FAILURE, etc.
override val recoverable: Boolean = true,
override val technicalDetails: String? = null
) : DomainError()
data class ApiError(...) : DomainError()
data class TimeoutError(...) : DomainError()
// Configuration & State (2 types)
data class ConfigurationError(...) : DomainError()
data class InvalidStateError(...) : DomainError()
// File & Parsing (3 types)
data class ParseError(...) : DomainError()
data class FileNotFoundError(...) : DomainError()
data class UnsupportedFormatError(...) : DomainError()
// Validation & Data (4 types)
data class ValidationError(...) : DomainError()
data class DatabaseError(...) : DomainError()
data class NotFoundError(...) : DomainError()
data class EmbeddingError(...) : DomainError()
// Pipeline-specific (7 types) - NEW in v2.2
data class RateLimitError(...) : DomainError()
data class ProviderUnavailableError(...) : DomainError()
data class CircuitBreakerError(...) : DomainError()
data class SubscriptionError(...) : DomainError()
data class SignatureError(...) : DomainError()
data class ServerError(...) : DomainError()
data class PipelineError(...) : DomainError()
// Fallback (1 type)
data class UnknownError(...) : DomainError()
}
```
### DomainResult - Type-safe error handling
```kotlin
sealed class DomainResult<out T> {
data class Success<T>(val value: T) : DomainResult<T>()
data class Error(val error: DomainError) : DomainResult<Nothing>()
// Utility functions
fun <R> map(transform: (T) -> R): DomainResult<R>
fun <R> flatMap(transform: (T) -> DomainResult<R>): DomainResult<R>
fun flatMapError(transform: (DomainError) -> DomainResult<T>): DomainResult<T>
fun getOrNull(): T?
fun getOrElse(default: T): T
fun fold(onSuccess: (T) -> Unit, onError: (DomainError) -> Unit)
}
```
### Usage
```kotlin
// In Use Case
suspend fun translateText(text: String): DomainResult<Translation> {
return repository.translate(text)
.flatMapError { error ->
// Retry logic
when (error) {
is DomainError.NetworkError -> retryWithBackoff { repository.translate(text) }
else -> DomainResult.Error(error)
}
}
.map { translation ->
// Post-processing
translation.copy(timestamp = Clock.System.now())
}
}
// In ViewModel
viewModelScope.launch {
translateUseCase(text).fold(
onSuccess = { translation ->
_state.update { it.copy(translation = translation, isLoading = false) }
},
onError = { error ->
val uiError = ErrorHandler.handleError(error)
_state.update { it.copy(error = uiError, isLoading = false) }
}
)
}
// In UI
when (state.error) {
is ErrorUiState -> {
ErrorView(
message = state.error.message,
action = state.error.action, // RETRY, OPEN_SETTINGS, DISMISS, etc.
onActionClick = { handleErrorAction(state.error.action) }
)
}
}
```
**Advantages:**
- Type-safe (compiler enforces error handling)
- Exhaustive when (cannot forget to handle error type)
- Functional style (map, flatMap, fold)
- Single point of error logging
---
## 🌍 Localization (UiString System)
### Problem
Traditional localization approach in Android:
```kotlin
// ❌ Hardcoded strings
Text("Send")
// ❌ String resources (not type-safe, easy to make mistake in key)
Text(stringResource(R.string.send_button)) // what if key doesn't exist?
```
### Solution: Type-safe UiString
```kotlin
// Defining sealed interface
sealed interface UiString : LocalizationKey {
// Categories
sealed interface Common : UiString {
data object Send : Common {
override val key = "common.send"
override val params = emptyMap<String, Any>()
}
data object Cancel : Common {
override val key = "common.cancel"
override val params = emptyMap<String, Any>()
}
}
sealed interface Chat : UiString {
data object SendButton : Chat {
override val key = "chat.sendButton"
override val params = emptyMap<String, Any>()
}
// Parametrized strings
data class CostPerMillion(val cost: Double) : Chat {
override val key = "chat.model.costPerMillion"
override val params = mapOf("cost" to cost)
}
}
sealed interface Settings : UiString { ... }
sealed interface Models : UiString { ... }
}
// LocalizationProvider
class LocalizationProvider(private val currentLanguage: Language) {
private val translations = mapOf(
"common.send" to mapOf(
Language.EN to "Send",
Language.RU to "Отправить",
Language.ES to "Enviar",
Language.ZH to "发送"
),
"chat.model.costPerMillion" to mapOf(
Language.EN to "\${cost} per 1M tokens",
Language.RU to "\${cost} за 1М токенов",
// ...
)
)
fun localize(key: LocalizationKey): String {
val template = translations[key.key]?.get(currentLanguage)
?: key.key // fallback to key
// Replace parameters
return key.params.entries.fold(template) { acc, (k, v) ->
acc.replace("\${$k}", v.toString())
}
}
}
// Composable helper
@Composable
fun localize(uiString: UiString): String {
val provider = LocalLocalizationProvider.current
return provider.localize(uiString)
}
// Usage in UI
Text(localize(UiString.Common.Send)) // Type-safe!
Text(localize(UiString.Chat.CostPerMillion(1.09))) // With parameters!
```
**Advantages:**
1. **Type-safe** - compiler checks key existence
2. **Refactor-friendly** - Rename works across project
3. **Autocomplete** - IDE suggests available strings
4. **Parameterization** - safe parameter substitution
5. **Centralized** - all strings in one place
### Dynamic Language Addition
```kotlin
// AI-powered translation
class DynamicLanguageAdder(
private val geminiApi: GeminiApi,
private val repository: LocalizationRepository
) {
suspend fun addLanguage(targetLanguage: Language) {
val allKeys = UiString::class.sealedSubclasses
.flatMap { it.sealedSubclasses }
.map { it.objectInstance as UiString }
val translations = allKeys.map { uiString ->
val englishText = localize(uiString, Language.EN)
val translatedText = geminiApi.translate(englishText, Language.EN, targetLanguage)
uiString.key to translatedText
}.toMap()
repository.saveTranslations(targetLanguage, translations)
}
}
```
---
## 🔌 Technology Stack
### Frontend (UI)
```
Jetpack Compose 1.7.5
└─ Declarative UI framework, Material 3 Design System
Material 3 1.3.1
└─ Design system components and theming
Compose Navigation 2.8.5
└─ Type-safe navigation between screens
Accompanist 0.36.0
└─ Permissions handling, system UI controller
Coil 2.7.0
└─ Image loading and caching library
```
### Backend (Business Logic)
```
Kotlin 2.2.20
└─ Primary programming language
Coroutines 1.10.1
└─ Asynchronous programming, structured concurrency
Flow 1.10.1
└─ Reactive streams for data flow
Hilt 2.57.2
└─ Dependency injection for :app module (compile-time safe)
Koin 4.0.0
└─ Dependency injection for library modules (SmartRAG v3)
```
### Data & Storage
```
ObjectBox 5.0.1
└─ NoSQL database, HNSW vector indexing, persistent RAG
Room 2.8.2
└─ SQL database for structured data (fallback/cache)
DataStore 1.1.1
└─ Key-value storage for settings and preferences
ONNX Runtime 1.20.0
└─ On-device ML inference for embeddings generation
```
### AI & ML
```
Gemini SDK 0.9.0
└─ Google AI integration (Conductor, fallback translation)
LangChain4j 0.35.0
└─ LLM orchestration and chain management
ML Kit (Latest)
└─ Document scanner, OCR, text recognition
CLD3 (Latest)
└─ Compact Language Detector for 107 languages
```
### Document Processing
```
PDFBox Android 2.0.27.0
└─ PDF parsing and text extraction
Apache POI 5.2.5
└─ Microsoft Office formats (DOCX, XLSX, PPTX)
JSoup 1.18.1
└─ HTML parsing and DOM manipulation
```
### Networking
```
OkHttp 4.12.0
└─ HTTP client with connection pooling and caching
Retrofit 2.11.0
└─ REST API client with type-safe endpoints
Ktor Client 3.0.2
└─ Async HTTP client (alternative for streaming)
```
### Testing
```
JUnit 5 5.11.4
└─ Unit testing framework with modern assertions
Mockk 1.13.13
└─ Mocking library for Kotlin (idiomatic DSL)
Turbine 1.2.0
└─ Flow testing library for async streams
MockWebServer 4.12.0
└─ HTTP mocking for API testing
Compose Test 1.7.5
└─ UI testing framework for Jetpack Compose
```
### Build System
```
Gradle 8.13
└─ Build automation tool with Kotlin DSL
AGP 8.13.0
└─ Android Gradle Plugin for Android builds
KSP 2.2.20-2.0.3
└─ Kotlin Symbol Processing (replaces KAPT)
Version Catalog
└─ Centralized dependency management (libs.versions.toml)
```
---
## 📐 Architectural Patterns
### 1. Repository Pattern
**Goal:** Abstract data sources from business logic
**Implementation:**
```kotlin
interface TranslationRepository {
suspend fun translate(text: String, from: Language, to: Language): DomainResult<Translation>
}
class TranslationRepositoryImpl(
private val remoteSource: TranslationRemoteDataSource,
private val localSource: TranslationLocalDataSource
) : TranslationRepository {
override suspend fun translate(...): DomainResult<Translation> {
// Check cache → call API → save to cache
}
}
```
### 2. Factory Pattern
**Goal:** Create objects with complex initialization
**Implementation:**
```kotlin
class DocumentParserFactory {
fun createParser(mimeType: String): IDocumentParser? {
return when (mimeType) {
"application/pdf" -> PdfDocumentParser()
"application/vnd.openxmlformats-officedocument.wordprocessingml.document" -> DocxDocumentParser()
else -> null
}
}
}
```
### 3. Strategy Pattern
**Goal:** Select algorithm at runtime
**Implementation:**
```kotlin
// Document Analyzer uses different strategies for different types
interface DocumentTemplate {
fun getPrompt(): String
fun parseResponse(json: String): DocumentAnalysis
}
class ContractTemplate : DocumentTemplate { ... }
class InvoiceTemplate : DocumentTemplate { ... }
class EmailTemplate : DocumentTemplate { ... }
class DocumentAnalyzerService(templates: Map<DocumentType, DocumentTemplate>) {
fun analyze(document: Document, type: DocumentType): DocumentAnalysis {
val template = templates[type]!!
val prompt = template.getPrompt()
val response = gemini.generateContent(prompt + document.text)
return template.parseResponse(response)
}
}
```
### 4. Observer Pattern (Flow)
**Goal:** Reactive updates
**Implementation:**
```kotlin
class TranslatorViewModel {
private val _state = MutableStateFlow(TranslatorUiState())
val state: StateFlow<TranslatorUiState> = _state.asStateFlow()
init {
sttService.transcription
.onEach { partial ->
_state.update { it.copy(partialTranscription = partial) }
}
.launchIn(viewModelScope)
}
}
```
### 5. Chain of Responsibility (Error Handling)
**Goal:** Error handling through chain of handlers
**Implementation:**
```kotlin
fun translateWithFallback(text: String): DomainResult<Translation> {
return deepInfraService.translate(text)
.flatMapError { error1 ->
Log.w(TAG, "DeepInfra failed: $error1, trying Gemini")
geminiService.translate(text)
}
.flatMapError { error2 ->
Log.w(TAG, "Gemini failed: $error2, trying cache")
cacheService.getLastTranslation(text)
}
}
```
### 6. Circuit Breaker Pattern
**Goal:** Protection from cascading failures
**Implementation:**
```kotlin
class CircuitBreaker(
private val failureThreshold: Int = 5,
private val recoveryTimeout: Duration = 60.seconds
) {
private var failureCount = 0
private var state: State = State.CLOSED
private var lastFailureTime: Instant? = null
suspend fun <T> execute(block: suspend () -> T): T {
when (state) {
State.OPEN -> {
if (shouldAttemptRecovery()) {
state = State.HALF_OPEN
} else {
throw CircuitBreakerOpenException()
}
}
State.HALF_OPEN -> {
// Try one request
}
State.CLOSED -> {
// Normal operation
}
}
return try {
val result = block()
onSuccess()
result
} catch (e: Exception) {
onFailure()
throw e
}
}
}
```
### 7. Adapter Pattern (Service Integration)
**Goal:** Adapt external APIs to internal interfaces
**Implementation:**
```kotlin
// Internal interface
interface STTService {
fun startListening(language: Language): Flow<String>
fun stopListening()
}
// External service (Android SpeechRecognizer)
class DeviceSTTService(private val recognizer: SpeechRecognizer) : STTService {
override fun startListening(language: Language): Flow<String> = callbackFlow {
recognizer.setRecognitionListener(object : RecognitionListener {
override fun onPartialResults(bundle: Bundle) {
val text = bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)?.get(0)
trySend(text ?: "")
}
})
recognizer.startListening(createIntent(language))
awaitClose { recognizer.stopListening() }
}
}
```
---
## 🏛️ Layered Architecture
### Responsibility Separation by Layers
```
┌────────────────────────────────────────────────────────┐
│ LAYER 1: PRESENTATION (UI + ViewModels) │
│ │
│ Responsibilities: │
│ - Display data │
│ - Handle user input │
│ - Navigation │
│ - UI state management │
│ │
│ Dependencies: Domain layer │
│ Does not know about: Data sources, APIs, databases │
└────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────┐
│ LAYER 2: DOMAIN (Use Cases + Models) │
│ │
│ Responsibilities: │
│ - Business logic │
│ - Domain models │
│ - Repository interfaces │
│ - Business rules validation │
│ │
│ Dependencies: NONE (pure Kotlin) │
│ Does not know about: UI, databases, APIs, Android SDK│
└────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────┐
│ LAYER 3: DATA (Repositories + Data Sources) │
│ │
│ Responsibilities: │
│ - Repository implementations │
│ - API calls │
│ - Database operations │
│ - Caching │
│ - Data mapping (DTO ↔ Domain) │
│ │
│ Dependencies: Domain layer (repository interfaces) │
│ Does not know about: UI, ViewModels │
└────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────┐
│ LAYER 4: EXTERNAL (APIs, SDK, Hardware) │
│ │
│ - REST APIs (DeepInfra, Gemini, etc.) │
│ - Android SDK (SpeechRecognizer, TTS) │
│ - Third-party SDKs (ObjectBox, ONNX) │
│ - Hardware (microphone, speakers) │
└────────────────────────────────────────────────────────┘
```
### Dependency Flow Rules
1. **Dependency Rule:** Dependencies point INWARD
- Presentation → Domain → Data → External ✅
- Data → Presentation ❌ VIOLATION
2. **Abstractions Rule:** Inner layers define interfaces, outer layers implement them
- Domain layer: `interface TranslationRepository`
- Data layer: `class TranslationRepositoryImpl : TranslationRepository`
3. **Data Flow Rule:** Data passes through layer boundaries via DTO/mappers
- API DTO → Domain Model (mapper)
- Domain Model → UI Model (mapper)
---
## 🔒 Security Architecture
### Security Principles
1. **Least Privilege** - minimum necessary permissions
2. **Defense in Depth** - multiple layers of security
3. **Fail Secure** - safe state on error
4. **Privacy by Design** - user data on device
### Implemented Measures
**1. API Keys Protection**
```kotlin
// ✅ GOOD: BuildConfig (generated, not in git)
val apiKey = BuildConfig.DEEPINFRA_API_KEY
// ❌ BAD: Hardcoded (CRITICAL vulnerability found!)
val apiKey = "hf_xxx..." // Found in QualityAssessmentService.kt!
```
**2. Encrypted Storage (Android Keystore)**
```kotlin
class MailCredentialManager(private val keystore: KeystoreManager) {
fun savePassword(email: String, password: String) {
val encrypted = keystore.encrypt(password)
preferences.putString("pwd_$email", encrypted)
}
}
```
**3. Voice Command Security (Round 5)**
- Fuzzy logic for command recognition
- CAPTCHA challenge for suspicious actions
- Confirmation dialog for critical operations
**4. Network Security**
```xml
<!-- network_security_config.xml -->
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
```
**5. On-device RAG**
- Data doesn't leave device
- Embeddings generated locally (ONNX)
- Backup encrypted with user passphrase
### Security Checklist (current state)
- [x] Network security config
- [x] Encrypted preferences (EncryptedSharedPreferences)
- [x] Android Keystore integration
- [x] HTTPS only (cleartextTrafficPermitted=false)
- [ ] **ProGuard/R8 obfuscation** - NOT configured
- [ ] **Certificate pinning** - NOT implemented
- [ ] **Root detection** - NOT implemented
- [ ] **Biometric auth** - Partial (for email credentials)
---
## 🚀 Performance Architecture
### Optimizations
**1. Lazy Loading (Dynamic Features)**
```kotlin
// PDF parser loaded only when needed
val pdfParser = SplitInstallManagerFactory
.create(context)
.loadModule("docparser_pdf")
```
**2. Caching Strategy**
- **Memory cache:** LRU cache for embeddings (size: 100MB)
- **Disk cache:** ObjectBox for translations (TTL: 30 days)
- **Network cache:** OkHttp cache (size: 50MB)
**3. Background Processing**
```kotlin
// WorkManager for heavy operations
class PersonaSyncWorker : CoroutineWorker() {
override suspend fun doWork(): Result {
// Sync SMS, emails in background
}
}
```
**4. Pagination**
```kotlin
// Paging 3 for large lists
val messages = Pager(
config = PagingConfig(pageSize = 20),
pagingSourceFactory = { MessagePagingSource(db) }
).flow
```
**5. Compression**
- ZSTD for large texts (ratio: 3-5x)
- Int8 quantization for embeddings (ratio: 4x)
### Performance Metrics (target)
```
PERFORMANCE BENCHMARKS:
App startup (cold start)
├─ Target: <2s
└─ Current: ~1.5s ✅ MEETING TARGET
Translation latency (end-to-end)
├─ Target: <900ms
└─ Current: ~600ms ✅ EXCEEDS TARGET
UI frame drops (jank rate)
├─ Target: <1%
└─ Current: ~0.5% ✅ EXCELLENT
Memory usage (runtime)
├─ Target: <150MB
└─ Current: ~120MB ✅ EFFICIENT
APK size (base APK)
├─ Target: <20MB
└─ Current: ~18MB ✅ OPTIMIZED
```
---
## 📊 Scalability Architecture
### Horizontal Scaling (Multi-instance)
**Problem:** Conference scenario with 50+ participants
**Solution:** WebSocket broadcasting
```kotlin
class ConferenceHost(private val webSocketServer: WebSocketServer) {
suspend fun broadcast(transcription: String) {
participants.forEach { participant ->
webSocketServer.send(participant.id, transcription)
}
}
}
```
### Vertical Scaling (Performance)
**Problem:** Processing 100+ translations/min
**Solution:** Coroutine pools + flow batching
```kotlin
val translationFlow = translationRequests
.buffer(capacity = 100) // Buffering
.chunked(10, 500.milliseconds) // Batching
.flatMapMerge(concurrency = 5) { batch ->
flow { emit(translateBatch(batch)) }
}
```
---
## 🎯 Architecture Conclusions
### Strengths
1. **Clean Architecture** - clear separation of concerns
2. **Type-safe error handling** - DomainError + DomainResult
3. **Scenario-based** - easy to add new features
4. **Modular** - 32 modules, low coupling
5. **Testable** - domain layer 100% test coverage (target)
6. **Flexible DI** - Hilt + Koin for different needs
### Areas for Improvement
1. **Testing** - coverage ~60%, target 80%
2. **Documentation** - some modules without .md files
3. **Security** - need ProGuard, certificate pinning
4. **Performance** - profiling for bottlenecks
---
**Navigation:**
- [← Back: Project Overview](01_PROJECT_OVERVIEW.md)
- [Next: Modules and Components →](03_MODULES_AND_COMPONENTS.md)
- [↑ To Contents](README.md)