Mobile Client Implementation Guide
Source of truth:
d3chat/frontend/src/store/*.tsd3chat/frontend/src/crypto/*.tsd3chat/backend/app/routers/*.pyd3chat/backend/app/websocket/*.py
This guide defines a practical mobile implementation contract so a native app can be built with no repository context.
Required Feature Phases
Phase 1 - Auth and Session
Implement:
- register/login flows
- token storage and refresh rotation
- logout + logout-all
- websocket ticket acquisition and connection
Acceptance criteria:
- app survives process restart with session restore
- 401 triggers refresh once then clean logout
Phase 2 - Core Messaging
Implement:
- channel list
- message pagination (
before,limit) - send/edit/delete
- typing indicators and membership list
Acceptance criteria:
- no duplicate messages on ws + HTTP merge
- pagination stable under high volume
Phase 3 - Encryption
Implement:
- device key bootstrap (
/keys/upload) - OTP replenishment (
/keys/one-time) - DM encryption via X3DH setup endpoints
- group encryption via sender keys and ratchet
Critical note:
- sender-key decryption must be sequential per sender device due to ratchet semantics.
Phase 4 - Admin Surfaces (optional per app role)
Implement for admin-capable builds:
- dashboard stats and analytics
- user moderation
- channel moderation
- settings read/update
- audit log viewer
Local Persistence Contract
Persist at minimum:
access_tokenrefresh_tokendevice_iduser_id
And local crypto material equivalent to web IndexedDB key store:
- identity key pair
- signed pre-key
- signing key pair
- one-time prekeys
- session keys per DM channel
- sender chain keys per
(channel_id, sender_device_id) - plaintext cache by message id (important for own sender-key messages)
Realtime Integration Pattern
Startup
- restore tokens
- fetch
/users/me - connect websocket via ticket
- load channels
- load active channel messages
On channel.new
- insert/update channel list
- optionally auto-subscribe explicitly using
subscribeevent
On message.new
- dedupe by
message.id - decrypt based on
channel.encryption_type - append chronologically
API Sequencing for DM Encryption
For first DM message in a channel:
- fetch members of DM
- fetch recipient key bundles
- establish initiator X3DH session
- store setup data
/keys/channels/{id}/x3dh-setup - encrypt and send message with
protocol_version=2
Responder path:
- fetch setup data from endpoint
- derive responder session
- decrypt payload
API Sequencing for Group Encryption
- ensure sender key exists locally
- if missing, generate and POST
/keys/channels/{id}/sender-keys - encrypt with ratcheted message key
- send message with
protocol_version=2andsender_device_id - on receive, decrypt sequentially by sender device
Known Edge Cases
- Own sender-key messages may be undecryptable if plaintext cache was lost, because ratchet is one-way.
- Federation-discovered users may appear after lookup and need local identity normalization.
- Network retries for message send should avoid duplicate submission unless server idempotency key is introduced.
- Background reconnect should back off exponentially.
Test Checklist for Mobile Readiness
- Fresh install, register, restart app, session restored.
- Two-device same user receives
channel.newupdates. - DM first-message encryption/decryption succeeds both directions.
- Group message order maintained across reconnect.
- OTP low warning handling path (listen for
keys.low_otp). - Admin moderation actions reflected in UI and enforceable on subsequent login.