Expand description
The mail4agent mailbox engine: participants, addressing, delivery,
acknowledgement and the storage boundary. No HTTP, no framework – see
mail4agent/CLAUDE.md for this crate’s place in the workspace.
This crate owns the registry (who a participant is, what it may do, and
– since 2026-09-17 – which live sessions exist under it) and the mail
operations (send, inbox, ack, message lookup, plus unread counting).
Persistence is a separate task: what lives here is the MailStore
trait a persistent implementation will satisfy, and InMemoryStore,
the implementation this crate’s own tests run against.
The rule that defines the mailbox (mail4agent/CLAUDE.md): a sender
is never a field the caller fills in. MailboxEngine::authenticate is
the only way a mail4agent_api::ParticipantId (an account) enters
the engine from the outside, and MailboxEngine::ensure_session is the
only way one of its sessions does; every other operation takes an
already-resolved mail4agent_api::Address as an argument, never one
read out of a request. A session is a participant, not a new concept
beside one – see MailboxEngine’s own doc comments on send, inbox
and ack for exactly how it inherits its account’s permissions and
reads its account’s mail
(docs/gate4agent/plans/mailbox-service-extraction-and-signed-session-identity-2026-09-16.md
§5e).
Structs§
- InMemory
Store - An in-memory
MailStore, used by this crate’s own tests. Not meant for production use: nothing here survives a process restart, and every method always succeeds – there is no disk, lock or connection here to fail. - Mailbox
Engine - The mailbox engine. Generic over its
MailStoreso the same logic runs againstcrate::InMemoryStorein tests and, later, a persistent store – neither of which this crate needs to know about here. - Participant
Permissions - What a newly registered (or re-permissioned) participant may do.
Distinct from
ParticipantRecord: this is the caller-facing shape a registration call takes, without the label or the secret digest, which the engine derives itself. - Participant
Record - A registered participant, as the mailbox’s own registry holds it.
- Participant
Summary - A directory-listable summary of a registered participant: enough to
list it, and no more. Deliberately excludes
ParticipantRecord’ssecret_digest,may_send,may_readandoperator– a directory answers “who exists”, never “what may they do” or anything that would help forge one, and a type that structurally has nosecret_digestfield cannot leak one even by accident, regardless of whatMailStore::list_participants’s implementation does internally. Seemail4agent_api::DirectoryEntry, the wire type this is assembled into. - Room
Record - A room the mailbox tracks membership for. Membership is explicit and
mailbox-owned – never recomputed from a foreign graph (see
mail4agent/CLAUDE.mdandmailbox-service-extraction-and-signed-session-identity-2026-09-16.md§5b: this is what makes a room’s readability immune to something unrelated growing too large elsewhere). - Room
Summary - A directory-listable summary of a room: its id and current membership,
as raw fact – not yet filtered through any one caller’s point of view.
crate::MailboxEngine::directoryis what turns “who is a member” into “is the caller a member”. - Session
Record - One live session, as the mailbox’s own registry holds it. Carries no
secret and no permission bits of its own – a session authenticates
through its account’s bearer secret plus kernel attestation of the
calling process (
mail4agent-attest, outside this crate entirely), and borrows its account’smay_send/may_read/operatorbits rather than carrying its own (seecrate::MailboxEngine::resolve_identity). This is “a participant record gains a kind” made a type-system fact rather than a runtime tag:ParticipantRecordis the account kind, this is the session kind, and which one a lookup returns says which kind it found. - Store
Error - An error from a
MailStoreimplementation itself – I/O, a lock, a corrupt row – as distinct from a domain refusal (mail4agent_api::MailError). Carries a message meant fortracing::error!, never for a caller: see the module doc comment.
Enums§
- Insert
Message Outcome - What
MailStore::insert_messagedid. Distinguishes a genuinely new message from a retry recognised by its idempotency key, so the engine can return the originalmail4agent_api::SendResponsewithout needing a second read.
Constants§
- SECRET_
HEX_ LEN - Length, in lower-hex characters, of a freshly generated participant
secret: 32 random bytes (256 bits of entropy) rendered as hex. See
MailboxEngine::authenticatefor why that much entropy is exactly what makes an exact-digest lookup safe.
Traits§
- Mail
Store - The mailbox’s persistence boundary. One mutating method per engine-level mutation (see the module doc comment on why); reads are split finely enough that each maps onto a single indexed SQL query rather than a linear scan.
Type Aliases§
- Liveness
Check - A liveness check the engine is given, never one it performs itself:
mail4agent-corelearns nothing about processes or Windows (seemail4agent-attest, which lives outside this crate entirely and is exactly the shape this closure expects –mail4agent_attest::is_alivecoerces to it directly). Takes(pid, started_at_unix_ms), the same pairmail4agent_api::SessionAttestedcarries, and answers whether that process is still the one that started at that time. - Secret
Digest - The SHA-256 digest of a participant’s secret. The engine stores only
this, never the secret itself – see
MailboxEngine::authenticate’s doc comment for why an exact-digest index is safe to look up directly rather than scanned.