- Ya
- 26 Agosti 2026, 02:33 UTC
- Mwandishi
- kamo
- Ahadi ya
- a04da73
The softphone opened its SockJS/STOMP connection to media.<domain> unconditionally at boot. getCapabilities() is awaited a few lines above and is the backend's own answer to "can this org take calls", but the socket was set up outside that gate — so a member of an org with no phone system configured opened the connection anyway, paid its /info XHR, and then held it open with a heartbeat pair every 20 s, per tab, for events that could never arrive. It is now inside `if (caps?.voiceCalls)`. Deliberately its own block rather than folded into the SIP-credentials gate above it: that one early-returns when the credential fetch fails, and a voice-enabled org should still get the socket even when registration could not be established. The boot sequence also fetched /api/user-info directly, making it the seventh independent caller of that endpoint on a cold authed load — each one a Redis EXISTS + SETEX plus a SecurityService rights recompute. It goes through loadUserInfoShared now, the coalescer that already existed in useUserInfo, exported for callers outside the hook. Reaching it from a plain effect rather than consuming useUserInfo() is deliberate: the hook would add another 5-minute refresh interval and another visibilitychange listener for an answer the softphone needs once, at boot. That swap also fixes something quieter. The raw fetch sent no X-***-Token, so it leaned on the cookie jar rather than naming the session this TAB holds; the shared loader reads the tab's own token. And when there is no session it now returns instead of carrying on — the old path turned a 401 body into String(undefined) and initialised a softphone for member "undefined". Deliberately NOT done: collapsing the five STOMP connections onto shared clients. Three go to one identical URL and two to another, so there is real waste there, but the notification and email sockets have materially different retry budgets and give-up policies — sharing them would make notifications strictly less resilient to buy some frames. That needs a connection registry with per-subscriber retry semantics, not a merge. Verified: tsc --noEmit clean over useSoftphone, useUserInfo, SoftphoneContext and SoftphonePanel with their transitive imports; no import cycle introduced; all 9 guards pass, including check-session-token-source; 29 voip and session tests pass.