//! PAS-backed session liveness primitives.
//!
//! When a consumer persists PAS `refresh_token`s server-side and treats
//! PAS as the single source of truth for session validity, the code path
//! is always the same:
//!
//! 1. Encrypt the `refresh_token` at rest — leaking a database snapshot
//!    must not leak a renewable credential.
//! 2. Periodically ask PAS "is this session still live?" by calling
//!    [`AuthClient::refresh_token`] with the decrypted token.
//! 3. Distinguish a *revoked* session (PAS rejected the token — stop
//!    trusting it immediately) from a *transient* failure (PAS is
//!    temporarily unreachable — serve the cached session so a network
//!    blip doesn't log users out).
//!
//! This module ships the pieces every consumer needs for that shape:
//!
//! - [`TokenCipher`] — AES-256-GCM wrapper for at-rest encryption.
//! - [`LivenessOutcome`] — classification of a single liveness attempt.
//! - [`classify_refresh_error`] — maps a PAS error into `Revoked` or
//!   `Transient`.
//! - [`attempt_liveness_refresh`] — the decrypt → call PAS → re-encrypt
//!   sequence wrapped as one call.
//!
//! The consumer retains ownership of: its [`crate::middleware::SessionStore`]
//! persistence (when to mark a session revoked, when to refresh
//! `last_verified_at`), the stale-check gate (how often to re-verify),
//! and the `AuthContext` its handlers receive. The SDK stays on this
//! side of the line so every consumer can pick a schema and domain model
//! that fits its product.
//!
//! [`AuthClient::refresh_token`]: crate::oauth::AuthClient::refresh_token

mod cipher;
mod liveness;

pub use cipher::{CipherError, EncryptedRefreshToken, TokenCipher};
pub use liveness::{
    LivenessFailure, LivenessOutcome, RevokeCause, TransientCause, attempt_liveness_refresh,
    classify_refresh_error,
};
