supercode-harness 0.5.148

The optional native Volter Harness agent and tool harness
Documentation
//! Filing: a sender that does not wait for its mail to arrive (a board's dispatcher, a script) writes the envelope
//! into the receiver's mailbox here and stops (docs/adr/0008-agent-mailbox.md, decision 17; D140). The write is local,
//! needs no network and is idempotent by the message id its key fixes. The mailbox delivers it from there: the
//! machine daemon's watch loop ([`crate::mail_watch::MailCarrier`]) hands it to its session by the session's own door,
//! or, for an address on another machine, carries it there through Teams and files it with the same wake.

use crate::mail_route::Caller;
use crate::mailbox::{mail_root, Envelope, MailAddress, MailKind, Mailbox, ReplyVia};

/// What a filing did.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Filed {
    /// The message's id (the one its key fixes, when it had one).
    pub message_id: String,
    /// Whether this filing wrote it; false when the id was already filed (a second filer, or a repeat).
    pub new: bool,
}

/// The id of a message `sender` sends under `key`: a key that is itself a whole message id (`m-` and 24 lowercase
/// hex digits) is that id, so a sender that chose it beforehand (a board blocking a card on the answer to the question
/// it is about to send) knows what the answer will name; any other key is hashed with the sender's address; no key is
/// a fresh id.
pub fn message_id_for(sender: &MailAddress, key: Option<&str>) -> std::io::Result<String> {
    Ok(match key {
        Some(key)
            if key.len() == 26
                && key.starts_with("m-")
                && key[2..]
                    .bytes()
                    .all(|byte| byte.is_ascii_hexdigit() && !byte.is_ascii_uppercase()) =>
        {
            key.to_string()
        }
        Some(key) => format!(
            "m-{}",
            &blake3::hash(format!("{sender}\0{key}").as_bytes()).to_hex()[..24]
        ),
        None => crate::mailbox::new_message_id()?,
    })
}

/// One message to file.
#[derive(Debug, Clone, Default)]
pub struct Filing {
    /// A short subject, separate from the body.
    pub subject: Option<String>,
    /// Idempotency key: filing again under it files nothing new.
    pub key: Option<String>,
    /// Ask the receiver to deliver it now (wake an idle session); false leaves it for the session's next turn.
    pub wake: bool,
}

/// File `body` from `caller` in the mailbox of `to`, on this machine's mail root whatever machine `to` names (mail for
/// another machine waits here until the watch loop has carried it there). A wake is requested only by the filing that
/// wrote the message, so a repeat never delivers it twice.
pub fn file(
    caller: &Caller,
    to: &MailAddress,
    body: &str,
    filing: &Filing,
) -> std::io::Result<Filed> {
    let mut envelope = Envelope::new(
        caller.address.clone(),
        caller.name.clone(),
        MailKind::Peer,
        ReplyVia::Command,
        body,
    )?;
    envelope.id = message_id_for(&caller.address, filing.key.as_deref())?;
    envelope.subject = filing.subject.as_deref().map(|value| {
        value
            .lines()
            .next()
            .unwrap_or("")
            .chars()
            .take(200)
            .collect()
    });
    let mailbox = Mailbox::open(&mail_root(), to)?;
    if mailbox.find(&envelope.id)?.is_some() {
        return Ok(Filed {
            message_id: envelope.id,
            new: false,
        });
    }
    mailbox.deliver(&envelope)?;
    if filing.wake {
        mailbox.request_wake(&envelope.id)?;
    }
    Ok(Filed {
        message_id: envelope.id,
        new: true,
    })
}