Files
Toju/emergency-fix/01-product-overview.md
T
myxelium e49b3ec112 chore: dev-stack switches, shared e2e harness, and desktop shell rules
- `LIVE_RELOAD=false npm run dev` keeps the renderer alive across a machine
  suspend; the reload client otherwise destroys the session under test.
- `dev-peer.sh` plus a separate userdata dir runs a second local peer.
- `tools/voice-probe.js` samples peer state and RTP counters from a live
  window, persisting to localStorage so a renderer reload cannot erase it.
- e2e helpers for voice pairs, peer-role election, and a TURN relay.
- Electron single-instance and dev-client-load decisions move into rules
  files with colocated specs.
2026-08-14 03:19:29 +02:00

6.3 KiB
Raw Blame History

01 — Product overview (user + system)

What the user thinks this app is

Toju / MetoYou is a Discord-like desktop chat app with:

  • Accounts on a signal (signaling) server
  • Chat-servers (communities) with text channels and voice channels
  • Live text chat in those channels
  • Voice / camera / screen share in voice channels
  • Direct messages and private calls
  • Friends, profile cards, custom emoji, GIFs, file attachments
  • Multiple signal servers in the network settings (home + others)

The marketing promise implied by the product design:

Log in once. Join communities anywhere on the network. Chat and voice “just work.” Switching signal hosts should not feel like logging into a second product.


What the system actually is

Layer Role
Angular client (toju-app/) All UX, NgRx state, domain logic, WebRTC + WebSocket clients
Electron shell (electron/) Desktop window, SQLite persistence, IPC (window.api), provision-secret safeStorage, screen capture helpers
Signaling server (server/) Auth tokens, public server directory REST, WebSocket identify/join/presence, RTC offer/answer/ICE relay, narrow chat/DM/voice_state fallbacks, multi-device account_sync. Does not store chat history.
Web / Capacitor Same Angular app; weaker secret storage (sessionStorage); mobile voice/UI constraints

Transport split (critical mental model)

Transport What the user experiences What it actually carries
WebSocket to signal server “Im online / in this server / someone joined voice” Identity, room membership, presence, SDP/ICE relay, chat_message + DM fallbacks, voice_state, account_sync
WebRTC media Hearing / seeing people Mic, camera, screen tracks (never through the signal server)
WebRTC ordered data channel Messages syncing, files, emoji, many “live” features Chat events, inventory sync, attachments, avatar/emoji chunks, voice/screen control, plugin bus

If the socket is wrong or unauthenticated → user is invisible; no relay; chat fallback may fail.
If the data channel is dead → live text may still limp via chat_message, but history sync, attachments, emoji, many controls fail.
If media is routed wrong or peer never connects → voice UI lies (“In Voice”) with silence.


Core vocabulary (user ↔ engineering)

User says Engineering term
“My account / login” Home session on homeSignalServerUrl + local profile in SQLite/IndexedDB
“Another network / signal host” Foreign ServerEndpoint URL; needs per-URL credential
“A server / community” Saved Room (chat-server) with sourceUrl / sourceId = which signal hosts it
“Text channel / voice channel” Channels inside a room; text vs voice types
“Im in voice” Local VoiceSession + voice_state with isConnected + mic ownership via clientInstanceId
“DM / call someone” Direct-message conversation + optional direct-call session
“It logged me out” Often /login or /login?mode=authorize — may be foreign authorize, not true home logout

Multi-signal identity (the footgun)

  1. User registers on Signal A → home user id H.
  2. User later needs Signal B → client is supposed to auto-register/login with a local provision secret, creating actor id A_B on B (username may be suffixed).
  3. Peers on Signal B see the user as A_B, not H.
  4. WebRTC peer map keys, targetUserId on relay, DM conversation ids, and call participant lists may mix H and A_B.

Invariant the product claims: one human, one local profile, many per-server actor credentials — UX never asks for password again except last-resort authorize / real home expiry.

Invariant signaling claims: non-federated — peers in the same room must share the same signal endpoint to discover each other. Cross-room “same person” is a client-side identity problem.


Feature inventory (what “done product” includes)

Must work for a release-quality emergency fix:

  1. Home register / login / logout / session restore
  2. Silent foreign provision + Network settings badges
  3. Discover / create / join / leave chat-servers (public, password, invite, moderated)
  4. Text channels: send, edit, delete, react, typing, unread, sync after late join
  5. Voice channels: join/leave, mute/deafen, speaking indicators, multi-device takeover, move between channels
  6. Camera + screen share in voice / calls
  7. DMs + friends + delivery states
  8. Direct / group calls (ring, answer, decline, DND)
  9. Attachments over data channel
  10. Multi-device account_sync for saved rooms / chat batches / friends / avatar / emoji
  11. Endpoint health, version compatibility, room signal affinity + fallback

Secondary (do not block P0 voice/auth/chat): plugins, game activity, themes, KLIPY, link previews, experimental media.


Platforms

Platform Notes for bugs
Electron desktop Primary; provision secret in safeStorage; SQLite; best screen share
Browser sessionStorage provision secret dies with tab; IndexedDB
Capacitor mobile Auth routing, mic permissions, no reliable screen share; title bar hidden

Trust boundaries (short)

  • REST mutations and WS identify require bearer/session token per signal URL.
  • Actor user ids in request bodies are ignored server-side; token wins.
  • Message bodies are not E2E encrypted beyond DTLS on WebRTC and TLS on WS.
  • Signaling server is not the source of truth for chat history.

Where truth lives (for agents)

Kind of truth Prefer
Wire WebSocket types agents-docs/features/signaling.md + server/src/websocket/handler.tsnot shared-kernel/signaling-contracts.ts
Auth multi-server agents-docs/features/authentication.md + emergency-fix/04-*.md
Voice/WebRTC plumbing toju-app/.../realtime/README.md — verify against code (see 10-code-lies)
Domain UX toju-app/src/app/domains/<name>/README.md
Known past bugs agents-docs/LESSONS.md — verify symbols still exist (some lessons describe desired fixes as if shipped)