# Phone Recorder - Architecture Overview ## Purpose Android app that records audio continuously, encrypts recordings immediately (never stored unencrypted), and syncs them to a server over LAN or internet. ## Security Model ``` Phone (has: server public key) Server (has: private key) ───────────────────────────── ──────────────────────── Record audio → temp.ogg Encrypt with public key → recording_*.ogg.enc │ └──── HTTP POST ────────→ Receive encrypted file Decrypt with private key Store as .ogg in recordings/ ``` - **Sealed box encryption**: X25519 key exchange + XSalsa20-Poly1305 - **Forward secrecy**: Each encryption uses ephemeral keys - **Phone never stores unencrypted**: Temp file deleted immediately after encryption - **If no public key configured**: Recordings are deleted (security-first design) ## File Format (SREC) Encrypted files use a chunked format for streaming large files: ``` [4 bytes: "SREC" magic] [1 byte: version (1)] [4 bytes: chunk count, big-endian] For each chunk (64KB max): [4 bytes: encrypted length, big-endian] [N bytes: sealed box ciphertext] ``` ## Android App Structure ### Main Files | File | Purpose | |------|---------| | `MainActivity.kt` | UI, settings, sync controls | | `RecordingService.kt` | Foreground service for recording, encryption on stop | | `StorageHelper.kt` | File paths, temp vs recordings directories | ### Crypto Package (`crypto/`) | File | Purpose | |------|---------| | `CryptoHelper.kt` | SREC format encryption using lazysodium | | `KeyManager.kt` | Store/retrieve server public key (SharedPreferences) | ### Sync Package (`sync/`) | File | Purpose | |------|---------| | `SyncSettings.kt` | Sync mode enum, server URLs, LAN subnet prefix | | `NetworkHelper.kt` | Detect WiFi, LAN (by IP prefix), network availability | | `SyncTracker.kt` | Track which files synced successfully (SharedPreferences) | | `SyncWorker.kt` | WorkManager background job for uploads | | `SyncManager.kt` | Schedule periodic (15min) and immediate syncs | ### API Package (`api/`) | File | Purpose | |------|---------| | `RecordingsApi.kt` | OkHttp client, upload with SHA-256 verification | ## Sync Modes | Mode | Behavior | |------|----------| | Never | No sync, files stay on phone | | LAN Only | Sync only when IP matches configured subnet (e.g., `10.0.0.`) | | WiFi Only | Sync on any WiFi network | | Any Network | Sync on WiFi or mobile data | ## Server Structure (Python/FastAPI) | File | Purpose | |------|---------| | `main.py` | FastAPI endpoints | | `crypto.py` | PyNaCl decryption, keypair management | | `config.py` | Paths, ports | ### Endpoints | Endpoint | Method | Description | |----------|--------|-------------| | `/health` | GET | Returns `{"status": "ok"}` | | `/api/v1/public-key` | GET | Returns Base64 public key | | `/api/v1/recordings/upload` | POST | Upload encrypted file, returns hash for verification | | `/api/v1/recordings` | GET | List decrypted recordings | ## Data Flow 1. **Recording starts**: `RecordingService` writes to `temp/recording_TIMESTAMP.ogg` 2. **Recording stops**: - `CryptoHelper.encryptFile()` reads temp, writes `recordings/recording_TIMESTAMP.ogg.enc` - Temp file deleted - `SyncManager.scheduleImmediateSync()` triggered 3. **Sync runs**: - `SyncWorker` checks network conditions match `SyncMode` - Computes SHA-256 of encrypted file - Uploads to server - Server decrypts, returns hash - If hashes match, marks file as synced 4. **Server storage**: `recordings/YYYY/MM/DD/recording_TIMESTAMP.ogg` ## Key Dependencies ### Android - `lazysodium-android` - libsodium bindings - `androidx.work` - Background job scheduling - `okhttp3` - HTTP client ### Server - `fastapi` + `uvicorn` - Web framework - `pynacl` - libsodium bindings - `aiofiles` - Async file I/O ## Configuration ### Android (in-app settings) - Sync mode (Never/LAN/WiFi/Any) - LAN subnet prefix (default: `10.0.0.`) - Server URLs (LAN and remote) - Server public key (Base64) ### Server (config.py or env vars) - `HOST` - Bind address (default: 0.0.0.0) - `PORT` - Listen port (default: 8000) - `BASE_DIR` - Base directory for keys and recordings