Backend, sync, infra, docs: ETag, API versioning, k8s, web scaffold, Android 16, domain stubs

- Backend: ShallowEtagHeaderFilter for /api/v1/*, API-VERSIONING.md, README (tenant, CORS, Flyway, ETag)
- k8s: backend-deployment.yaml (Deployment, Service, Secret/ConfigMap)
- Web: scaffold with directory pull, 304 handling, touch-friendly UI
- Android 16: ANDROID-16-TARGET.md; BuildConfig STUN/signaling, SMOAApplication configures InfrastructureManager
- Domain: CertificateManager revocation stub, ReportService signReports, ZeroTrust/ThreatDetection minimal docs
- TODO.md and IMPLEMENTATION_STATUS.md updated; communications README for endpoint config

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
defiQUG
2026-02-10 20:37:01 -08:00
parent 97f75e144f
commit 5a8c26cf5d
101 changed files with 4923 additions and 103 deletions

View File

@@ -0,0 +1,10 @@
# Android 16 target (compileSdk / targetSdk 36)
- **Android 16** uses **API level 36**. The app currently uses **compileSdk 34** and **targetSdk 34** and runs on Android 16 via compatibility behavior.
- **To fully target Android 16** (opt into new behavior and APIs):
1. Upgrade **Android Gradle Plugin** to **8.5 or 8.6+** (supports compileSdk 35/36). Update root `build.gradle.kts`: e.g. `id("com.android.application") version "8.6.0"`.
2. In **buildSrc/.../AppConfig.kt**, set `compileSdk = 36` and `targetSdk = 36`.
3. Sync and fix any deprecations or API changes.
4. Test on a device or emulator with Android 16 (API 36).
Until then, **minSdk 24** and **targetSdk 34** remain; the app is forward compatible on Android 16.

View File

@@ -0,0 +1,110 @@
# Device compatibility Samsung Galaxy Z Fold5 (primary target)
This document describes SMOA compatibility with the **Samsung Galaxy Z Fold5** (model **SM-F946U1**) as the primary target device, and what has been done to ensure the app works correctly on it.
---
## Required target (mandatory minimum)
| Aspect | Required minimum |
|--------|-------------------|
| **Device** | Samsung Galaxy Z Fold5 (SM-F946U1) or equivalent (foldable, 4G/5G capable). |
| **OS** | Android 10 (API 29) or higher; primary target Android 16 (API 36). |
| **App SDK** | `minSdk 24`, `targetSdk 34` (forward compatible on Android 16). |
| **Network** | Cellular (4G LTE or 5G NR) and/or WiFi; optional dual SIM. |
| **Permissions** | INTERNET, ACCESS_NETWORK_STATE; RECORD_AUDIO, CAMERA for meetings; READ_BASIC_PHONE_STATE optional for 5G MW detection. |
Below minSdk 24 the app does not build. For full Android 16 behavior and testing, targetSdk 36 is recommended once the project upgrades the Android Gradle Plugin.
---
## Target device summary
| Attribute | Value |
|-----------|--------|
| **Device** | Samsung Galaxy Z Fold5 (SM-F946U1) |
| **OS** | Android 16, One UI 8.0 |
| **Cellular** | 4G LTE, 5G NR, 5G millimeter wave (5G MW) capable |
| **Connectivity** | Dual SIM (physical + eSIM), e.g. Dark Star + US Mobile |
| **Security** | SE for Android (Enforcing), Knox 3.12, DualDAR 1.8.0 |
| **Form factor** | Foldable (cover screen + inner large screen) |
## App compatibility measures
### 1. SDK and API level
- **Current:** `compileSdk = 34`, `targetSdk = 34`, `minSdk = 24` (see `buildSrc/.../AppConfig.kt`).
- **Android 16** uses **API level 36**. The app is **forward compatible**: it runs on Android 16 with existing targetSdk 34; the system applies compatibility behavior.
- **Recommendation for full Android 16 optimization:** When upgrading the projects Android Gradle Plugin (e.g. to 8.9+), set `compileSdk = 36` and `targetSdk = 36` and test against Android 16.
### 2. Foldable support
- **FoldableStateManager** (`core/common`) tracks folded vs unfolded state using a 600 dp width threshold, suitable for Z Fold5 (narrow cover vs wide inner screen).
- **MainActivity** calls `foldableStateManager.updateFoldState(configuration)` in `onCreate` and **onConfigurationChanged**, so fold/unfold updates the UI without requiring an activity recreate when combined with manifest `configChanges`.
- **Manifest:** `MainActivity` declares
`android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"`
so that fold/unfold and size changes are delivered to `onConfigurationChanged` and the activity is not recreated unnecessarily.
- **MainScreen** receives `foldableStateManager` and can adapt layout (e.g. list/detail, panels) for folded vs unfolded.
- **PolicyManager** supports a “lock on fold” option for security when the device is folded.
### 3. 4G LTE, 5G, and 5G MW (smart routing)
- **ConnectivityManager** (`core/common`):
- **getActiveTransportType()** WIFI, CELLULAR, VPN, ETHERNET, UNKNOWN.
- **getCellularGeneration()** when transport is CELLULAR, returns LTE_4G, NR_5G, or NR_5G_MW.
- **Cellular generation logic:**
- LTE → `LTE_4G`.
- NR (5G) + `TelephonyDisplayInfo.overrideNetworkType == OVERRIDE_NETWORK_TYPE_NR_ADVANCED` (value 5) → **NR_5G_MW** (millimeter wave); otherwise → **NR_5G**.
- **Permissions:** `READ_BASIC_PHONE_STATE` is declared (optional) to improve accuracy of 4G/5G/5G MW detection on API 29+. Not required for basic connectivity.
- **Smart routing** (e.g. `MediaRoutingPolicy`, `NetworkPathSelector`) uses transport type and cellular generation to prefer 5G / 5G MW over 4G where appropriate.
### 4. Dual SIM / multi-carrier
- The app uses the systems **default data network** and **active network capabilities** via `ConnectivityManager` and `NetworkCapabilities`. It does not bind to a specific subscription ID.
- On dual-SIM devices (e.g. physical SIM + eSIM), the system chooses the active data subscription; SMOAs connectivity and cellular generation logic apply to whichever subscription is currently used for data. No code changes are required for dual SIM per se.
### 5. Permissions (manifest)
- **Network:** INTERNET, ACCESS_NETWORK_STATE.
- **Phone state (optional):** READ_BASIC_PHONE_STATE (for 4G/5G/5G MW detection).
- **Communications:** RECORD_AUDIO, MODIFY_AUDIO_SETTINGS, CAMERA (meetings).
- **Security:** USE_BIOMETRIC, USE_FINGERPRINT, BIND_VPN_SERVICE.
- **Storage:** READ/WRITE_EXTERNAL_STORAGE with `maxSdkVersion="32"` where applicable.
### 6. Knox and SE Android
- The app does not use Knox APIs. It runs as a normal Android app; Knox/SE for Android enforce system policy (e.g. device attestation, MDM) independently.
- If future versions need Knox integration (e.g. Knox SDK for secure storage or VPN), the same device and OS support the required Knox API level (e.g. 39).
## Testing on Z Fold5
- **Fold/unfold:** Open app on cover screen, unfold and fold; confirm layout updates and no unnecessary activity restarts.
- **Network:** Switch between WiFi and cellular; on cellular, confirm 4G vs 5G (and 5G+ where available) is reflected if you surface cellular generation in UI or logs.
- **Dual SIM:** Use one SIM for data, then switch default data to the other; confirm connectivity and routing still work.
- **Meetings/WebRTC:** Verify camera, microphone, and smart routing (e.g. path selection, codec selection) on both WiFi and 5G.
---
## Aspects which scale (client / device)
These dimensions scale with usage, device variety, or backend load. The required target above is the floor.
| Aspect | What it scales with | How it scales |
|--------|---------------------|----------------|
| **API level (minSdk / targetSdk)** | Newer devices, Android 16+ features | Raise minSdk/targetSdk when dropping older OS support; use `Build.VERSION.SDK_INT` checks for optional APIs (e.g. 5G MW on API 31+). |
| **Screen size / density** | Folded vs unfolded, different devices | `FoldableStateManager` (600 dp threshold); responsive layouts; `configChanges` so fold/unfold doesnt recreate Activity. |
| **Network type** | WiFi vs 4G vs 5G vs 5G MW | `ConnectivityManager.getActiveTransportType()` and `getCellularGeneration()`; smart routing and adaptive codecs use these. |
| **Concurrent backend load** | Number of devices syncing / pulling | Backend scales (see [PROXMOX-VE-TEMPLATE-REQUIREMENTS.md](../infrastructure/PROXMOX-VE-TEMPLATE-REQUIREMENTS.md)); app uses rate limit and retries. |
| **WebRTC sessions** | Number of participants, video quality | Adaptive codec policy and connection-quality tier; TURN/signaling and backend infra scale with sessions. |
| **Sync volume** | Directory/orders/evidence/reports per device | Backend disk and DB; app queues and syncs by type; no fixed device-side limit. |
| **Dual SIM / multi-carrier** | Multiple subscriptions | App uses default data network; no per-SIM logic; scales to any number of SIMs as chosen by system. |
| **Permissions** | Features used (meetings, 5G detection) | Optional permissions (e.g. READ_BASIC_PHONE_STATE) scale with feature set; core works without them. |
---
## References
- **Smart routing / QoS:** [SMART-ROUTING-AND-QOS.md](SMART-ROUTING-AND-QOS.md)
- **Media codecs (P2M, adaptive):** [MEDIA-CODECS-AND-P2M.md](MEDIA-CODECS-AND-P2M.md)
- **Backend sync:** `backend/README.md`, `backend/docs/BACKEND-GAPS-AND-ROADMAP.md`
- **Backend/infra scaling:** [PROXMOX-VE-TEMPLATE-REQUIREMENTS.md](../infrastructure/PROXMOX-VE-TEMPLATE-REQUIREMENTS.md)

View File

@@ -0,0 +1,49 @@
# Connection-Speed-Aware Media and Point-to-Multipoint
## Overview
SMOA audio and video (Communications and Meetings modules) use **connection-speed-aware compression codecs** so that encoding adapts to available bandwidth, RTT, and packet loss. This is especially important for **point-to-multipoint** (one sender, many receivers), where different participants may have different link quality.
## Components
| Component | Location | Purpose |
|-----------|----------|---------|
| **ConnectionTier** | `communications/domain/AdaptiveCodecPolicy.kt` | Bandwidth tier (VERY_LOW … VERY_HIGH) for codec selection. |
| **AudioCodecConstraints** | Same | Opus codec limits: min/max bitrate, bandwidth mode (narrowband/wideband/fullband), DTX. |
| **VideoCodecConstraints** | Same | Video codec (VP8/VP9/H264), max resolution, max bitrate, simulcast/SVC options. |
| **MediaCodecPolicy** | Same | Maps each ConnectionTier to audio and video constraints; default policy is built-in. |
| **ConnectionQualityMonitor** | `communications/domain/ConnectionQualityMonitor.kt` | Interface for current quality (bandwidth, RTT, loss, tier). |
| **StubConnectionQualityMonitor** | `communications/domain/StubConnectionQualityMonitor.kt` | Stub implementation (fixed MEDIUM until WebRTC stats are wired). |
| **AdaptiveCodecSelector** | `communications/domain/AdaptiveCodecSelector.kt` | Selects current audio/video constraints from policy and quality monitor. |
| **WebRTCConfig / RTCConfiguration** | `communications/domain/WebRTCConfig.kt`, `WebRTCManager.kt` | Optional media policy; RTC config carries selected audio/video constraints into peer connection setup. |
## Connection Tiers and Default Policy
- **VERY_LOW** (e.g. &lt; 100 kbps): Audio-only or minimal video; Opus narrowband, low bitrate.
- **LOW** (e.g. 100256 kbps): Low-resolution video (e.g. 320×240), VP8, constrained audio.
- **MEDIUM** (e.g. 256512 kbps): Moderate video (e.g. 640×360), VP8, wideband Opus.
- **HIGH** (e.g. 512 kbps1 Mbps): Higher resolution (e.g. 720p), VP8, simulcast (2 layers), fullband Opus.
- **VERY_HIGH** (e.g. &gt; 1 Mbps): 1080p, VP9, simulcast (3 layers), SVC preferred, fullband Opus.
Exact thresholds are in `connectionTierFromBandwidth()` in `ConnectionQualityMonitor.kt`.
## Point-to-Multipoint
- **Sender**: Uses `AdaptiveCodecSelector.getSendConstraints()` (or current tier) so the **single send** stream uses codec and bitrate appropriate for the current connection. For HIGH/VERY_HIGH, the policy enables **simulcast** (multiple resolution/bitrate layers) so an SFU or receivers can choose the best layer per participant.
- **Receivers**: When WebRTC stats are integrated, each receiver can use its own `ConnectionQualityMonitor` (or stats) to request the appropriate simulcast layer or SVC spatial/temporal layer from the server.
- **Stub**: Until WebRTC is fully integrated, `StubConnectionQualityMonitor` reports a fixed MEDIUM tier. Replace with an implementation that parses `RTCStatsReport` (e.g. outbound-rtp, remote-inbound-rtp, candidate-pair) and calls `update(estimatedBandwidthKbps, rttMs, packetLoss)` (or updates a tier) so the selector adapts in real time.
## Applying Constraints When WebRTC Is Integrated
When the WebRTC library is integrated:
1. When creating the peer connection, read `RTCConfiguration.audioConstraints` and `videoConstraints` (already set by `WebRTCManager` from `AdaptiveCodecSelector`).
2. For **audio**: create the audio track/sender with Opus and apply `minBitrateBps`/`maxBitrateBps` and bandwidth mode (narrowband/wideband/fullband) and DTX from `AudioCodecConstraints`.
3. For **video**: create the video track/sender with the requested codec (VP8/VP9/H264), cap resolution to `maxWidth`×`maxHeight`, set `maxBitrateBps`; if `useSimulcast` is true, configure the appropriate number of simulcast layers.
4. Periodically (e.g. from `getStats()` callback), compute estimated bandwidth (and optionally RTT/loss), call `StubConnectionQualityMonitor.update()` or the real monitors update, and optionally call `AdaptiveCodecSelector.selectForBandwidth()` so constraints are updated for the next negotiation or track reconfiguration.
## Related
- Communications module: `modules/communications/`
- Meetings (video transport): `modules/meetings/domain/VideoTransport.kt`
- WebRTC config: `WebRTCConfig.kt`, `WebRTCManager.kt`

View File

@@ -0,0 +1,101 @@
# SMOA platform requirements Android, iOS, Web
This document defines **required targets** and **supported platforms** for SMOA: **Android** (primary), **iOS** (last three generations), and **Web Dapp** (Desktop/Laptop including touch). All platforms use the same backend API contract.
---
## 1. Required target (all platforms)
| Aspect | Required minimum |
|--------|-------------------|
| **Backend API** | REST `/api/v1` (sync, pull, delete); JSON request/response; optional X-API-Key auth; CORS for web. |
| **Sync contract** | POST sync (directory, order, evidence, credential, report); DELETE for sync delete; GET for pull; `SyncResponse` with success, itemId, serverTimestamp, conflict, remoteData (base64 when conflict). |
| **Auth** | API key via header `X-API-Key` or query `api_key`; when key is set, all `/api/v1/*` require it. |
| **Network** | HTTPS in production; same-origin or configured CORS for web. |
---
## 2. Android (primary)
| Aspect | Required / supported |
|--------|----------------------|
| **OS** | Android 10 (API 29) or higher; primary device Android 16 (API 36). |
| **App SDK** | minSdk 24, targetSdk 34 (forward compatible on 16). |
| **Device** | Primary: Samsung Galaxy Z Fold5 (SM-F946U1) or equivalent foldable with 4G/5G. |
| **Features** | Sync (push/pull/delete), foldable UI, 4G/5G/5G MW detection, WebRTC-ready, VPN-aware routing, biometric. |
| **Details** | See [DEVICE-COMPATIBILITY.md](DEVICE-COMPATIBILITY.md). |
---
## 3. iOS (last three generations)
SMOA supports **iOS clients** for the same backend; an iOS app is a separate codebase (e.g. Swift/SwiftUI or shared logic via KMP).
| Aspect | Required / supported |
|--------|----------------------|
| **OS** | **iOS 15, iOS 16, iOS 17** (last three major generations). Minimum deployment target: **iOS 15.0**. |
| **Devices** | iPhone and iPad: models that run iOS 15+ (e.g. iPhone 6s and later, iPad Air 2 and later, and subsequent generations). |
| **Auth** | Same as backend: `X-API-Key` header or `api_key` query; store key in Keychain. |
| **Sync** | Same REST contract: POST to `/api/v1/sync/*`, DELETE to `/api/v1/sync/{resource}/{id}`, GET to `/api/v1/directory`, `/api/v1/orders`, etc. |
| **Data** | Decode `SyncResponse.remoteData` as base64 when `conflict == true`; use same DTO field names as backend. |
| **Networking** | URLSession or Alamofire; certificate pinning optional; respect rate limit (429). |
| **Offline** | Queue sync when offline; retry when online; optional local persistence (Core Data / SwiftData). |
| **Touch** | Native touch; support pointer events where applicable (iPad). |
| **Gaps to implement** | iOS app project (Swift/SwiftUI or cross-platform); Keychain for API key; optional Face ID / Touch ID for app unlock. |
---
## 4. Web Dapp (Desktop / Laptop, including touch)
SMOA supports a **browser-based Web Dapp** for Desktop and Laptop, including **touch devices** (e.g. touch laptops, tablets in browser).
| Aspect | Required / supported |
|--------|----------------------|
| **Browsers** | Chrome, Firefox, Safari, Edge (current versions); Desktop and Laptop. |
| **Viewports** | Responsive layout: desktop (e.g. 1280px+), laptop (1024px+), and tablet/touch (768px+). |
| **Input** | Mouse + keyboard; **touch** (touchstart/touchend/pointer events) for touch laptops and tablets. |
| **Auth** | Same backend: `X-API-Key` header or `api_key` query; store in secure storage (e.g. sessionStorage for session, or secure cookie if served from same origin). |
| **Sync** | Same REST contract; use `fetch` or axios; CORS must allow the web origin (backend `smoa.cors.allowed-origins`). |
| **Data** | Same JSON DTOs; decode `remoteData` base64 when `conflict == true`. |
| **Offline** | Optional: Service Worker + Cache API; queue sync in IndexedDB/localStorage and flush when online. |
| **HTTPS** | Required in production; backend behind TLS; web app served over HTTPS. |
| **PWA (optional)** | Installable; optional offline shell; same API contract. |
| **Gaps to implement** | Web app codebase (e.g. React, Vue, Svelte); build and host; configure CORS for web origin. |
---
## 5. Backend support for all clients
The backend **already supports** Android, iOS, and Web:
| Feature | Backend | Android | iOS | Web |
|---------|---------|---------|-----|-----|
| **Sync POST** | ✅ | ✅ | Same contract | Same contract |
| **Sync DELETE** | ✅ | ✅ | Same contract | Same contract |
| **Pull GET** | ✅ | ✅ | Same contract | Same contract |
| **API key auth** | ✅ | ✅ | Same contract | Same contract |
| **CORS** | ✅ configurable | N/A | N/A | ✅ use allowed-origins |
| **Rate limit** | ✅ per key/IP | ✅ | Same | Same |
| **Health / info** | ✅ GET /health, GET /api/v1/info | ✅ | Same | Same |
- **CORS:** Set `smoa.cors.allowed-origins` to the web app origin(s) (e.g. `https://smoa.example.com`) when deploying the Web Dapp; use `*` only for dev if acceptable.
- **Discovery:** GET `/api/v1/info` returns endpoint list so any client (Android, iOS, Web) can discover sync, delete, and pull URLs.
---
## 6. Scaling (all platforms)
| Aspect | Scales with | Notes |
|--------|-------------|--------|
| **Concurrent devices** | Number of Android + iOS + Web clients | Backend rate limit and VM sizing; see [PROXMOX-VE-TEMPLATE-REQUIREMENTS.md](../infrastructure/PROXMOX-VE-TEMPLATE-REQUIREMENTS.md). |
| **Sync volume** | Entities per user, pull page size | Backend DB and disk; clients use since/limit on GET. |
| **Web origins** | Multiple Dapp domains | Add all origins to `smoa.cors.allowed-origins` (comma-separated). |
---
## 7. References
- [DEVICE-COMPATIBILITY.md](DEVICE-COMPATIBILITY.md) Android device (Z Fold5) and app
- [REQUIREMENTS-ALIGNMENT.md](REQUIREMENTS-ALIGNMENT.md) Frontendbackend contract and gaps
- [BACKEND-GAPS-AND-ROADMAP.md](../../backend/docs/BACKEND-GAPS-AND-ROADMAP.md) Backend API and ops
- [PROXMOX-VE-TEMPLATE-REQUIREMENTS.md](../infrastructure/PROXMOX-VE-TEMPLATE-REQUIREMENTS.md) Infra sizing

View File

@@ -0,0 +1,103 @@
# SMOA requirements alignment frontend and backend
This document maps **requirements** between the **device application** (Android; future iOS and Web) and the **backend**, and lists **gaps** with ownership (device vs backend).
---
## 1. Sync contract (frontend ↔ backend)
All clients (Android, iOS, Web) use the same REST contract.
| Requirement | Backend | Android app | iOS (to build) | Web Dapp (to build) |
|-------------|---------|-------------|-----------------|----------------------|
| **POST sync** (directory, order, evidence, credential, report) | ✅ SyncController | ✅ SyncAPI + SyncService | Same contract | Same contract |
| **SyncResponse** (success, itemId, serverTimestamp, conflict, remoteData, message) | ✅ | ✅ core/common SyncResponse | Same | Same |
| **Conflict** (server returns conflict + base64 remoteData) | ✅ | ✅ SyncService handles ConflictException | Same | Same |
| **DELETE** (sync delete) | ✅ | ✅ SyncAPI.delete* + SyncService on SyncOperation.Delete | Same | Same |
| **Pull GET** (directory, orders, evidence, credentials, reports) | ✅ PullController | ✅ Use GET with since/limit | Same | Same |
| **Auth** (X-API-Key or api_key) | ✅ | ✅ Send header/query when configured | Same | Same |
| **Rate limit** (429, configurable RPM) | ✅ | ✅ Retry with backoff | Same | Same |
---
## 2. API surface (backend)
| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/health` | GET | Liveness; db status. |
| `/api/v1/info` | GET | Discovery: name, version, list of sync/pull/delete endpoints. |
| `/api/v1/sync/directory` | POST | Sync directory entry. |
| `/api/v1/sync/order` | POST | Sync order. |
| `/api/v1/sync/evidence` | POST | Sync evidence. |
| `/api/v1/sync/credential` | POST | Sync credential. |
| `/api/v1/sync/report` | POST | Sync report. |
| `/api/v1/sync/directory/{id}` | DELETE | Delete directory entry. |
| `/api/v1/sync/order/{orderId}` | DELETE | Delete order. |
| `/api/v1/sync/evidence/{evidenceId}` | DELETE | Delete evidence. |
| `/api/v1/sync/credential/{credentialId}` | DELETE | Delete credential. |
| `/api/v1/sync/report/{reportId}` | DELETE | Delete report. |
| `/api/v1/directory` | GET | List directory (optional unit, X-Unit). |
| `/api/v1/orders` | GET | List orders (since, limit, jurisdiction / X-Unit). |
| `/api/v1/evidence` | GET | List evidence (since, limit, caseNumber). |
| `/api/v1/credentials` | GET | List credentials (since, limit, holderId). |
| `/api/v1/reports` | GET | List reports (since, limit). |
---
## 3. DTO alignment (device → backend)
Device sends JSON that matches backend request DTOs; backend returns JSON that matches device expectations.
| Resource | Request (device → backend) | Response (backend → device) |
|----------|----------------------------|-----------------------------|
| Directory | DirectorySyncRequest (id, name, title, unit, …; lastUpdated) | SyncResponse |
| Order | OrderSyncRequest (orderId, orderType, title, content, …; clientUpdatedAt) | SyncResponse |
| Evidence | EvidenceSyncRequest (evidenceId, caseNumber, …; clientUpdatedAt) | SyncResponse |
| Credential | CredentialSyncRequest (credentialId, holderId, …; clientUpdatedAt) | SyncResponse |
| Report | ReportSyncRequest (reportId, reportType, title, format, …; clientUpdatedAt) | SyncResponse |
**Enums (validation):** orderType, status, evidenceType, reportType, format — backend uses `@Pattern`; device must send allowed values (see backend SyncRequest.kt).
---
## 4. Gaps and ownership
### 4.1 Filled by device (Android)
| Gap | Status | Notes |
|-----|--------|--------|
| **Real SyncAPI implementation** | ✅ Done | BackendSyncAPI (app) calls backend when BuildConfig.SMOA_BACKEND_BASE_URL set; build with -Psmoa.backend.baseUrl=http://host:8080. |
| **SyncService uses SyncAPI** | ✅ Done | CommonModule provides SyncService(syncAPI); AppModule provides SyncAPI (BackendSyncAPI or DefaultSyncAPI). |
| **Delete operation** | ✅ Done | SyncService calls syncAPI.delete*(item.id) when item.operation == SyncOperation.Delete. |
| **Pull on connect** | Optional | On connectivity restored, call GET endpoints and merge into local DB. |
### 4.2 Filled by backend
| Gap | Status | Notes |
|-----|--------|--------|
| **CORS for Web** | ✅ | smoa.cors.allowed-origins; set to web app origin(s) for production. |
| **Info endpoint** | ✅ | GET /api/v1/info lists all sync, delete, and pull endpoints for client discovery. |
| **Auth for all clients** | ✅ | API key required when smoa.api.key set; same for Android, iOS, Web. |
### 4.3 Filled by iOS (when built)
| Gap | Owner | Notes |
|-----|--------|--------|
| **iOS app** | iOS | Swift/SwiftUI or KMP; same REST contract; Keychain for API key. |
| **Offline queue** | iOS | Queue sync when offline; retry when online. |
### 4.4 Filled by Web Dapp (when built)
| Gap | Owner | Notes |
|-----|--------|--------|
| **Web app** | Web | SPA (e.g. React/Vue); responsive + touch; same REST contract. |
| **CORS origin** | Backend config | Set smoa.cors.allowed-origins to web origin. |
| **Secure storage** | Web | sessionStorage or secure cookie for API key/session. |
---
## 5. References
- **Backend API:** `backend/README.md`, OpenAPI `/v3/api-docs`, `/swagger-ui.html`
- **Mobile contract:** `core/common/SyncAPI.kt`, `SyncService.kt`
- **Platforms:** [PLATFORM-REQUIREMENTS.md](PLATFORM-REQUIREMENTS.md)

View File

@@ -0,0 +1,68 @@
# Smart Routing, QoS, Lag Reduction, and System Stability
## Overview
SMOA implements **smart routing** and **QoS (Quality of Service)** for media (voice/video) to improve quality, reduce lag, manage infrastructure, and keep the system stable under poor conditions.
## Components
### Core (core/common)
| Component | Purpose |
|-----------|---------|
| **CircuitBreaker** | Per-endpoint failure handling: after N failures the circuit opens and calls fail fast until reset timeout. Used by InfrastructureManager for STUN/TURN/signaling. |
| **QoSPolicy / TrafficClass** | Traffic classification (VOICE, VIDEO, SIGNALING, DATA) and priority; policy caps (max concurrent sessions, max total send bitrate) for stability. |
| **ConnectivityManager** | Extended with `getActiveTransportType()` (WIFI, CELLULAR, VPN, ETHERNET) and `getCellularGeneration()` (4G LTE, 5G, 5G MW) for path selection. |
| **NetworkTransportType** | Enum for transport used by routing policy. |
| **CellularGeneration** | When on cellular: LTE_4G, NR_5G, NR_5G_MW (millimeter wave), UNKNOWN. Used to prefer 5G / 5G MW over 4G. |
### Communications (modules/communications)
| Component | Purpose |
|-----------|---------|
| **MediaRoutingPolicy** | Path preference: prefer low latency, prefer VPN when required, transport order, path failover, min bandwidth for video. |
| **NetworkPathSelector** | Selects best network path for media using ConnectivityManager, VPNManager, and MediaRoutingPolicy; exposes `SelectedPath` (transport, cellularGeneration when CELLULAR, recommendedForVideo). On cellular, ranks 4G LTE, 5G, and 5G MW per policy. |
| **InfrastructureManager** | Manages STUN/TURN/signaling endpoint lists; uses CircuitBreaker for health; `getHealthyStunUrls()`, `getHealthyTurnServers()`, `getHealthySignalingUrl()`; `buildWebRTCConfig()` for WebRTC with failover. |
| **ConnectionStabilityController** | Reconnection exponential backoff; degradation mode (NONE, AUDIO_ONLY, REDUCED_VIDEO); session count and bitrate caps from QoSPolicy. |
| **SmartRoutingService** | Orchestrates path selection, infra, stability, and adaptive codecs; exposes `RoutingState`, `getWebRTCConfig()`, `tryStartSession()`, `recordConnectionSuccess/Failure`, `updateFromConnectionQuality()`, `onConnectivityChanged()`. |
## QoS and Lag Reduction
- **Traffic classes**: Voice (highest), Video, Signaling, Data. Used for scheduling and prioritization hints.
- **Path selection**: Prefer Wi-Fi/VPN over cellular when policy says so; when on cellular, prefer 5G MW &gt; 5G &gt; 4G LTE (configurable via `cellularGenerationPreferenceOrder`). Avoid sending video when path is not recommended.
- **Adaptive codecs**: Connection-speed-aware codecs (see [MEDIA-CODECS-AND-P2M.md](MEDIA-CODECS-AND-P2M.md)) reduce bitrate on slow links, reducing buffering and lag.
- **Reconnection backoff**: Exponential backoff after connection failures to avoid hammering endpoints and reduce perceived instability.
- **Graceful degradation**: When connection tier is VERY_LOW (or policy says so), switch to AUDIO_ONLY to preserve voice and reduce load.
## Infrastructure Management
- **STUN/TURN/signaling**: Configure via `InfrastructureManager.setStunEndpoints()`, `setTurnEndpoints()`, `setSignalingEndpoints()`.
- **Health**: Each endpoint is protected by a circuit breaker; after a threshold of failures the endpoint is skipped until reset timeout.
- **Failover**: `getHealthyStunUrls()` / `getHealthyTurnServers()` / `getHealthySignalingUrl()` return only endpoints with closed circuits; WebRTC config is built from these for automatic failover.
## System Stability
- **Session cap**: `QoSPolicy.maxConcurrentSessions` limits concurrent media sessions; `SmartRoutingService.tryStartSession()` enforces it.
- **Bitrate cap**: `QoSPolicy.maxTotalSendBitrateBps` can be enforced by the app when sending (ConnectionStabilityController.isWithinBitrateCap()).
- **Circuit breakers**: Prevent cascading failures to unhealthy STUN/TURN/signaling servers.
- **Degradation**: AUDIO_ONLY and REDUCED_VIDEO reduce load when quality is poor.
## Integration
- **WebRTCManager**: Uses `SmartRoutingService.getWebRTCConfig()` for ICE/signaling config (healthy infra) and adaptive codec constraints.
- **VideoTransport** (meetings): Uses `SmartRoutingService.tryStartSession()` / `notifySessionEnded()`, `getRoutingState().recommendedForVideo` to decide audio-only vs video, and `recordConnectionSuccess/Failure()` for backoff.
- **Connectivity changes**: Call `SmartRoutingService.onConnectivityChanged()` when connectivity or VPN state changes so path selection and routing state are updated.
- **Quality updates**: When WebRTC stats (or network callback) provide new bandwidth/RTT/loss, update the connection quality monitor and call `SmartRoutingService.updateFromConnectionQuality()` to adapt codecs and degradation.
## Configuration
- **MediaRoutingPolicy**: Default prefers low latency and VPN when required; customize transport order, `cellularGenerationPreferenceOrder` (4G LTE, 5G, 5G MW), and `minBandwidthKbpsForVideo` per deployment. Cellular generation is derived from `TelephonyManager` (API 29+ for 5G NR; API 31+ for 5G MW when `OVERRIDE_NETWORK_TYPE_NR_ADVANCED` is reported).
- **QoSPolicy**: Set via `SmartRoutingService.setQoSPolicy()` (session cap, bitrate cap).
- **Circuit breaker**: Threshold and reset timeout are in InfrastructureManager (e.g. 3 failures, 60s reset); adjust as needed.
- **StabilityController**: `minBackoffMs`, `maxBackoffMs`, `backoffMultiplier` control reconnection backoff.
## Related
- [MEDIA-CODECS-AND-P2M.md](MEDIA-CODECS-AND-P2M.md) Connection-speed-aware audio/video codecs and point-to-multipoint.
- Communications module: `modules/communications/domain/`.
- Core common: `core/common/` (CircuitBreaker, QoS, ConnectivityManager).