de_mls/core/conversation_plugins.rs
1//! [`ConversationPluginsFactory`] trait — bundle of per-conversation plug-in
2//! types plus the construction methods for each, *plus* the
3//! identity-bound `generate_key_package` entry that joiners use before
4//! any conversation exists. The trait lives in `core` so
5//! [`crate::core::ConversationHandle`] can take a single bundle parameter
6//! rather than several independently-bounded type parameters;
7//! integrators implement it once to swap any of the per-conversation
8//! plug-ins.
9
10use crate::{
11 core::{PeerScoringPlugin, ScoringConfig, StewardListConfig, StewardListPlugin},
12 mls_crypto::{KeyPackageBytes, MlsError, MlsService},
13};
14
15/// Per-conversation plug-in bundle. One trait carries the three plug-in
16/// types (`Mls`, `Scoring`, `StewardList`) plus the construction methods
17/// for each. Identity is intentionally **not** part of this bundle — it
18/// lives parallel to the conversation registry as `Arc<dyn Identity>` on
19/// `User`.
20pub trait ConversationPluginsFactory {
21 type Mls: MlsService;
22 type Scoring: PeerScoringPlugin;
23 type StewardList: StewardListPlugin;
24
25 /// Build an MLS service for a brand-new conversation as its sole creator.
26 fn create_mls(&self, conversation_id: String) -> Result<Self::Mls, MlsError>;
27
28 /// Try to build an MLS service from a serialized MLS welcome.
29 /// Returns `Ok(None)` when the welcome isn't for us.
30 fn welcome_mls(&self, welcome_bytes: &[u8]) -> Result<Option<Self::Mls>, MlsError>;
31
32 /// Build a fresh peer-scoring plug-in for a new conversation runner.
33 fn make_scoring(&self, config: &ScoringConfig) -> Self::Scoring;
34
35 /// Build a fresh steward-list plug-in for a new conversation runner.
36 /// Returns an empty plug-in; the lifecycle creator path bootstraps it
37 /// via [`StewardListPlugin::install_list`].
38 fn make_steward_list(
39 &self,
40 conversation_id: &[u8],
41 config: StewardListConfig,
42 ) -> Self::StewardList;
43
44 /// Mint a single-use key package. Identity-bound (not
45 /// conversation-bound): joiners publish a KP before any conversation
46 /// exists, so this method takes no `conversation_id`.
47 fn generate_key_package(&self) -> Result<KeyPackageBytes, MlsError>;
48}