Skip to main content

SessionStore

Trait SessionStore 

Source
pub trait SessionStore:
    Send
    + Sync
    + 'static {
    type Error: Debug + Send + Sync + 'static;

    // Required methods
    fn store_session<'life0, 'life1, 'async_trait>(
        &'life0 self,
        session: &'life1 Session,
    ) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;
    fn get_session<'life0, 'life1, 'async_trait>(
        &'life0 self,
        session_id: &'life1 str,
    ) -> Pin<Box<dyn Future<Output = Result<Option<Session>, Self::Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;
    fn delete_session<'life0, 'life1, 'async_trait>(
        &'life0 self,
        session_id: &'life1 str,
    ) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;
    fn store_refresh_index<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        refresh_token: &'life1 str,
        session_id: &'life2 str,
    ) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait;
    fn take_session_id_by_refresh<'life0, 'life1, 'async_trait>(
        &'life0 self,
        refresh_token: &'life1 str,
    ) -> Pin<Box<dyn Future<Output = Result<Option<String>, Self::Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;
    fn count_pending_challenges<'life0, 'life1, 'async_trait>(
        &'life0 self,
        did: &'life1 str,
    ) -> Pin<Box<dyn Future<Output = Result<usize, Self::Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;
}
Expand description

Storage operations the canonical handlers invoke.

Each backend wraps its own keyspace handle (vti-common’s KeyspaceHandle enum, did-hosting’s KeyspaceHandle struct, future cloud-store backends) in an adapter implementing this trait. The handler holds a &S and never touches the concrete storage type directly.

§Why this trait, not a single KeyspaceHandle type

did-hosting and vti-common evolved separate keyspace abstractions before the auth-architecture consolidation. Merging them is out of scope for the auth work; the trait boundary keeps them independent while still sharing the auth-flow code.

Required Associated Types§

Source

type Error: Debug + Send + Sync + 'static

Wrapped error type. Conversion to AuthError::Internal is the handler’s responsibility (via ? and the backend’s From<AuthError> impl).

Required Methods§

Source

fn store_session<'life0, 'life1, 'async_trait>( &'life0 self, session: &'life1 Session, ) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Persist a session under its session_id.

Source

fn get_session<'life0, 'life1, 'async_trait>( &'life0 self, session_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Option<Session>, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Load a session by session_id. Ok(None) if missing or expired-and-swept.

Source

fn delete_session<'life0, 'life1, 'async_trait>( &'life0 self, session_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Delete a session and its refresh-token reverse-index.

Source

fn store_refresh_index<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, refresh_token: &'life1 str, session_id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Persist the refresh_token → session_id reverse-index. Implementors choose whether to hash the key (recommended; vti-common does, did-hosting historically does not) — the handler treats the token as an opaque bearer.

Source

fn take_session_id_by_refresh<'life0, 'life1, 'async_trait>( &'life0 self, refresh_token: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Option<String>, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Atomically claim-and-delete the refresh_token → session_id reverse-index. Cross-replica safe (Redis GETDEL / DynamoDB DeleteItem ReturnValues=ALL_OLD / fjall mutex). Exactly one concurrent caller observes Some for any given token. Used by /auth/refresh to close the rotation TOCTOU.

Source

fn count_pending_challenges<'life0, 'life1, 'async_trait>( &'life0 self, did: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<usize, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Count ChallengeSent sessions for did. Backends with an O(1) per-DID tracker (did-hosting) override the default O(N) prefix-scan implementation by re-implementing this method.

Default implementation provided for backends that haven’t yet built a tracker — correct but slow under load. Override before relying on per-DID rate limiting in production.

Dyn Compatibility§

This trait is dyn compatible.

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

Implementors§