Skip to content

Concepts

This page explains the model you program against when you use pkg/client: who the peers are, how a client picks a server, which agent handles each request, and what happens to a message between SendMessage and the recipient’s acknowledgement.

Every participant is a libp2p peer: your app, the people it talks to and the Ricochet server. A peer’s identity is an Ed25519 key pair, and its peer ID (12D3KooW...) is derived from the public key. The peer ID is the address you send to, and the public key inside it is what end-to-end encryption uses, so there is no separate key exchange. See Encryption & compression.

The server identifies the caller from the connection itself. Noise authenticates both ends when the connection opens, and every request is checked against that identity. Nothing a client writes into a request can claim to be someone else.

Two consequences for your app:

  • Keep the private key. It is the user’s address and the key to their encrypted mail. The mailbox example stores it in a file and reloads it.
  • Use Ed25519. Encryption converts the key to X25519 and fails with any other key type.

A client does not discover servers. You list them in client.Config.PreferredServers, each with a Priority (lower is tried first) and a Weight (breaks ties, higher first). This is how email MX records work, and the semantics follow them:

  • For each request the client tries the servers in order. A server it cannot open a stream to is skipped, and the next one is tried.
  • A server that answers is final. If it refuses the request, the refusal comes back to you; the client does not retry it on another server.
  • An option such as WithDocServer names one server for one call. The client makes exactly one attempt.

There is no replication between servers. A message stored on server A is retrieved from server A, so sender and recipient need a server in common. Creating a client covers the details.

The server splits its work the way a mail system does. Each agent with a protocol ID is a libp2p protocol that the client opens a stream to; the others run inside the server.

Agent Protocol ID What it does Client calls
MSA (submission) /sf-network/submit/1.0.0 Accepts a message for delivery SendMessage, ForwardMessage
MSA batch /sf-network/submit/batch/1.0.0 Accepts up to 100 messages in one request SendMessages
MTA (transfer) internal Validates and routes a submitted message —
MDA (delivery) internal Stores the message in the recipient’s mailbox and triggers a notification —
MAA (access) /sf-network/access/1.0.0 Retrieval, flags, acknowledgement, expunge, delete RetrieveMessages, MarkDelivered, UpdateFlags, …
MMA (management) /sf-network/admin/1.0.0 Mailbox lifecycle, ACLs, capacity CreateMailbox, GrantAccess, QueryCapacity, …
SDA (documents) /ricochet/store/doc/1.0.0 Documents and the directory PutDocument, JoinDirectory, …
SFA (feeds) /ricochet/store/feed/1.0.0 Append-only feeds CreateFeed, AppendFeedEntry, …
SCA (collections) /ricochet/store/collection/1.0.0 Keyed JSON collections with queries PutCollectionItem, QueryCollection, …
Notify /ricochet/mailbox-notify/1.0.0 Server-to-client push for private mailboxes RegisterNotificationHandler

The protocol reference lists the operations of each protocol.

A message goes through five steps. Only the last one removes it.

  1. Submit. The sender calls SendMessage. The client applies compression and encryption, then writes the message to the first reachable preferred server. The server’s answer comes back in a *client.SendResult.
  2. Store. The server validates the message and stores it in the recipient’s mailbox for the message’s folder path (inbox when none is given). A mailbox that does not exist yet is created as a private mailbox. A full mailbox refuses the message.
  3. Notify. If the recipient is connected, the server pushes a notification: over a direct stream for a private mailbox, on a GossipSub topic for a shared or public one. A notification is a hint, and the server may drop it under load. See Push notifications.
  4. Retrieve. The recipient calls RetrieveMessages, which returns the stored messages and decrypts them. Retrieval changes nothing on the server: the same messages come back next time.
  5. Acknowledge. The recipient calls MarkDelivered with the message IDs it has handled. The server deletes non-persistent messages and marks persistent ones \Seen. See Flags, ack & expunge.

A message the recipient never acknowledges stays until its expiry (seven days unless the sender set one), the mailbox’s retention period, or an explicit delete.

Data Visible to the server
Message payload sent with WithEncryption No. Only the recipient’s key opens it.
Message envelope: sender, recipient, folder path, timestamps, expiry, priority, flags, size Yes
Message payload sent without encryption Yes
Documents, feed entries, collection items Yes. They are stored as sent.
Paths, content types, sizes and version counts of stored resources Yes
Directory listings Yes, and to every peer
Who is connected Yes. The server tracks presence to decide whom to notify.

Visibility settings on documents, feeds and collections are enforced by the server, not by a key. If the server itself must not read a document, encrypt it in your app before you store it. The operator’s view of the same model is in Who can read what.