max / makenotwork
| 1 | //! Live chat shared by Multithreaded forums and MNW stream pages. |
| 2 | //! |
| 3 | //! Design + decisions: maintainer wiki. |
| 4 | //! <!-- wiki: livechat-design --> |
| 5 | //! |
| 6 | //! A thin crate. It owns the message and event vocabulary, bounded retention, |
| 7 | //! and (as they land) the hub and SSE transport. It owns no schema, no authz, and |
| 8 | //! no moderation policy: those arrive through four traits the host implements, so |
| 9 | //! Multithreaded can gate on `CommunityScope` and the MNW server on |
| 10 | //! `SubscriptionGate` without either concept appearing here. |
| 11 | //! |
| 12 | //! # Shape |
| 13 | //! |
| 14 | //! SSE downstream, plain `POST` upstream. Not a WebSocket. The upstream volume is |
| 15 | //! one request per message typed, so bidirectionality buys nothing, and a `POST` |
| 16 | //! passes through the CSRF, rate-limit, and session middleware both apps already |
| 17 | //! run. It also avoids adding a `connect-src` CSP directive on the Multithreaded |
| 18 | //! side, which currently has none. |
| 19 | //! |
| 20 | //! # Ephemeral, but written down |
| 21 | //! |
| 22 | //! Chat in both consumers expires. Messages are stored anyway, for two reasons: |
| 23 | //! a deploy is a symlink swap plus a restart with no connection draining, so |
| 24 | //! every client reconnects and needs its backlog replayed from a cursor; and |
| 25 | //! moderation has to be able to reach a message that already scrolled past. |
| 26 | //! |
| 27 | //! [`Retention`] makes the bound un-opt-out-able. There is no `Option`, no |
| 28 | //! "forever" sentinel, and no public field: the only constructor rejects anything |
| 29 | //! over the crate ceilings. |
| 30 | //! |
| 31 | //! # Not here, on purpose |
| 32 | //! |
| 33 | //! No presence, no typing indicators, no edit path, and no link previews. The |
| 34 | //! first two are the largest drivers of event volume against a hard 512M cgroup |
| 35 | //! cap where an OOM restarts the whole site. Edit is surface with no benefit in a |
| 36 | //! stream nobody re-reads. Link previews would point a server-side fetcher at |
| 37 | //! unreviewed user input at chat volume, which is a much hotter SSRF surface than |
| 38 | //! the forum-post path it would borrow. |
| 39 | |
| 40 | |
| 41 | |
| 42 | |
| 43 | |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | |
| 55 | pub use ; |
| 56 | pub use ; |
| 57 | pub use ChatEvent; |
| 58 | pub use ; |
| 59 | pub use ; |
| 60 | pub use ; |
| 61 | pub use ; |
| 62 | pub use ; |
| 63 | pub use ; |
| 64 | pub use SendRejection; |
| 65 | |
| 66 | pub use ; |
| 67 | pub use ChatStream; |
| 68 | pub use |
| 69 | ChatAuthz, ChatIdentity, ChatModeration, ChatRooms, DenyReason, Identity, WriteAccess, |
| 70 | ; |
| 71 |