Skip to main content

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}