de_mls/core/events.rs
1//! I/O contract between the protocol layer and an integrator.
2//!
3//! Two channels:
4//!
5//! - [`SessionEvent`] — fire-and-forget notifications about a single
6//! conversation. Each [`crate::app::SessionRunner`] owns a broadcast sender;
7//! integrators subscribe per session.
8//! - [`ConversationLifecycle`] — User-level create/remove notifications.
9//! Integrators use this to discover new sessions and subscribe to them.
10//!
11//! Synchronous outbound transport is supplied by
12//! [`crate::ds::DeliveryService`], passed to `User` at construction and
13//! cloned into each session.
14
15use hashgraph_like_consensus::types::ConsensusEvent;
16
17use crate::{
18 core::ConversationState,
19 protos::de_mls::messages::v1::{AppMessage, ConversationUpdateRequest},
20};
21
22/// Per-conversation notification. Sessions append these to their pending
23/// buffer; integrators drain via
24/// [`crate::app::SessionRunner::drain_events`] once per polling cycle. All
25/// variants are fire-and-forget — no failure path back to the session.
26#[derive(Debug, Clone)]
27pub enum SessionEvent {
28 /// Decrypted application message (chat, vote request, proposal
29 /// notification, ban request, …).
30 AppMessage(AppMessage),
31
32 /// Welcome processed and MLS state initialised. Epoch timers + state
33 /// transitions are already wired — surface to UI only.
34 Joined,
35
36 /// The user is out of this conversation (self-leave commit merged, or
37 /// someone else removed us). The session entry is about to be removed
38 /// from `User`'s registry.
39 Leaving,
40
41 /// A background operation (e.g., vote submission) failed. UI may surface;
42 /// state has already been reconciled.
43 Error { operation: String, message: String },
44
45 /// The local user just submitted `request` as a new proposal with the
46 /// creator's vote bundled. UI should record for history; no "please vote"
47 /// affordance.
48 OwnProposalSubmitted {
49 proposal_id: u32,
50 request: ConversationUpdateRequest,
51 },
52
53 /// A freeze round merged a commit; `batch` is the set of approved
54 /// proposals that landed in this commit (in insertion order).
55 CommitApplied(Vec<ConversationUpdateRequest>),
56
57 /// Conversation transitioned into `state`.
58 PhaseChange(ConversationState),
59
60 /// A consensus session reached an outcome. Fired after the runner has
61 /// applied the result to local state.
62 ProposalDecided(ConsensusEvent),
63}
64
65/// User-level conversation lifecycle event. Appended to [`crate::app::User`]'s
66/// pending buffer; integrators drain via
67/// [`crate::app::User::drain_lifecycle_events`] once per polling cycle and
68/// use `Created` as the trigger to begin draining per-session
69/// [`SessionEvent`]s.
70#[derive(Debug, Clone)]
71pub enum ConversationLifecycle {
72 /// A new conversation entry has been registered. The session is in the
73 /// registry; the integrator can look it up and `subscribe()` to its
74 /// per-session events.
75 Created(String),
76
77 /// A conversation entry has been removed from the registry.
78 Removed(String),
79}