Skip to main content

ProtocolStateStorage

Trait ProtocolStateStorage 

Source
pub trait ProtocolStateStorage: Send + Sync {
    // Required methods
    fn store(
        &self,
        key_type: &str,
        key_id: &str,
        data: &[u8],
    ) -> ProtocolStateResult<()>;
    fn load(
        &self,
        key_type: &str,
        key_id: &str,
    ) -> ProtocolStateResult<Option<Vec<u8>>>;
    fn delete(&self, key_type: &str, key_id: &str) -> ProtocolStateResult<()>;
    fn list_keys(&self, key_type: &str) -> ProtocolStateResult<Vec<String>>;
}
Expand description

Storage for restartable protocol and message-plane state.

Implementations must be app-container scoped and must not use a credential store whose lifetime can exceed the app container. The operations retain the atomicity and durability contract defined by offline_protocol_mls::MlsStorage, but this trait deliberately does not inherit from the crypto-storage contract: lifecycle separation should be structural, not a marker on the wrong abstraction.

Values for sensitive categories arrive already sealed (see the module docs), so an implementation must store and return the bytes it is given verbatim — it must not inspect, re-encode, or truncate them.

Required Methods§

Source

fn store( &self, key_type: &str, key_id: &str, data: &[u8], ) -> ProtocolStateResult<()>

Atomically stores or replaces one protocol-state entry.

Implementations may refuse a value over MAX_PROTOCOL_STATE_RECORD_TRANSFER_BYTES; core never sends one.

Source

fn load( &self, key_type: &str, key_id: &str, ) -> ProtocolStateResult<Option<Vec<u8>>>

Loads one protocol-state entry, returning None when absent.

Implementations must bound the read. Check the stored entry’s size before materializing it and never return — or allocate — more than MAX_PROTOCOL_STATE_RECORD_TRANSFER_BYTES. An entry above the ceiling is corrupt or tampered by construction; drop it and report ProtocolStateError::Corrupted, which is what lets core settle the message ids the application is still holding for it. Returning the oversized value instead defeats the size policy, because core can only check a length it has already been handed.

The same applies to a record whose framing does not parse. Reserve Corrupted for losses that are permanent — anything transient belongs in ProtocolStateError::LoadFailed, which core leaves in place to retry.

Source

fn delete(&self, key_type: &str, key_id: &str) -> ProtocolStateResult<()>

Deletes one protocol-state entry and succeeds when it is already absent.

Source

fn list_keys(&self, key_type: &str) -> ProtocolStateResult<Vec<String>>

Lists entry IDs within one protocol-state category.

Like Self::load, enumeration should stay bounded: core caps every category well below any sane ceiling, so a store holding vastly more has been tampered with and an implementation may stop early.

An empty category is Ok(vec![]). A backend that can only spell it as ProtocolStateError::NotFound is read the same way, so honoring that contract does not fail restore.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§