# 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** | “I’m 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 | | “I’m 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.ts` — **not** `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//README.md` | | Known past bugs | `agents-docs/LESSONS.md` — verify symbols still exist (some lessons describe **desired** fixes as if shipped) |