ppoppo-sdk-core 0.2.0

Internal shared primitives for the Ppoppo SDK family (pas-external, pas-plims, pcs-external) — verifier port, audit trait, session liveness port, OIDC discovery, perimeter Bearer-auth Layer kit, identity types. Not a stable public API; do not depend on this crate directly. Consume the SDK crates that re-export from it (e.g. `pas-external`).
Documentation
//! [`AuthProvider`] — perimeter token-validation port.

use async_trait::async_trait;

use super::error::VerifyError;

/// Perimeter token-validation port — the consumer-implemented seam.
///
/// One async method spans the consumer's full security decision —
/// cryptographic verification + substrate liveness lookup — and
/// produces the consumer's perimeter session type `S` directly.
/// [`super::BearerAuthLayer`] calls this once per authenticated
/// request and maps the two error variants to HTTP dispositions:
/// [`VerifyError::Rejected`] → 401 + cookie clearance,
/// [`VerifyError::SubstrateTransient`] → 503 with cookies preserved.
///
/// ## Why generic over `S` rather than returning a fixed claims type
///
/// chat-auth's perimeter session has 5 fields (`ppnum_id`, `ppnum`,
/// `account_type`, `scopes`, `audience`); RCW/CTW's has 3. A fixed
/// SDK-side `AuthClaims` would force chat-auth to run a second
/// "hydration" Layer after the perimeter to enrich the session,
/// breaking the single-perimeter invariant. The generic `S` lets
/// each consumer's substrate-aware impl produce its native session
/// directly in one step.
#[async_trait]
pub trait AuthProvider<S>: Send + Sync
where
    S: Clone + Send + Sync + 'static,
{
    /// Validate the Bearer token end-to-end. The SDK Layer passes the
    /// raw token verbatim — no decoding, no trimming. The impl owns
    /// the substrate (JWKS cache, session-row lookup, sv-axis cache,
    /// or whichever combination this consumer composes).
    async fn verify_token(&self, bearer: &str) -> Result<S, VerifyError>;
}