# Mobile Application Architecture {#mobile-application-architecture}


The **MQUAD** mobile field app is an enterprise-grade cross-platform data collection system built using Flutter and Dart. Designed for critical public health, academic research, and socioeconomic survey campaigns, the app delivers a resilient offline-first runtime supporting Android, iOS, macOS, Windows, and Linux.

---


## 1. Architectural Principles {#1-architectural-principles}


The application is architected around four core pillars:

1. **Offline Authority**: The local device holds full operational capability without needing live network access. Interviews, media capture, skip logic, and validation evaluate with zero latency.
2. **Clean Architecture Separation**: Strict boundaries between Presentation, Domain, and Data layers ensure business logic remains isolated from UI rendering and database mechanics.
3. **Multi-Tenant Iteration**: The client authenticates once with multi-tenant token support (`tenant_id: null` in base payload) and iterates across assigned forms from multiple organizations seamlessly.
4. **Defensive Encryption & Sovereignty**: Sensitive research data is protected at rest with 256-bit AES SQLCipher encryption, cryptographic verification leases, and automated paradata logging.

---


## 2. Technology Stack {#2-technology-stack}


| Layer | Technology | Version | Purpose |
|-------|------------|---------|---------|
| **Core Framework** | Flutter SDK | ^3.41.0 | Multi-platform UI engine |
| **Language** | Dart SDK | ^3.11.0 | Typed, null-safe client runtime |
| **State Management** | Riverpod | ^3.3.1 | Compile-safe dependency injection & state notifiers |
| **Local Database** | Drift + SQLCipher | ^2.33.0 | Type-safe reactive SQLite with 256-bit AES encryption |
| **Networking** | Dio | ^5.7.0 | HTTP client with multi-tenant interceptors & retry logic |
| **Routing** | GoRouter | ^17.3.0 | Declarative URL-based and deep-link routing |
| **Secure Key Storage** | FlutterSecureStorage | ^10.2.0 | Keychain (iOS/macOS) and Keystore (Android) access |
| **Offline Mapping** | Flutter Map | ^7.0.2 | Leaflet-compatible interactive map tiles with offline caching |
| **Audio & Speech** | Flutter TTS + Record | Latest | Human audio playback with system TTS fallback |

---


## 3. Layered Directory Structure {#3-layered-directory-structure}


```
mobile/lib/
├── constants/             # Global application constants and version flags
├── core/
│   ├── auth/              # Global auth interceptors and token contracts
│   ├── database/          # Drift database definitions, migrations, SQLCipher setup
│   ├── di/                # Core dependency providers
│   ├── errors/            # Typed app exceptions, failure wrappers, error mappers
│   ├── layouts/           # Responsive breakpoints, master/detail scaffolds
│   ├── network/           # Dio client setup, token refresh interceptor
│   ├── paradata/          # Sensor capture, interaction audit tracker
│   ├── router/            # GoRouter routing table and auth redirect guards
│   ├── security/          # Inactivity gates, screenshot blocker, biometric engines
│   └── theme/             # Design tokens (AppColors, AppTypography, DensityScope)
├── features/
│   ├── auth/              # Login, token refresh, biometric unlock, tenant hydration
│   ├── surveys/           # Survey catalog, version-pinning, pre-flight checks
│   ├── form/              # XLSForm runtime engine, input widgets, AST evaluator
│   ├── responses/         # Response viewing, correction mode, detail inspector
│   ├── sync/              # Background/foreground sync engine, conflict resolver
│   ├── media/             # Gallery, compression pipeline, resumable uploaders
│   └── updates/           # OTA binary updates, version compatibility checker
└── shared/
    └── widgets/           # Atomic UI library (buttons, inputs, cards, dialogs)
```

---


## 4. Feature Modularization Pattern {#4-feature-modularization-pattern}


Each business domain under `features/` adheres to Clean Architecture:

```
feature_name/
├── data/
│   ├── datasources/       # Remote API clients and local Drift DAO queries
│   ├── dtos/              # JSON serialization models (Freezed / json_serializable)
│   └── repositories/      # Repository implementations coordinating local & remote
├── domain/
│   ├── entities/          # Pure immutable business models
│   ├── repositories/      # Abstract repository interface contracts
│   └── usecases/          # Self-contained business operations
└── presentation/
    ├── providers/         # Riverpod Notifiers and StateNotifier providers
    ├── screens/           # Full-screen page widgets
    └── widgets/           # Feature-specific atomic components
```

---


## 5. Multi-Tenancy Resolution in Mobile {#5-multi-tenancy-resolution-in-mobile}


Unlike standard web applications where a user switches tenants via an active session selector, MQUAD mobile enumerators must see surveys across **all authorized tenants** simultaneously.


### Multi-Tenant Token Flow {#multi-tenant-token-flow}
1. **Login (`/account/login_new`)**: Returns a primary access token with `tenant_id: null` and an array of authorized tenant IDs: `tenant_ids: ["tenant-a-uuid", "tenant-b-uuid"]`.
2. **Dynamic Context Scoping**: When requesting data for a specific survey, the repository wraps the call with `TenantRequestContext.runWithTenant(tenantId, ...)`.
3. **Header Injection**: The `AuthInterceptor` reads the active request context and dynamically injects the required header:
   ```http
   GET /surveys HTTP/1.1
   Host: api.mquad.local
   Authorization: Bearer <multi_tenant_jwt>
   X-Tenant-ID: b94d513e-7993-4ecf-bd47-a2f6041623bb
   ```
4. **Microservice Validation**: The backend services verify that `tenant_id` is either `None` (multi-tenant token) or matches `X-Tenant-ID`, and confirms that the requested tenant is present in the token's `tenant_ids` claim.

---


## 6. Reactive State Architecture {#6-reactive-state-architecture}






```mermaid
graph TD
    UI[Flutter UI Widgets] -->|Watch / Select| Notifier[Riverpod StateNotifier]
    Notifier -->|Execute| UC[Domain UseCase]
    UC -->|Query / Mutate| Repo[Repository Implementation]
    Repo -->|Cached First| LocalDS[Local DataSource - Drift/SQLCipher]
    Repo -->|Sync / Network| RemoteDS[Remote DataSource - Dio]
    LocalDS -->|Streams| Notifier
    Notifier -->|Rebuilds with new state| UI
```





All screens observe state via Riverpod providers. Changes made in the local database trigger reactive Drift streams (`select().watch()`), updating the UI in real time without manual polling.
