# 03 — Architecture map (for agents) ## Bounded contexts (product client) See `toju-app/src/app/domains/README.md`. Emergency-relevant domains: | Domain | Owns | |--------|------| | `authentication` | Login/register HTTP, provision secret, per-URL credentials, authorize navigation | | `server-directory` | Endpoints, health, discovery, invites, room metadata affinity | | `chat` | Message rules, sync rules, chat UI | | `direct-message` | DMs, friends, offline queue, PeerDelivery usage | | `direct-call` | Private call sessions / rings | | `voice-session` | Join/leave bookkeeping, floating controls, settings storage | | `voice-connection` | Facade over realtime for mic/camera/playback/VAD | | `screen-share` | Picker / quality | | `attachment` | Chunked P2P files | | `access-control` | Permissions / bans | **Infrastructure (not a domain):** `infrastructure/realtime/` (WebRTC + signaling), `infrastructure/persistence/`, `infrastructure/mobile/`. **Global NgRx:** `store/users`, `store/rooms`, `store/messages` — orchestration across domains. --- ## Identity & credentials ``` Home profile (NgRx User) id / username / displayName / homeSignalServerUrl │ ├─ AuthTokenStore (legacy per-URL token) metoyou.authTokens ├─ SignalServerCredentialStore metoyou.signalServerCredentials │ { serverUrl → userId, token, provisioned? } └─ ProvisionSecretStore (per home user id) Electron safeStorage | web sessionStorage ``` **Actor resolution for a room:** `SignalServerAuthService.resolveActorUserIdForServer(sourceUrl, homeOderId)` — foreign URL must use provisioned `userId`. **Identify on socket:** `SignalingTransportHandler.getIdentifyCredentialsForSignalUrl(url)` must resolve token+actor for that URL (store fallback). **Danger:** `getIdentifyCredentials()` returns **home** credential — used for some localOderId / polite-peer paths → cross-signal initiator bugs (`06`, `09`). --- ## Room ↔ signal affinity ``` Room { id, channels[], sourceUrl, sourceId, ... } │ ▼ RoomSignalingConnection ensureCredentialForServerUrl(sourceUrl) identify(actor for sourceUrl) join_server / view_server on that WS │ ▼ ServerSignalingCoordinator maps serverId ↔ signalUrl ↔ peers ``` Fallback: try other online compatible endpoints on outage; **do not** treat Cloudflare 521/522 as “client incompatible”. Non-federated: peers must converge on same endpoint for that room. --- ## Realtime composition root `WebRTCService` (`realtime-session.service.ts`) wires: - `SignalingTransportHandler` → many `SignalingManager` (one WS per URL) - `PeerConnectionManager` → negotiation, DC, recovery - `MediaManager` / noise / screen share - `WebRtcStateController` (signals) Inbound WS → `SignalingMessageHandler` → users/rooms/voice/chat effects. --- ## Message send path (server channel) ``` Composer → MessagesActions.sendMessage({ id? }) → local DB + NgRx → DC broadcast chat-message (+ message-revision) → WS chat_message fallback (room members) → account_sync to sibling devices ``` Receive gates: room must be current or saved; channel scoping for text. --- ## Voice join path ``` UI join channel → VoiceSessionFacade startSession → leave previous exclusive target → enableVoice / heartbeat → voice_state on WS (+ DC control) → MediaManager.syncVoiceRouting (same channel only) → VoicePlaybackService for remote same-channel peers ``` Peer PC may already exist from presence mesh; join mainly attaches tracks + announces state. --- ## Call / DM delivery path ``` DirectCallService / DirectMessageService → PeerDeliveryService 1) data channel if open 2) signaling forward (targetUserId) 3) offline queue (DM) / silent fail (call if ignored) ``` Inbound call admission: `direct-call-participant-identity.rules.ts` (aliases — implemented). Outbound routable id pick: **documented in LESSONS as fixed; symbols not in tree** — see `10-code-lies`. --- ## Recovery constants (cheat sheet) | Constant | Value | |----------|-------| | WS reconnect backoff | 1s → 30s | | Connect timeout | 5s | | Keepalive interval / ack timeout | 25s / 10s | | Health probe | 5s | | Peer disconnect grace | 10s | | Peer reconnect | 5s × 12 then silent abandon | | DC recovery grace (closing) | 2.5s | | Non-initiator give-up | 5s | | Offer-sent grace | 20s | | Inventory / full sync limit | 20_000 | | Sync batch | 200 | | Sync poll | 10s fast / 15 min slow | Source: `realtime.constants.ts`, `message-sync.rules.ts`. --- ## Server responsibilities (only when needed) Default agent scope excludes `server/` unless packet expands. Know this: - Serializes WS handlers per connection (identify-before-join). - Relays RTC only when peers share membership (DM types exempt). - No message persistence. - `voiceActive` routes offers to owning connection. Canonical envelopes: `agents-docs/features/signaling.md`.