Add senderId to ConvoOutcome::Content

This commit is contained in:
Jazz Turner-Baggs
2026-07-21 12:04:21 -07:00
parent d3495db1da
commit 1efb377de7
6 changed files with 68 additions and 4 deletions
@@ -13,6 +13,7 @@ use std::collections::VecDeque;
use tracing::debug;
use crate::conversation::ConversationIdRef;
use crate::conversation::mls_utils::signer_for_sender;
use crate::inbox_v2::MlsProvider;
use crate::service_context::{ExternalServices, ServiceContext};
@@ -263,6 +264,9 @@ impl<S: ExternalServices> Convo<S> for GroupV1Convo {
.process_message(&cx.mls_provider, protocol_message)
.map_err(ChatError::generic)?;
// Sender Id is not validated, the AuthService/Client is responsible for validating that the credential
// is valid for the sender
let sender_id = signer_for_sender(&self.mls_group, &processed)?;
let cred_bytes = processed.credential().serialized_content().to_vec();
let content = match processed.into_content() {
@@ -271,6 +275,7 @@ impl<S: ExternalServices> Convo<S> for GroupV1Convo {
cx.causal.on_receive(&self.convo_id, &reliable);
Some(Content {
bytes: reliable.content.to_vec(),
sender_id,
encoded_credential: cred_bytes,
})
}
@@ -471,7 +471,8 @@ impl GroupV2Convo {
payload: Some(app_message::Payload::ConversationMessage(cm)),
}) => Some(Content {
bytes: cm.message.clone(),
encoded_credential: cm.sender.clone(),
sender_id: cm.sender.as_slice().into(),
encoded_credential: cm.sender_credential.clone(),
}),
_ => None,
});
@@ -0,0 +1,27 @@
use openmls::{
framing::{ProcessedMessage, Sender},
group::MlsGroup,
};
use crate::{ChatError, SignerId};
pub fn signer_for_sender(
mls_group: &MlsGroup,
processed: &ProcessedMessage,
) -> Result<SignerId, ChatError> {
// The signature key openmls just verified this message under.
let sender_sig_key: Vec<u8> = match processed.sender() {
Sender::Member(leaf_index) => {
mls_group
.member_at(*leaf_index)
.ok_or_else(|| ChatError::generic("sender leaf not in tree"))?
.signature_key
}
// Application/private messages always come from a Member; anything else
// here is a protocol violation.
other => {
return Err(ChatError::generic(format!("unexpected sender: {other:?}")));
}
};
Ok(sender_sig_key.into())
}
+1 -1
View File
@@ -28,10 +28,10 @@ pub use outcomes::{
Content, ConversationClass, ConvoOutcome, InboxOutcome, NewConversation, PayloadOutcome,
};
pub use service_context::ExternalServices;
pub use shared_traits::{IdentId, IdentIdRef, IdentityProvider};
pub use service_traits::{
AuthResult, AuthVerifyService, DeliveryService, RegistrationService, WakeupService,
};
pub use shared_traits::{IdentId, IdentIdRef, IdentityProvider, SignerId};
pub use storage::{ChatStore, ConversationKind};
pub use types::{AddressedEnvelope, ConvoMetadata};
pub use utils::{hex_trunc, trunc};
+2 -2
View File
@@ -8,13 +8,13 @@
use storage::ConversationKind;
use crate::SignerId;
use crate::conversation::ConversationId;
#[derive(Debug, Clone)]
pub struct Content {
pub bytes: Vec<u8>,
/// Hex-encoded [`DelegateCredential`] of the sender, if present in the message.
/// Empty when the sender did not attach a credential.
pub sender_id: SignerId,
pub encoded_credential: Vec<u8>,
}
+31
View File
@@ -27,6 +27,37 @@ impl AsRef<str> for IdentId {
}
}
#[derive(Debug, Clone)]
pub struct SignerId(Vec<u8>);
impl SignerId {
pub fn from_ed25519(key: &Ed25519VerifyingKey) -> Self {
Self(key.as_ref().to_vec())
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_slice()
}
}
impl From<Vec<u8>> for SignerId {
fn from(value: Vec<u8>) -> Self {
Self(value)
}
}
impl From<&[u8]> for SignerId {
fn from(value: &[u8]) -> Self {
Self(value.to_vec())
}
}
impl AsRef<[u8]> for SignerId {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
/// Represents an external Identity
/// Implement this to provide an Authentication model for users/installations
pub trait IdentityProvider {