pub struct Configuration {
pub owner_member_id: MemberId,
pub configuration_version: u32,
pub privacy_mode: PrivacyMode,
pub display: RoomDisplayMetadata,
pub max_recent_messages: usize,
pub max_user_bans: usize,
pub max_message_size: usize,
pub max_nickname_size: usize,
pub max_members: usize,
pub max_room_name: usize,
pub max_room_description: usize,
pub max_direct_messages: Option<usize>,
}Fields§
§owner_member_id: MemberId§configuration_version: u32§privacy_mode: PrivacyMode§display: RoomDisplayMetadata§max_recent_messages: usize§max_user_bans: usize§max_message_size: usize§max_nickname_size: usize§max_members: usize§max_room_name: usize§max_room_description: usize§max_direct_messages: Option<usize>Owner-tunable global bound on direct_messages.messages, mirroring how
max_recent_messages bounds recent_messages. None means “this
configuration was signed before the field existed”; read it through
Configuration::effective_max_direct_messages, which substitutes
DEFAULT_MAX_DIRECT_MESSAGES, so pre-existing rooms are bounded
without the owner having to re-sign anything.
§Why Option + skip_serializing_if, and why that is NOT optional
AuthorizedConfigurationV1::verify_signature re-serializes this
whole struct with ciborium and checks the owner’s signature over those
bytes. A plain #[serde(default)] usize deserializes old bytes to 0
and then re-serializes them WITH the extra map entry, so the bytes no
longer match what the owner signed: every room created before this
field existed would fail verify, which also gates the #292 migration
PUT — i.e. every existing room bricked, unrecoverably.
Option + skip_serializing_if makes the addition byte-neutral: an
old configuration decodes to None, re-encodes without the key, and
its signature still verifies. Pinned by
legacy_configuration_bytes_still_verify_after_adding_the_field.
Any future field added to Configuration MUST follow this pattern AND
be appended LAST — inserting an Option field mid-struct reorders the
CBOR map for configurations that set it.
The pattern is one-directional, and deliberately so. It protects OLD
bytes read by NEW code. The reverse — an old-struct client reading a
configuration that actually SETS this field — still breaks: serde has no
deny_unknown_fields here, so such a client silently drops the key,
re-serializes one entry short, and the owner signature fails. That is
unreachable only because the contract key is BLAKE3(wasm, params) and
both the UI and riverctl include_bytes! the WASM they derive the key
from: a client with the old struct also derives the OLD contract key and
never sees state carrying this field. Do not weaken that coupling.
Implementations§
Source§impl Configuration
impl Configuration
Sourcepub fn effective_max_direct_messages(&self) -> usize
pub fn effective_max_direct_messages(&self) -> usize
The global DM cap in force for this room: the owner’s explicit
Self::max_direct_messages, or DEFAULT_MAX_DIRECT_MESSAGES when
unset. Every retention and horizon decision MUST read the cap through
here so a legacy (None) configuration and an explicitly-defaulted one
behave identically.
Trait Implementations§
Source§impl Clone for Configuration
impl Clone for Configuration
Source§fn clone(&self) -> Configuration
fn clone(&self) -> Configuration
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more