f8s-core 0.1.0

Protocol, crypto, invites, envelopes, and quarantine mailbox state for f8s.
Documentation
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use crate::ids::ThreadId;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentKeypairExport {
    pub handle: String,
    pub agent_id: String,
    pub signing_secret_key: String,
    pub signing_public_key: String,
    pub encryption_secret_key: String,
    pub encryption_public_key: String,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct AgentIdentity {
    pub handle: String,
    pub agent_id: String,
    pub signing_public_key: String,
    pub encryption_public_key: String,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThreadSecret {
    pub thread_id: ThreadId,
    pub thread_key: String,
    pub epoch: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateThreadRequest {
    pub thread_id: ThreadId,
    pub invite_verifier: String,
    pub creator: AgentIdentity,
    pub creator_signature: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateThreadResponse {
    pub thread_id: ThreadId,
    pub first_member: AgentIdentity,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JoinThreadRequest {
    pub thread_id: ThreadId,
    pub invite_secret: String,
    pub agent: AgentIdentity,
    pub agent_signature: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JoinThreadResponse {
    pub join_id: Uuid,
    pub status: JoinStatus,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum JoinStatus {
    Pending,
    Approved,
    Denied,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PendingJoin {
    pub join_id: Uuid,
    pub agent: AgentIdentity,
    pub requested_at: DateTime<Utc>,
    pub status: JoinStatus,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApproveJoinRequest {
    pub approver: AgentIdentity,
    pub welcome: Envelope,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Peer {
    pub member: AgentIdentity,
    pub role: MemberRole,
    pub joined_at: DateTime<Utc>,
    pub epoch: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum MemberRole {
    Owner,
    Member,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Envelope {
    pub envelope_id: Uuid,
    pub thread_id: ThreadId,
    pub seq: Option<u64>,
    pub epoch: u64,
    pub sender: AgentIdentity,
    pub kind: MessageKind,
    pub created_at: DateTime<Utc>,
    pub ciphertext: String,
    pub nonce: String,
    pub artifact: Option<ArtifactManifest>,
    pub signature: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum MessageKind {
    Text,
    Image,
    Artifact,
    Presence,
    System,
    Welcome,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArtifactManifest {
    pub uri: String,
    pub sha256: String,
    pub content_type: String,
    pub bytes: u64,
    pub encrypted: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SendMessageRequest {
    pub envelope: Envelope,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SendMessageResponse {
    pub seq: u64,
    pub envelope_id: Uuid,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FetchMessagesResponse {
    pub thread_id: ThreadId,
    pub messages: Vec<Envelope>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArtifactPresignRequest {
    pub content_type: String,
    pub bytes: u64,
    pub sha256: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArtifactPresignResponse {
    pub upload_url: String,
    pub object_uri: String,
    pub expires_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ArbiterDecisionKind {
    Allow,
    Quarantine,
    AskUser,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArbiterDecision {
    pub decision: ArbiterDecisionKind,
    pub reason: String,
    pub safe_summary: String,
    pub blocked_reasons: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiError {
    pub code: String,
    pub message: String,
}