Skip to main content

Module dm_body

Module dm_body 

Source
Expand description

Direct-message body encoding — the structured payload that goes INSIDE the ECIES ciphertext of an AuthorizedDirectMessage.

§Why this lives here

The room contract validates the OUTER envelope of a DM (sender signature, membership, caps, tombstones) but never reads the plaintext — that’s opaque ECIES ciphertext only the recipient can decrypt. The body is therefore a pure client-↔-client concern: every River UI / riverctl client agrees on how to encode and decode the plaintext bytes, but the contract is indifferent. Putting this in river-core keeps UI + CLI byte-identical without dragging any contract WASM changes into the picture (i.e. no delegate / contract migration entry is required for adding a body variant).

§Wire format

    magic_byte (0x80)           ( 1 byte)
    cbor(DirectMessageBody)     (variable)

0x80 is a UTF-8 continuation byte and CANNOT appear as the first byte of any valid UTF-8 string. Pre-this-format DM plaintexts were always UTF-8 text (encoded via String::into_bytes), so any DM starting with 0x80 is unambiguously a new-format body. Bodies whose first byte is anything else are decoded as legacy DirectMessageBody::Text via lossy UTF-8 conversion.

See encode_body / decode_body for the canonical wire transition, plus the unit tests below pinning round-trips and the legacy fallback path.

§Why CBOR and not bincode

CBOR is already in river-core’s dep graph (used by Invitation encoding in the UI), and is forwards-compatible with optional fields out of the box (#[serde(default)]). bincode would tighten the encoding a few bytes but would create a separate deserialization surface to evolve.

§Adding a new variant

  1. Add the variant at the END of DirectMessageBody so older clients still decode the existing variants.
  2. Existing test coverage (encode_decode_*, legacy_text_decodes_as_text, plus your new round-trip test) pin the wire shape.
  3. Update both [crate::room_state::direct_messages::compose_direct_message] callers (UI + CLI) to produce the new variant when appropriate.

Structs§

InvitePayload
Inner shape of DirectMessageBody::Invite.

Enums§

DirectMessageBody
Structured plaintext payload of a direct message.

Constants§

DM_BODY_MAGIC
First byte of every new-format DM body. 0x80 is a UTF-8 continuation byte and cannot appear as the leading byte of any valid UTF-8 string, so a legitimate legacy text body can never collide with this magic.

Functions§

decode_body
Decode wire bytes back into a DirectMessageBody.
encode_body
Encode a DirectMessageBody to wire bytes per the format described in the module docs (magic byte + CBOR). The returned Vec<u8> is what gets passed to compose_direct_message’s body parameter.