pas-external 4.0.1

Ppoppo Accounts System (PAS) external SDK -- OAuth2 PKCE, PASETO verification, Axum middleware, session liveness
Documentation
use crate::oauth::UserInfo;
use crate::session_liveness::EncryptedRefreshToken;
use crate::types::{PpnumId, UserId};

/// Session data from a successful PAS authentication.
///
/// Passed to [`SessionStore::create`](super::SessionStore::create) for the consumer to persist.
///
/// # Data ownership
///
/// `user_info` is **transient** data from PAS. It should be used for logging or
/// display at login time, but PAS-owned fields (`ppnum`, `email`) must NOT be
/// persisted in the consumer's database. Fetch via PAS userinfo API when needed.
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct NewSession {
    /// PAS ppnum identifier (OAuth `sub` claim, ULID format).
    pub ppnum_id: PpnumId,
    /// User ID returned by [`AccountResolver::resolve`](super::AccountResolver::resolve).
    pub user_id: UserId,
    /// PAS refresh token for this session, **already encrypted** by the SDK
    /// using the `TokenCipher` supplied to
    /// [`PasAuthConfig::with_refresh_token_cipher`](super::PasAuthConfig::with_refresh_token_cipher).
    ///
    /// `None` iff (a) PAS issued no refresh_token (rare — only for special
    /// scopes), or (b) the consumer did not configure a cipher (DEV_AUTH
    /// flows, or consumers that explicitly opt out of refresh-token
    /// persistence).
    ///
    /// **OAuth consumers (RCW, CTW):** PAS does NOT apply Refresh Token Rotation
    /// (RTR) for OAuth clients — the same token is reused across refreshes.
    /// Lifetime: 180 days of inactivity expiry.
    ///
    /// Store the ciphertext (`as_str()` or `into_inner()`) in your session
    /// table. The plaintext **never** crosses this boundary, so a consumer
    /// schema bug cannot expose it.
    pub refresh_token: Option<EncryptedRefreshToken>,
    /// Client `User-Agent` header value.
    pub user_agent: Option<String>,
    /// Client IP address. See
    /// [`PasAuthConfig::with_xff_trusted_proxies`](super::PasAuthConfig::with_xff_trusted_proxies)
    /// to control the X-Forwarded-For walk for your proxy topology.
    pub ip_address: Option<String>,
    /// PAS UserInfo snapshot (transient — for display, NOT for DB storage).
    pub user_info: UserInfo,
    /// PASETO `sv` claim snapshot from the just-issued access token.
    /// Populated by the SDK's OAuth callback from
    /// [`UserInfo::session_version`]. `None` for tokens that carry no
    /// `sv` claim (AI agent / client-credentials — spec §4.2.1) and for
    /// DEV_AUTH sessions that bypass the token issuance step.
    ///
    /// Consumers should persist this alongside the session and expose it
    /// via [`SvAware::sv`](super::SvAware::sv) so the SDK's
    /// [`SvAwareSessionResolver`](super::SvAwareSessionResolver) can
    /// detect break-glass / lifecycle-driven invalidation.
    pub sv: Option<i64>,
}