# Platform Overview ## System Architecture The PTT Platform consists of three independently deployed components that communicate through well-defined interfaces. ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ VENDOR INFRASTRUCTURE │ │ ┌───────────────────┐ ┌──────────────────────────────────────────┐ │ │ │ Platform Root CA │ │ Platform Attestation Service (PAS) │ │ │ │ (air-gapped) │ │ POST /v1/device-certificates │ │ │ │ │ │ Validates Bootstrap JWT │ │ │ │ Platform Issuing │ │ Issues Device Certificates │ │ │ │ CA (Vault PKI) │ │ (signed by Platform Issuing CA) │ │ │ └───────────────────┘ └──────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────────────┐ │ OPERATOR SYSTEM (one per operator) │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌───────────────────────┐ │ │ │ System CA │ │ ptt-server │ │ ptt-backend (REST) │ │ │ │ (offline) │ │ (Node.js + │────▶│ Devices, Talkgroups │ │ │ │ issues leaf │ │ Socket.IO) │ │ Config, Keystore │ │ │ │ certs │ │ │ └───────────────────────┘ │ │ └──────────────┘ └──────┬────────┘ │ │ │ ┌──────────────────┐ │ │ │ │ Redis │ │ │ │ │ KEYOFFER inbox │ │ │ │ │ (key sharing) │ │ │ │ └──────────────────┘ │ └──────────────────────────────┼───────────────────────────────────────────┘ │ Socket.IO (WSS) │ Layer 1: TLS (public CA or System CA) │ Layer 2: bidirectional nonce exchange ▼ ┌────────────────────────┐ │ pttclient (Android) │ │ minSdk 19 │ │ Conscrypt JCE │ │ Android Keystore │ └────────────────────────┘ ``` ## Component Responsibilities ### pttclient (Android, minSdk 19) The client app is distributed to end users by the vendor. It is responsible for: - Generating the device RSA keypair in Android Keystore on first run (or software-backed on API 19–22). - Deriving `DeviceUUID = SHA-256(public key DER)[0:16]`. - Performing first-run PAS attestation to obtain a Device Certificate. - Establishing a Socket.IO connection to the active ptt-server. - Completing Layer 1 TLS validation and Layer 2 bidirectional nonce exchange. - Capturing audio, Opus-encoding it, encrypting with AES-256-GCM, and emitting `voice_data`. - Receiving and decrypting incoming `voice_data` and playing it through the speaker. - Managing a list of known Systems and Servers, switchable at runtime without rebuilding. ### ptt-server (Node.js + Socket.IO) The real-time server handles the bulk of PTT protocol logic. It is responsible for: - Accepting Socket.IO connections and completing authentication (Layer 2 nonce exchange). - Verifying device UUID derivation from the presented public key. - Emitting `server_challenge` — a nonce signed with the server's System CA-issued identity key. - Optionally requiring and validating `client_proof` (device certificate + nonce signature). - Routing `voice_data` between devices in the same talkgroup room. - Routing text messages and call setup signals. - Resolving group types locally via tier ranges (no backend lookup required for affiliation). - Caching group key share offers in Redis for offline delivery (`KEYOFFER::` keys with TTL). - Serving the System CA certificate at `GET /system-root-ca.crt` for QR-code-based onboarding. ### ptt-backend (REST API) The backend is the system-of-record. It is responsible for: - Storing device records (UUID, public key, assigned talkgroup). - Storing talkgroup definitions (ID, label, type, assigned device for private-type TGs). - Providing talkgroup lookup (`GET /talkgroups/:id`) called by ptt-server on every `affiliate`. - Providing device lookup (`GET /devices/:uuid`) and talkgroup lookup (`GET /talkgroups/:id`) for backend-integrated deployments. - Registering newly seen devices via `POST /devices/initialize`. - Storing system configuration (system name, etc.). > **Note:** In current DNI-mode deployments the ptt-server performs all routing without calling ptt-backend on connect, affiliate, or squawk. ptt-backend integration is preserved for backend-assigned private talkgroup (`P` type) lookups and admin workflows. --- ## Data Flow Summary ### Connection Establishment ``` pttclient ptt-server │ TCP + TLS handshake │ │ ─────────────────────────► │ │ │ │ Socket.IO connect │ │ ?dni=<16-digit DNI> │ │ &publicKey= │ │ x-api-key: │ │ ─────────────────────────► │ │ │ Validate DNI derivation │ │ Validate Bootstrap JWT (if enabled) │ │ │ server_challenge │ │ { cert, sig, keyId } │ │ ◄───────────────────────── │ │ │ │ [Client validates cert │ │ chain + nonce sig] │ │ │ │ Socket.IO authenticate │ │ { dni, pubKey, sig } │ │ ─────────────────────────► │ │ │ Verify sig locally (no backend) │ │ │ register_ok { dni } │ │ update_talkgroup │ │ { talkgroup_id: } │ │ ◄───────────────────────── │ ``` ### Voice Flow ``` Sender pttclient ptt-server Receiver pttclient │ PTT button down │ │ │ Opus encode frame │ │ │ AES-256-GCM encrypt │ │ │ emit voice_data (v2) │ │ │ ─────────────────────────► │ │ │ │ socket.to(room) │ │ │ emit voice_data ─────►│ │ │ │ │ │ Decrypt + decode │ │ Play on speaker ``` --- ## PKI Overview The PKI hierarchy has three tiers: ``` Platform Root CA (vendor, offline, air-gapped) └── Platform Issuing CA (vendor, Vault PKI) ├── Bootstrap Certificates (one per app build) ├── Device Certificates (one per physical device) └── System CAs (one per operator deployment) ├── Server Identity Certificates (one per ptt-server) └── Backend Server Certificates (one per ptt-backend) ``` Client trust is anchored to System CA certificates, bundled in the APK at build time or imported at runtime. Device authenticity is anchored to the Platform Issuing CA. See `pki/PKI-PTT-ARCH-001.md` for the full specification.