Skip to main content

max / makenotwork

2.7 KB · 71 lines History Blame Raw
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 mod chat;
41 mod error;
42 mod event;
43 mod hub;
44 mod ids;
45 mod message;
46 mod rate_limit;
47 mod retention;
48 mod room;
49 mod send;
50 #[cfg(feature = "axum")]
51 mod sse;
52 mod stream;
53 mod traits;
54
55 pub use chat::{Chat, SendRequest};
56 pub use error::{ChatError, LimitScope};
57 pub use event::ChatEvent;
58 pub use hub::{Hub, HubLimits, Subscription};
59 pub use ids::{MessageId, Nonce, RoomId, UserId};
60 pub use message::{MAX_MESSAGE_LEN, Message, MessageBody};
61 pub use rate_limit::{RateDecision, RateLimiter, RateLimits};
62 pub use retention::{MAX_AGE_CEILING, MAX_MESSAGES_CEILING, Retention};
63 pub use room::{Room, RoomState};
64 pub use send::SendRejection;
65 #[cfg(feature = "axum")]
66 pub use sse::{KEEPALIVE_INTERVAL, sse_response};
67 pub use stream::ChatStream;
68 pub use traits::{
69 ChatAuthz, ChatIdentity, ChatModeration, ChatRooms, DenyReason, Identity, WriteAccess,
70 };
71