Skip to main content

SsoManager

Struct SsoManager 

Source
pub struct SsoManager<T, Si, St, E, Pk = NoopProductKeyStore>
where T: SsoTransport + 'static, Si: SsoSigner, St: SsoSessionStore + 'static, E: SsoEventSink + 'static, Pk: SsoProductKeyStore + 'static,
{ /* private fields */ }
Expand description

Central coordinator for the SSO pairing lifecycle.

Generic over five injected adapters so hosts provide platform-specific implementations without coupling this crate to any I/O runtime.

The fifth generic Pk defaults to NoopProductKeyStore, so existing callers constructed via SsoManager::new do not need to change.

All shared fields are wrapped in Arc so the background pairing thread can update state and notify the sink without requiring Arc<SsoManager>.

Implementations§

Source§

impl<T, Si, St, E> SsoManager<T, Si, St, E, NoopProductKeyStore>
where T: SsoTransport + 'static, Si: SsoSigner, St: SsoSessionStore + 'static, E: SsoEventSink + 'static,

Source

pub fn new( transport: T, signer: Si, store: St, sink: E, metadata_url: String, ) -> Self

Construct a new manager starting in the Idle state with the default no-op product key store.

If you need product key caching with persistence, use SsoManager::with_product_key_store instead.

Source§

impl<T, Si, St, E, Pk> SsoManager<T, Si, St, E, Pk>
where T: SsoTransport + 'static, Si: SsoSigner, St: SsoSessionStore + 'static, E: SsoEventSink + 'static, Pk: SsoProductKeyStore + 'static,

Source

pub fn with_product_key_store( transport: T, signer: Si, store: St, sink: E, product_key_store: Pk, metadata_url: String, ) -> Self

Construct a new manager with a custom product key store.

The manager starts in the Idle state.

Source§

impl<T, Si, St, E, Pk> SsoManager<T, Si, St, E, Pk>
where T: SsoTransport + 'static, Si: SsoSigner, St: SsoSessionStore + 'static, E: SsoEventSink + 'static, Pk: SsoProductKeyStore + 'static,

Source

pub fn state(&self) -> SsoState

Return a snapshot of the current state.

Source

pub fn pair(&self) -> Result<(), SsoError>

Initiate a QR-pairing session in a background thread.

Transitions: Idle / FailedAwaitingScan (when QR is ready) → Paired on success, or Failed on error or cancellation.

Returns Err(PairingAlreadyInProgress) if a pairing is already running.

Source

pub fn unpair(&self) -> Result<(), SsoError>

Clear the current session and return to the Idle state.

If a pairing is in progress it is cancelled before clearing. Safe to call from any state, including Idle.

Source

pub fn restore_session(&self) -> Result<(), SsoError>

Load a previously persisted session from the store.

On success, transitions to Paired. If no session is stored, stays Idle. Returns Err(Store(_)) if the store call itself fails.

Source

pub fn handle_pairing_result( &self, result: PairingResult, ) -> Result<(), SsoError>

Finalise a completed pairing handshake.

Persists the session metadata, stores sign material for future request_sign calls, initialises the product key cache with the phone identity (loading any persisted entries), clears the in-progress guard, and transitions to Paired. The PairingResult is consumed and its session_key is zeroized on drop — callers must not use it after this call.

Source

pub fn request_sign(&self, payload: &[u8]) -> Result<Vec<u8>, SsoError>

Send a sign request to the paired phone and block until response or timeout.

Must be called from a background thread (blocking I/O). Returns the signature bytes on success.

Returns Err(NotPaired) if no paired session exists, or Err(SignFailed) if the transport or phone returns an error.

Source

pub fn request_product_key( &self, product_id: &str, index: u32, ) -> Result<[u8; 32], SsoError>

Request a product public key from the paired phone.

Checks the in-memory cache first (no network round-trip on hit). On a cache miss, verifies the phone is online before sending a ProductKeyRequest over the encrypted channel and waiting up to 30 seconds for the phone’s response.

Returns Err(NotPaired) if no paired session exists. Returns Err(PhoneOffline) if the phone has not sent a heartbeat within presence::HEARTBEAT_TIMEOUT_SECS (cache misses only). Returns Err(ProductKeyCapabilityAbsent) if the phone does not advertise the "product_key" capability. Returns Err(ProductKeyRejected) if the phone denies the request. Returns Err(ProductKeyTimeout) if no response arrives within 30 s.

Source

pub fn is_phone_online(&self) -> bool

Return true if the phone sent a heartbeat within the presence timeout.

Delegates to presence::is_phone_online using the atomic timestamp so no mutex is required.

Source

pub fn cache_remove_and_persist(&self, product_id: &str, index: u32)

Remove a single entry from the product key cache and persist the snapshot.

No-op if the cache is uninitialised or the entry does not exist.

Auto Trait Implementations§

§

impl<T, Si, St, E, Pk = NoopProductKeyStore> !Freeze for SsoManager<T, Si, St, E, Pk>

§

impl<T, Si, St, E, Pk> RefUnwindSafe for SsoManager<T, Si, St, E, Pk>

§

impl<T, Si, St, E, Pk> Send for SsoManager<T, Si, St, E, Pk>

§

impl<T, Si, St, E, Pk> Sync for SsoManager<T, Si, St, E, Pk>

§

impl<T, Si, St, E, Pk> Unpin for SsoManager<T, Si, St, E, Pk>
where Si: Unpin,

§

impl<T, Si, St, E, Pk> UnsafeUnpin for SsoManager<T, Si, St, E, Pk>
where Si: UnsafeUnpin,

§

impl<T, Si, St, E, Pk> UnwindSafe for SsoManager<T, Si, St, E, Pk>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V