Skip to main content

Crate mail4agent_core

Crate mail4agent_core 

Source
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§

InMemoryStore
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.
MailboxEngine
The mailbox engine. Generic over its MailStore so the same logic runs against crate::InMemoryStore in tests and, later, a persistent store – neither of which this crate needs to know about here.
ParticipantPermissions
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.
ParticipantRecord
A registered participant, as the mailbox’s own registry holds it.
ParticipantSummary
A directory-listable summary of a registered participant: enough to list it, and no more. Deliberately excludes ParticipantRecord’s secret_digest, may_send, may_read and operator – a directory answers “who exists”, never “what may they do” or anything that would help forge one, and a type that structurally has no secret_digest field cannot leak one even by accident, regardless of what MailStore::list_participants’s implementation does internally. See mail4agent_api::DirectoryEntry, the wire type this is assembled into.
RoomRecord
A room the mailbox tracks membership for. Membership is explicit and mailbox-owned – never recomputed from a foreign graph (see mail4agent/CLAUDE.md and mailbox-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).
RoomSummary
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::directory is what turns “who is a member” into “is the caller a member”.
SessionRecord
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’s may_send/may_read/operator bits rather than carrying its own (see crate::MailboxEngine::resolve_identity). This is “a participant record gains a kind” made a type-system fact rather than a runtime tag: ParticipantRecord is the account kind, this is the session kind, and which one a lookup returns says which kind it found.
StoreError
An error from a MailStore implementation itself – I/O, a lock, a corrupt row – as distinct from a domain refusal (mail4agent_api::MailError). Carries a message meant for tracing::error!, never for a caller: see the module doc comment.

Enums§

InsertMessageOutcome
What MailStore::insert_message did. Distinguishes a genuinely new message from a retry recognised by its idempotency key, so the engine can return the original mail4agent_api::SendResponse without 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::authenticate for why that much entropy is exactly what makes an exact-digest lookup safe.

Traits§

MailStore
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§

LivenessCheck
A liveness check the engine is given, never one it performs itself: mail4agent-core learns nothing about processes or Windows (see mail4agent-attest, which lives outside this crate entirely and is exactly the shape this closure expects – mail4agent_attest::is_alive coerces to it directly). Takes (pid, started_at_unix_ms), the same pair mail4agent_api::SessionAttested carries, and answers whether that process is still the one that started at that time.
SecretDigest
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.