diff --git a/help4bis-claude-notes/remaining-work.md b/help4bis-claude-notes/remaining-work.md index ee443c7..abeeecb 100644 --- a/help4bis-claude-notes/remaining-work.md +++ b/help4bis-claude-notes/remaining-work.md @@ -1,46 +1,66 @@ -## Remaining Work — Priority Order +## Remaining Work — M8Chat App2 (2026-04-11) -### P0 — LiveKit E2EE frame encryption (BLOCKING video calls) -- [ ] Enable AES-GCM frame encryption in LiveKit Flutter SDK to match Element X -- Element X publishes media with `encryption: GCM`, app2 publishes `encryption: NONE` -- Without matching encryption, remote video renders as scrambled garbage -- Check livekit_client docs for `E2EEOptions` / `FrameCryptorFactory` on web -- May need to pass shared key material derived from the MatrixRTC session -- **Start here next session**: read livekit_client 2.4.0 source for E2EE setup on web +### P0 — Must test immediately (next session) +- [ ] **Test video call with E2EE + COOP/COEP** — COOP/COEP headers are now on the server, E2EE is re-enabled in code. Start a call from app2 → Element X mobile. Watch console for: + - `[E2EE] Received encryption key(s) from @user` — means key exchange worked + - `worker error` — means SharedArrayBuffer still not available (COOP/COEP not working) + - Scrambled video — key exchange format mismatch with Element X +- [ ] **Test hangup termination** — end call from app2, verify Element X sees call ended +- [ ] **If E2EE worker still crashes**: the COOP/COEP headers may break other things (e.g. loading cross-origin resources like Jitsi external_api.js, cached images). Test all features after enabling COEP. -### P1 — Incoming call detection from Element X -- [ ] Element X sends MSC3401 `org.matrix.msc3401.call.member` state events (already in hidden events list) -- [ ] App currently listens for old `m.call.invite` events in matrixrtc_repository.dart -- [ ] Need to detect call.member state changes and show incoming call overlay -- The state event format includes `memberships[]` with `foci_active[].type: livekit` +### P1 — Important fixes +- [ ] **Incoming call detection** — MSC3401 state event listener. When Element X starts a call, app2 should show an incoming call UI. Currently nothing happens. +- [ ] **Ghost device cleanup** — Each web login creates a new device. Need either: (a) periodic admin API cleanup, (b) logout deletes the device, or (c) cron job to purge old M8Chat devices. +- [ ] **Rooms provider performance** — Room list rebuilds on every sync tick (15+ times visible in console). Should debounce or only rebuild on actual changes. +- [ ] **Device ID for APK/iOS** — When building native apps, re-enable session persistence and device ID reuse. The secure_storage.dart scaffold exists but is currently neutered for web. -### P2 — Cleanup and polish -- [ ] Remove debug logging from rooms_repository.dart (debugPrint of all rooms on every sync) -- [ ] Fix avatar 404s — switch to authenticated media API (/_matrix/client/v1/media/) -- [ ] Clean up 20 ghost devices for @try user on server (DELETE via admin API) -- [ ] Remove diagnostic Olm logging from index.html (console.log statements) -- [ ] Remove debug prints from auth_repository.dart (encryptionEnabled logging) +### P2 — Quality improvements +- [ ] **Noto emoji font** — Add NotoColorEmoji font asset to render emoji in room names (currently shows squares) +- [ ] **Consolidate key restore dialogs** — key_restore_dialog.dart and security_setup_dialog.dart overlap. The security setup already does key restore. +- [ ] **Voice-only calling** — LiveKit supports audio-only but no UI for it yet +- [ ] **Cross-signing verification UX** — The Bootstrap flow creates cross-signing keys but there's no UI for verifying other users' devices (emoji comparison) -### P3 — Voice calling -- [ ] Test voice-only calls (same LiveKit flow, just no video track) -- [ ] Likely same E2EE issue as video — fix P0 first +### P3 — Future features +- [ ] **Push notifications** (Phase 2) +- [ ] **Room search** (Phase 2 — placeholder in AppBar) +- [ ] **Message reactions** (partial — display works, sending not implemented) +- [ ] **File/image upload** (attachment button exists, handler not wired) +- [ ] **Read receipts** (partial implementation) -### P4 — Cross-signing (Phase 2) -- [ ] Device verification to remove red exclamation in Element -- [ ] Profile screen hooks for verify/cross-sign +### Blockers / dependencies +- **E2EE video interop** depends on: (1) COOP/COEP working, (2) m.rtc.encryption_keys format matching Element X. If format doesn't match, need to capture what Element X actually sends (check to-device events on Synapse during a test call). +- **COEP may break cross-origin loads** — CachedNetworkImage, Jitsi external API, and avatar images from matrix.m8chat.au may fail with `require-corp`. May need `credentialless` instead of `require-corp`, or add `crossorigin` attributes. -### Build and deploy commands +### Commands to resume ```bash cd /srv/wp-dev/pwa-sites/m8chat-app2 -dart analyze --fatal-infos + +# Build flutter build web --release -rsync -avz --delete --exclude='.htaccess' --exclude='.ftpquota' \ - -e "ssh -p 2233 -i ~/.ssh/m8chat_prod" \ - build/web/ m8chat@app.m8chat.au:public_html/app2.m8chat.au/ + +# Deploy +rsync -avz --delete --exclude='.htaccess' \ + -e "ssh -i ~/.ssh/m8chat_prod -p 2233" \ + build/web/ m8chat@app.m8chat.au:~/public_html/app2.m8chat.au/ + +# Analyse +dart analyze lib/ + +# Regenerate Riverpod/Freezed code +dart run build_runner build --delete-conflicting-outputs + +# Check Synapse DB +ssh -i ~/.ssh/m8chat_key -p 2233 m8chat_help4bis@chat.m8chat.au \ + "PGPASSWORD=kijPt4cPWkoaZk8BVm psql -h localhost -U synapse_user -d synapse" + +# Check deployed .htaccess (COOP/COEP headers) +ssh -i ~/.ssh/m8chat_prod -p 2233 m8chat@app.m8chat.au \ + "cat ~/public_html/app2.m8chat.au/.htaccess" ``` -### Next session should start with -1. Read these claude-notes -2. Research LiveKit E2EE on Flutter web — check `livekit_client` package for `E2EEOptions`, `FrameCryptor`, `KeyProvider` -3. Check if Element X derives the E2EE key from the MatrixRTC session or uses a separate mechanism -4. Implement and test — the scrambled video fix is the most impactful single change +### What next session should start with +1. `/catchup` to load these notes +2. Test video call: app2 → Element X. Paste console output. +3. If E2EE works → commit everything to Gitea +4. If E2EE fails → check COEP compatibility issues, may need `credentialless` mode +5. If hangup works → move to P1 (incoming call detection) \ No newline at end of file