# QMAX Architecture ```mermaid flowchart LR A["Android app
Kotlin + Compose"] -->|HTTPS JSON + uploads| B["QMAX API
ASP.NET Core"] A -->|SignalR planned/available| B B --> C["SQLite cache
tenant-scoped chats/messages/sessions"] B --> D["Local storage
attachments/releases"] B -->|HTTP internal| E["MAX worker
Python + PyMax"] E -->|isolated session per user| F["MAX mobile API"] B --> G["Caddy TLS
qmax.kusoft.xyz"] ``` The server is the only public backend surface. The PyMax worker stays inside the Docker network and is controlled through the API/admin page. ## Security Rules - Android starts a short-lived phone challenge; JWT credentials are issued only after PyMax confirms the MAX code. - `QMAX_PAIRING_CODE` is an optional registration gate, not a substitute for MAX phone verification. - API access uses JWT access tokens and refresh tokens. - Chats, messages, push devices, realtime notifications and MAX state are scoped by QMAX user id. - MAX session files live only on the Pi in per-user Docker-volume directories. - `.env`, service-account files, keystores and runtime data are ignored by git. - Attachments are written as `.part` first and moved into place only after full upload. - Android image attachments are downloaded to a local `.part` cache and exposed to the UI only after size validation. ## Implemented Status - Phone challenge routing and per-user PyMax session directories are implemented in `pymax-worker/src/server.py`. - Chat list, message history, text sending and attachment sending are mapped through `pymax-worker/src/server.py`. - Image, video, file and voice attachments are projected through the API and rendered by the Android client. - Firebase initialization and Android push token registration are enabled for `xyz.kusoft.qmax`. Live multi-account authorization against MAX and Raspberry Pi capacity were not verified in this workspace. ## Remaining Production Checks - Keep PyMax session-expiration monitoring active. - Run an unlocked-device visual pass on the connected phone for every major UI change. - Replace debug fallback signing with a real release key in `android/key.properties`.