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:
@@ -15,6 +15,7 @@ This is the central index for all SMOA (Secure Mobile Operations Application) do
|
||||
|
||||
### Getting Started
|
||||
- [Project README](../README.md) - Project overview and quick start
|
||||
- [TODO – Remaining and optional tasks](../TODO.md) - Single checklist for remaining and optional work (backend, Android, iOS, Web, infra, compliance, testing)
|
||||
- [Specification](reference/SPECIFICATION.md) - Application specification
|
||||
- [Documentation Recommendations](DOCUMENTATION_RECOMMENDATIONS.md) - Documentation organization recommendations
|
||||
- [Documentation Plan](standards/DOCUMENTATION_PLAN.md) - Comprehensive documentation plan
|
||||
@@ -65,6 +66,11 @@ This is the central index for all SMOA (Secure Mobile Operations Application) do
|
||||
- [API Documentation](api/) - API specifications and reference
|
||||
- [Database Schema](database/) - Database schema and data models
|
||||
- [Integration Documentation](integrations/) - External system integrations
|
||||
- [Smart Routing and QoS](reference/SMART-ROUTING-AND-QOS.md) - QoS, lag reduction, infra management, system stability
|
||||
- [Media Codecs and Point-to-Multipoint](reference/MEDIA-CODECS-AND-P2M.md) - Connection-speed-aware audio/video codecs
|
||||
- [Platform Requirements](reference/PLATFORM-REQUIREMENTS.md) - Android, iOS (last 3 generations), Web Dapp (Desktop/Laptop + touch)
|
||||
- [Requirements Alignment](reference/REQUIREMENTS-ALIGNMENT.md) - Frontend–backend contract and gaps
|
||||
- [Device Compatibility](reference/DEVICE-COMPATIBILITY.md) - Primary device (Z Fold5) and app compatibility
|
||||
|
||||
### User Documentation
|
||||
- [User Manual](user/SMOA-User-Manual.md) - Complete user guide
|
||||
|
||||
@@ -20,11 +20,11 @@ SMOA provides secure mobile operations capabilities for government and military
|
||||
- Domain-specific operations (law enforcement, military, judicial, intelligence)
|
||||
|
||||
### System Context
|
||||
SMOA operates in a secure mobile environment with:
|
||||
- **Operating System:** Android (enterprise-hardened builds)
|
||||
- **Device Class:** Foldable smartphones with biometric hardware support
|
||||
- **Deployment Model:** Government-furnished or government-approved devices under MDM/UEM control
|
||||
- **Connectivity:** Online, offline, and degraded modes
|
||||
SMOA operates in a secure mobile and multi-platform environment with:
|
||||
- **Primary client:** Android (enterprise-hardened builds); primary device class foldable smartphones with biometric hardware support.
|
||||
- **Additional clients:** iOS (last three generations: iOS 15, 16, 17) and Web Dapp (Desktop/Laptop, including touch devices); same backend API contract.
|
||||
- **Deployment Model:** Government-furnished or government-approved devices under MDM/UEM control where applicable; Web Dapp served over HTTPS with CORS.
|
||||
- **Connectivity:** Online, offline, and degraded modes; backend supports all clients via REST and configurable CORS.
|
||||
|
||||
---
|
||||
|
||||
|
||||
167
docs/infrastructure/PROXMOX-VE-TEMPLATE-REQUIREMENTS.md
Normal file
167
docs/infrastructure/PROXMOX-VE-TEMPLATE-REQUIREMENTS.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# Proxmox VE template – hardware requirements for SMOA backend and supporting infra
|
||||
|
||||
This document lists **hardware requirements** for building a **Proxmox VE template** used to run the SMOA backend and supporting infrastructure (database, optional reverse proxy, optional TURN/signaling).
|
||||
|
||||
---
|
||||
|
||||
## Required target (mandatory minimum)
|
||||
|
||||
The **minimum viable target** for a single Proxmox VE template running the SMOA backend is:
|
||||
|
||||
| Aspect | Required minimum |
|
||||
|--------|-------------------|
|
||||
| **Backend VM** | 2 vCPU, 1 GiB RAM, 8 GiB disk, 1 Gbps network |
|
||||
| **OS** | Linux (e.g. Debian 12 or Ubuntu 22.04 LTS) |
|
||||
| **Java** | OpenJDK 17 (Eclipse Temurin or equivalent) |
|
||||
| **Backend** | `smoa-backend` JAR on port 8080; H2 file DB or PostgreSQL |
|
||||
| **Data** | Persistent storage for `./data/smoa` (H2) or PostgreSQL data directory |
|
||||
| **Proxmox host** | 4 physical cores, 8 GiB RAM, 128 GiB SSD, 1 Gbps NIC |
|
||||
|
||||
Below this, the backend may run but is not supported for production (no headroom for spikes, logs, or audit growth). All other dimensions (RAM, disk, vCPU, separate DB/proxy/TURN) are **scaling aspects** described in the next section.
|
||||
|
||||
---
|
||||
|
||||
## 1. Backend service (smoa-backend)
|
||||
|
||||
| Resource | Minimum (dev/small) | Recommended (production) | Notes |
|
||||
|----------|----------------------|---------------------------|--------|
|
||||
| **vCPU** | 2 | 4 | Spring Boot + JPA; sync and pull endpoints can spike briefly. |
|
||||
| **RAM** | 1 GiB | 2–4 GiB | JVM heap ~512 MiB–1 GiB; leave headroom for OS and buffers. |
|
||||
| **Disk** | 8 GiB | 20–40 GiB | OS + JAR + H2 data (or PostgreSQL data dir if DB on same VM). Logs and audit table growth. |
|
||||
| **Network** | 1 Gbps (shared) | 1 Gbps | API traffic; rate limit 120 req/min per client by default. |
|
||||
|
||||
- **Stack:** OpenJDK 17 (Eclipse Temurin), Spring Boot 3, Kotlin; H2 (file) or PostgreSQL.
|
||||
- **Ports:** 8080 (HTTP); optionally 8443 if TLS is terminated on the VM.
|
||||
- **Storage:** Persistent volume for `./data/smoa` (H2) or PostgreSQL data directory; consider separate disk for logs/audit.
|
||||
|
||||
---
|
||||
|
||||
## 2. Supporting infrastructure (same or separate VMs)
|
||||
|
||||
### 2.1 Database (if not H2 on backend VM)
|
||||
|
||||
When moving off H2 to **PostgreSQL** (recommended for production):
|
||||
|
||||
| Resource | Minimum | Recommended |
|
||||
|----------|---------|-------------|
|
||||
| **vCPU** | 2 | 2–4 |
|
||||
| **RAM** | 1 GiB | 2–4 GiB |
|
||||
| **Disk** | 20 GiB | 50–100 GiB (SSD preferred) |
|
||||
| **Network** | 1 Gbps | 1 Gbps |
|
||||
|
||||
- Can run on the **same Proxmox VM** as the backend (small deployments) or a **dedicated VM** (better isolation and scaling).
|
||||
|
||||
### 2.2 Reverse proxy (optional)
|
||||
|
||||
If you run **Nginx**, **Traefik**, or **Caddy** in front of the backend (TLS, load balancing, rate limiting):
|
||||
|
||||
| Resource | Minimum | Notes |
|
||||
|----------|---------|--------|
|
||||
| **vCPU** | 1 | Light. |
|
||||
| **RAM** | 512 MiB | |
|
||||
| **Disk** | 4 GiB | Config + certs + logs. |
|
||||
|
||||
- Can share a VM with the backend (e.g. Nginx in same template, backend as systemd service) or run as a separate small VM.
|
||||
|
||||
### 2.3 TURN / signaling (optional)
|
||||
|
||||
If you host **TURN** and/or **signaling** for WebRTC (meetings) instead of using external services:
|
||||
|
||||
| Resource | Minimum | Recommended |
|
||||
|----------|---------|-------------|
|
||||
| **vCPU** | 2 | 4 |
|
||||
| **RAM** | 1 GiB | 2 GiB |
|
||||
| **Disk** | 10 GiB | 20 GiB |
|
||||
| **Network** | 1 Gbps | 1 Gbps+, low latency |
|
||||
|
||||
- Media traffic can be CPU- and bandwidth-heavy; size for peak concurrent sessions.
|
||||
|
||||
---
|
||||
|
||||
## 3. Combined “all-in-one” template (single VM)
|
||||
|
||||
A single Proxmox VE template that runs backend + PostgreSQL + optional Nginx on one VM:
|
||||
|
||||
| Resource | Minimum | Recommended (production) |
|
||||
|----------|---------|---------------------------|
|
||||
| **vCPU** | 4 | 6–8 |
|
||||
| **RAM** | 4 GiB | 8 GiB |
|
||||
| **Disk** | 40 GiB | 80–120 GiB (SSD) |
|
||||
| **Network** | 1 Gbps | 1 Gbps |
|
||||
|
||||
- **Layout:**
|
||||
- OS (e.g. Debian 12 / Ubuntu 22.04 LTS), Docker or systemd.
|
||||
- Backend JAR (or container), listening on 8080.
|
||||
- PostgreSQL (if used) and optional Nginx on same host.
|
||||
- Persistent volumes for DB data, backend H2 (if kept), and logs.
|
||||
|
||||
---
|
||||
|
||||
## 4. Proxmox VE host (physical) recommendations
|
||||
|
||||
To run one or more VMs built from the template:
|
||||
|
||||
| Resource | Small (dev / few users) | Production (dozens of devices) |
|
||||
|----------|---------------------------|-------------------------------|
|
||||
| **CPU** | 4 cores | 8–16 cores |
|
||||
| **RAM** | 8 GiB | 32–64 GiB |
|
||||
| **Storage** | 128 GiB SSD | 256–512 GiB SSD (or NVMe) |
|
||||
| **Network** | 1 Gbps | 1 Gbps (low latency to mobile clients) |
|
||||
|
||||
- Prefer **SSD/NVMe** for database and backend data directories.
|
||||
- **Backups:** Use Proxmox backup or external backup for VM disks / PostgreSQL dumps and backend audit data.
|
||||
|
||||
---
|
||||
|
||||
## 5. Template contents checklist
|
||||
|
||||
- **OS:** Debian 12 or Ubuntu 22.04 LTS (minimal/server).
|
||||
- **Java:** OpenJDK 17 (Eclipse Temurin) or Adoptium.
|
||||
- **Backend:** Install path for `smoa-backend-*.jar`; systemd unit; env file for `SERVER_PORT`, `SPRING_PROFILES_ACTIVE`, `SMOA_API_KEY`, `spring.datasource.url` (if PostgreSQL).
|
||||
- **Optional:** PostgreSQL 15+ (if not using H2); Nginx/Caddy for reverse proxy and TLS.
|
||||
- **Firewall:** Allow 8080 (backend) and 80/443 if reverse proxy; restrict admin/SSH.
|
||||
- **Persistent:** Separate disk or volume for data (H2 `./data/smoa` or PostgreSQL data dir) and logs; exclude from “golden” template so each clone gets its own data.
|
||||
|
||||
---
|
||||
|
||||
## 6. Summary table (single backend VM, no separate DB/proxy)
|
||||
|
||||
| Component | vCPU | RAM | Disk | Network |
|
||||
|-----------|------|-----|------|---------|
|
||||
| **SMOA backend (all-in-one)** | 4 | 4 GiB | 40 GiB | 1 Gbps |
|
||||
| **Production (backend + PostgreSQL on same VM)** | 6 | 8 GiB | 80 GiB SSD | 1 Gbps |
|
||||
|
||||
---
|
||||
|
||||
## 7. All aspects which scale
|
||||
|
||||
Every dimension below **scales** with load, retention, or features. The required target (Section above) is the floor; use this section to size for growth.
|
||||
|
||||
| Aspect | What it scales with | How to scale | Config / notes |
|
||||
|--------|---------------------|--------------|----------------|
|
||||
| **vCPU (backend)** | Concurrent requests, JPA/DB work, sync bursts | Add vCPUs (4 → 6 → 8). Consider second backend instance + load balancer for high concurrency. | Spring Boot thread pool; no app config for vCPU. |
|
||||
| **RAM (backend)** | JVM heap, connection pools, cached entities, OS buffers | Increase VM RAM; set `-Xmx` (e.g. 1 GiB–2 GiB) leaving headroom for OS. | `JAVA_OPTS` or systemd `Environment`. |
|
||||
| **Disk (backend)** | H2/PostgreSQL data, log files, audit table (`sync_audit_log`) | Add disk or separate volume; rotate logs; archive/trim audit by date. | `spring.datasource.url`; logging config; optional audit retention job. |
|
||||
| **Network (backend)** | Request volume, payload size (sync/pull), rate limit | Bigger NIC or multiple backends behind proxy. | `smoa.rate-limit.requests-per-minute` (default 120 per key/IP). |
|
||||
| **Rate limit** | Number of clients and req/min per client | Increase `smoa.rate-limit.requests-per-minute` or disable for trusted LAN. | `application.yml` / env `SMOA_RATE_LIMIT_RPM`. |
|
||||
| **Concurrent devices (API)** | Sync + pull traffic from many devices | More backend vCPU/RAM; optional horizontal scaling (multiple backends + Nginx/Traefik). | No hard cap in app; rate limit is per key/IP. |
|
||||
| **Database size** | Directory, orders, evidence, credentials, reports, audit rows | More disk; move to dedicated PostgreSQL VM; indexes and vacuum. | `spring.datasource.*`; JPA/ddl-auto or Flyway. |
|
||||
| **Audit retention** | Compliance; `sync_audit_log` row count | More disk; periodic delete/archive by date; separate audit store. | Application-level job or DB cron. |
|
||||
| **vCPU (PostgreSQL)** | Query concurrency, connections, joins | Add vCPUs or move DB to dedicated VM with more cores. | `max_connections`, connection pool in backend. |
|
||||
| **RAM (PostgreSQL)** | Cache, working set | Increase VM RAM; tune `shared_buffers` / `work_mem`. | PostgreSQL config. |
|
||||
| **Disk (PostgreSQL)** | Tables, indexes, WAL | Add disk or volume; use SSD. | Data directory; backup size. |
|
||||
| **Reverse proxy** | TLS, load balancing, rate limiting | Add vCPU/RAM if many backends or heavy TLS; scale Nginx/Caddy workers. | Nginx `worker_processes`; upstreams. |
|
||||
| **TURN / signaling** | Concurrent WebRTC sessions, media bitrate | Scale vCPU (media encode/decode), RAM, and **network bandwidth**; add TURN instances for geography. | TURN/signaling server config; app `InfrastructureManager` endpoints. |
|
||||
| **Proxmox host CPU** | Sum of all VMs’ vCPU; burst load | Add physical cores; avoid overcommit (e.g. total vCPU < 2× physical for production). | VM vCPU count. |
|
||||
| **Proxmox host RAM** | Sum of all VMs’ RAM | Add DIMMs; avoid overcommit. | VM RAM allocation. |
|
||||
| **Proxmox host disk** | All VMs + backups | Add disks or NAS; use SSD for DB and backend data. | VM disk size; backup retention. |
|
||||
| **Proxmox host network** | All VMs’ traffic; backup/restore | 1 Gbps minimum; 10 Gbps for many devices or TURN. | NIC; VLANs if needed. |
|
||||
|
||||
### Scaling summary
|
||||
|
||||
- **Backend only:** Scale **vCPU** and **RAM** for more concurrent devices and request spikes; **disk** for logs and audit.
|
||||
- **Backend + PostgreSQL:** Scale **DB disk** and **DB RAM** with data size and query load; **backend vCPU/RAM** with API load.
|
||||
- **With TURN/signaling:** Scale **TURN vCPU, RAM, and network** with concurrent WebRTC sessions and media bitrate.
|
||||
- **Multi-node:** Add more backend or TURN VMs and scale **reverse proxy** and **Proxmox host** to support them.
|
||||
|
||||
These hardware requirements support the SMOA backend (sync, pull, delete, rate limiting, audit logging) and optional supporting infrastructure for a Proxmox VE template.
|
||||
80
docs/infrastructure/k8s/backend-deployment.yaml
Normal file
80
docs/infrastructure/k8s/backend-deployment.yaml
Normal file
@@ -0,0 +1,80 @@
|
||||
# Example Kubernetes Deployment and Service for SMOA backend.
|
||||
# Apply: kubectl apply -f docs/infrastructure/k8s/
|
||||
# Requires: backend image built (e.g. docker build -f backend/Dockerfile .) and pushed to your registry.
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: smoa-backend
|
||||
labels:
|
||||
app: smoa-backend
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: smoa-backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: smoa-backend
|
||||
spec:
|
||||
containers:
|
||||
- name: backend
|
||||
image: smoa-backend:1.0.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: SPRING_PROFILES_ACTIVE
|
||||
value: "prod"
|
||||
- name: SMOA_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: smoa-secrets
|
||||
key: api-key
|
||||
- name: SMOA_CORS_ORIGINS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: smoa-config
|
||||
key: cors-origins
|
||||
optional: true
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "1000m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
restartPolicy: Always
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: smoa-backend
|
||||
labels:
|
||||
app: smoa-backend
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: smoa-backend
|
||||
---
|
||||
# Optional: create secret and configmap (replace values)
|
||||
# kubectl create secret generic smoa-secrets --from-literal=api-key=YOUR_API_KEY
|
||||
# kubectl create configmap smoa-config --from-literal=cors-origins=https://smoa.example.com
|
||||
34
docs/infrastructure/nginx-smoa.conf.example
Normal file
34
docs/infrastructure/nginx-smoa.conf.example
Normal file
@@ -0,0 +1,34 @@
|
||||
# Example Nginx config for SMOA backend (reverse proxy + TLS).
|
||||
# Place in /etc/nginx/sites-available/ and symlink to sites-enabled.
|
||||
# Replace smoa.example.com and paths with your values.
|
||||
|
||||
upstream smoa_backend {
|
||||
server 127.0.0.1:8080;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name smoa.example.com;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name smoa.example.com;
|
||||
|
||||
ssl_certificate /etc/ssl/certs/smoa.example.com.crt;
|
||||
ssl_certificate_key /etc/ssl/private/smoa.example.com.key;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
location / {
|
||||
proxy_pass http://smoa_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Connection "";
|
||||
}
|
||||
}
|
||||
29
docs/ios/README.md
Normal file
29
docs/ios/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# SMOA iOS app (scaffold)
|
||||
|
||||
This folder is a **scaffold** for the SMOA iOS app. The actual app is to be implemented in a separate Xcode project or repo, targeting **iOS 15, 16, and 17** (last three generations).
|
||||
|
||||
## Contract
|
||||
|
||||
- Use the same **REST API** as Android and Web: see [PLATFORM-REQUIREMENTS.md](../reference/PLATFORM-REQUIREMENTS.md) and [REQUIREMENTS-ALIGNMENT.md](../reference/REQUIREMENTS-ALIGNMENT.md).
|
||||
- **Sync:** POST to `/api/v1/sync/directory`, `/api/v1/sync/order`, etc.; DELETE for sync delete.
|
||||
- **Pull:** GET `/api/v1/directory`, `/api/v1/orders`, `/api/v1/evidence`, `/api/v1/credentials`, `/api/v1/reports` (with `since`, `limit`, optional filters).
|
||||
- **Auth:** Header `X-API-Key` or query `api_key`.
|
||||
- **Response:** JSON; when `conflict: true`, `remoteData` is base64-encoded JSON.
|
||||
|
||||
## Implementation checklist
|
||||
|
||||
- [ ] Create Xcode project (Swift/SwiftUI or cross-platform); minimum deployment target iOS 15.0.
|
||||
- [ ] Store API key in **Keychain**.
|
||||
- [ ] Implement **PullAPI** (URLSession or Alamofire): GET endpoints above.
|
||||
- [ ] Implement **SyncAPI**: POST sync + DELETE; parse `SyncResponse`, decode `remoteData` when conflict.
|
||||
- [ ] **Offline queue:** Queue sync when offline; retry when online; optional Core Data / SwiftData for persistence.
|
||||
- [ ] Optional: Face ID / Touch ID for app unlock; certificate pinning for API.
|
||||
|
||||
## Discovery
|
||||
|
||||
- GET `/api/v1/info` returns `endpoints` (sync, delete, pull) and `auth` for client discovery.
|
||||
|
||||
## References
|
||||
|
||||
- Backend: [backend/README.md](../../backend/README.md)
|
||||
- Platform requirements: [docs/reference/PLATFORM-REQUIREMENTS.md](../reference/PLATFORM-REQUIREMENTS.md)
|
||||
10
docs/reference/ANDROID-16-TARGET.md
Normal file
10
docs/reference/ANDROID-16-TARGET.md
Normal 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.
|
||||
110
docs/reference/DEVICE-COMPATIBILITY.md
Normal file
110
docs/reference/DEVICE-COMPATIBILITY.md
Normal 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 Wi‑Fi; 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 project’s 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 system’s **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; SMOA’s 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 Wi‑Fi 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 Wi‑Fi 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 doesn’t recreate Activity. |
|
||||
| **Network type** | Wi‑Fi 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)
|
||||
49
docs/reference/MEDIA-CODECS-AND-P2M.md
Normal file
49
docs/reference/MEDIA-CODECS-AND-P2M.md
Normal 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. < 100 kbps): Audio-only or minimal video; Opus narrowband, low bitrate.
|
||||
- **LOW** (e.g. 100–256 kbps): Low-resolution video (e.g. 320×240), VP8, constrained audio.
|
||||
- **MEDIUM** (e.g. 256–512 kbps): Moderate video (e.g. 640×360), VP8, wideband Opus.
|
||||
- **HIGH** (e.g. 512 kbps–1 Mbps): Higher resolution (e.g. 720p), VP8, simulcast (2 layers), fullband Opus.
|
||||
- **VERY_HIGH** (e.g. > 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 monitor’s 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`
|
||||
101
docs/reference/PLATFORM-REQUIREMENTS.md
Normal file
101
docs/reference/PLATFORM-REQUIREMENTS.md
Normal 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) – Frontend–backend 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
|
||||
103
docs/reference/REQUIREMENTS-ALIGNMENT.md
Normal file
103
docs/reference/REQUIREMENTS-ALIGNMENT.md
Normal 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)
|
||||
68
docs/reference/SMART-ROUTING-AND-QOS.md
Normal file
68
docs/reference/SMART-ROUTING-AND-QOS.md
Normal 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 > 5G > 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).
|
||||
@@ -197,6 +197,16 @@ For detailed compliance information, see:
|
||||
|
||||
## Remaining Work
|
||||
|
||||
**See [TODO.md](../../TODO.md)** for the full checklist of remaining and optional tasks (backend, Android, iOS, Web, infrastructure, compliance, testing).
|
||||
|
||||
### Next steps (short-term)
|
||||
|
||||
1. **Backend:** Run `./gradlew :backend:test` and fix any failures; add integration tests for sync/pull/health.
|
||||
2. **Android 16:** When upgrading AGP to 8.5+, set `compileSdk = 36`, `targetSdk = 36` (see [ANDROID-16-TARGET.md](../reference/ANDROID-16-TARGET.md)).
|
||||
3. **Web:** Expand [web scaffold](../web-scaffold/index.html) (directory pull and status UI are in place); optional: React/Vue SPA, build pipeline, CORS in production.
|
||||
4. **iOS / Web Dapp:** Full apps are separate codebases; use [docs/ios/README.md](../ios/README.md) and web scaffold as starting points.
|
||||
5. **Domain/compliance:** NCIC, ATF, eIDAS QTSP, full WebRTC/AS4/signing require external approvals or larger implementations; extend stubs as needed.
|
||||
|
||||
### High Priority (Future Enhancements)
|
||||
|
||||
1. **WebRTC Full Library Integration**
|
||||
|
||||
72
docs/web-scaffold/index.html
Normal file
72
docs/web-scaffold/index.html
Normal file
@@ -0,0 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<title>SMOA Web</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
body { font-family: system-ui, sans-serif; margin: 1rem; max-width: 900px; }
|
||||
input, button { padding: 0.5rem 0.75rem; margin: 0.25rem; }
|
||||
button { cursor: pointer; background: #2563eb; color: #fff; border: none; border-radius: 6px; }
|
||||
button:disabled { opacity: 0.6; cursor: not-allowed; }
|
||||
#out { white-space: pre-wrap; background: #f1f5f9; padding: 1rem; margin-top: 1rem; border-radius: 8px; font-size: 0.875rem; }
|
||||
.section { margin-top: 1.5rem; }
|
||||
ul { list-style: none; padding: 0; }
|
||||
li { padding: 0.35rem 0; border-bottom: 1px solid #e2e8f0; }
|
||||
.error { color: #dc2626; }
|
||||
@media (pointer: coarse) { button { min-height: 44px; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SMOA Web</h1>
|
||||
<p>Base URL: <input id="baseUrl" value="http://localhost:8080" size="40" placeholder="http://localhost:8080" /></p>
|
||||
<p>API key: <input id="apiKey" type="password" size="24" placeholder="optional" /></p>
|
||||
<p>
|
||||
<button id="btnInfo">API info</button>
|
||||
<button id="btnHealth">Health</button>
|
||||
<button id="btnDirectory">Pull directory</button>
|
||||
</p>
|
||||
<div class="section">
|
||||
<h2>Directory (pull)</h2>
|
||||
<ul id="directoryList"></ul>
|
||||
<p id="dirStatus"></p>
|
||||
</div>
|
||||
<pre id="out"></pre>
|
||||
<script>
|
||||
function base() { return document.getElementById('baseUrl').value.replace(/\/$/, ''); }
|
||||
function key() { return document.getElementById('apiKey').value.trim() || null; }
|
||||
function headers() { var h = { 'Content-Type': 'application/json' }; if (key()) h['X-API-Key'] = key(); return h; }
|
||||
function out(t) { document.getElementById('out').textContent = t; }
|
||||
function dirList(html) { document.getElementById('directoryList').innerHTML = html; }
|
||||
function dirStatus(t) { document.getElementById('dirStatus').textContent = t; }
|
||||
|
||||
document.getElementById('btnInfo').onclick = function() {
|
||||
fetch(base() + '/api/v1/info', { headers: headers() }).then(function(r) { return r.json(); }).then(function(j) { out(JSON.stringify(j, null, 2)); }).catch(function(e) { out('Error: ' + e.message); });
|
||||
};
|
||||
document.getElementById('btnHealth').onclick = function() {
|
||||
fetch(base() + '/health').then(function(r) { return r.json(); }).then(function(j) { out(JSON.stringify(j, null, 2)); }).catch(function(e) { out('Error: ' + e.message); });
|
||||
};
|
||||
document.getElementById('btnDirectory').onclick = function() {
|
||||
var btn = document.getElementById('btnDirectory');
|
||||
btn.disabled = true;
|
||||
dirStatus('Loading…');
|
||||
fetch(base() + '/api/v1/directory', { headers: headers() })
|
||||
.then(function(r) {
|
||||
if (r.status === 304) { dirStatus('Not modified (304)'); return []; }
|
||||
return r.json();
|
||||
})
|
||||
.then(function(arr) {
|
||||
if (!Array.isArray(arr)) { dirStatus('Unexpected response'); return; }
|
||||
if (arr.length === 0) { dirList('<li>No entries</li>'); dirStatus('Empty list'); }
|
||||
else {
|
||||
dirList(arr.map(function(e) { return '<li>' + (e.name || e.id) + ' — ' + (e.unit || '') + '</li>'; }).join(''));
|
||||
dirStatus('Loaded ' + arr.length + ' entries');
|
||||
}
|
||||
})
|
||||
.catch(function(e) { dirStatus('Error: ' + e.message); dirList(''); })
|
||||
.then(function() { btn.disabled = false; });
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user