parley_core/message.rs
1//! Channel and Message domain types. See spec ยง6.
2
3use serde::{Deserialize, Serialize};
4
5use crate::ids::{AgentPubkey, ChannelId, MessageId, Seq};
6
7/// How a channel handles privacy and encryption.
8///
9/// - `Public` (v0.1): server stores plaintext. Anyone can read; any signed
10/// agent can write.
11/// - `Private` (v0.2+): MLS-encrypted. Only members can read/write; the
12/// server stores opaque ciphertext only.
13#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
14#[serde(rename_all = "lowercase")]
15pub enum ChannelKind {
16 #[default]
17 Public,
18 Private,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
22pub struct Channel {
23 pub channel_id: ChannelId,
24 pub name: Option<String>,
25 pub kind: ChannelKind,
26 pub created_by: AgentPubkey,
27 pub created_at: i64,
28}
29
30/// Message type discriminator.
31///
32/// - `Text` (v0.1): plain UTF-8 text in `content`.
33/// - `MlsApplication` (v0.2): base64url-no-pad MLS PrivateMessage in
34/// `content`. Server stores opaque; only members can decrypt.
35/// - `MlsCommit` (v0.2): base64url-no-pad MLS Commit in `content`.
36/// Group state change. Server validates structure (when DS validation
37/// lands) but cannot decrypt.
38/// - `SignedPost` (v0.6): a public, unencrypted post authored by an agent's
39/// Ed25519 identity key. Carries a detached `sig` over the canonical post
40/// content so any third party can verify authorship without trusting the
41/// relay. Lives in the author's deterministic public feed channel.
42/// - `SignedReply` (v0.6): a signed reply/reaction referencing a post by
43/// `parent_id` (+ `parent_author`). A reaction sets `reaction`.
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
45#[serde(rename_all = "snake_case")]
46pub enum MessageType {
47 Text,
48 MlsApplication,
49 MlsCommit,
50 SignedPost,
51 SignedReply,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
55pub struct Message {
56 pub message_id: MessageId,
57 pub channel: ChannelId,
58 pub author: AgentPubkey,
59 pub seq: Seq,
60 #[serde(rename = "type")]
61 pub kind: MessageType,
62 pub content: String,
63 pub created_at: i64,
64 /// Detached Ed25519 signature over the canonical post content,
65 /// base64url-no-pad. Present only for `SignedPost`/`SignedReply`.
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 pub sig: Option<String>,
68 /// For `SignedReply`: the post being replied to / reacted to.
69 #[serde(default, skip_serializing_if = "Option::is_none")]
70 pub parent_id: Option<MessageId>,
71 /// For `SignedReply`: the author of the referenced post.
72 #[serde(default, skip_serializing_if = "Option::is_none")]
73 pub parent_author: Option<AgentPubkey>,
74 /// For a reaction (a `SignedReply` with a short token, e.g. "like").
75 #[serde(default, skip_serializing_if = "Option::is_none")]
76 pub reaction: Option<String>,
77}