pas-external 0.9.0

Ppoppo Accounts System (PAS) external SDK — OAuth2 PKCE, JWT verification port, Axum middleware, session liveness
Documentation
//! sv-axis (`session_version`) enforcement port + first-party adapters.
//!
//! Phase 11.Z (RFC_2026-05-09 §3.5 Row 4*/5*) — the SDK boundary's
//! re-export of the engine's `EpochRevocation` port plus the canonical
//! adapter set consumers wire at boot:
//!
//! - [`Cache`] / [`Fetcher`] — narrow port traits (promoted from
//!   chat-auth's `validator.rs` `SessionVersionCache` / `SessionVersionFetcher`
//!   pair under §3 Row 6 "replace, don't layer").
//! - [`InProcessTtlCache`] — opinionated [`Cache`] impl (per-pod TTL map);
//!   default for RCW/CTW Slice 4/5 wiring.
//! - [`UserinfoFetcher`] — opinionated [`Fetcher`] impl (calls PAS
//!   userinfo with the consumer's access_token; reads `session_version`,
//!   gated on the new `session_version` scope per §3.5 Row 9).
//! - [`CompositeEpochRevocation`] — combines a [`Cache`] + a [`Fetcher`]
//!   into the engine port. Cache hit short-circuits; cache miss fetches
//!   authoritative + writes back. Fetcher transient surfaces as
//!   [`EpochRevocationError::Transient`], engine maps to
//!   [`AuthError::SessionVersionLookupUnavailable`], SDK maps to
//!   [`crate::token::VerifyError::SessionVersionLookupUnavailable`].
//!
//! ## Why HIDDEN sv on `Claims`, surfaced on userinfo
//!
//! The engine deliberately HIDES `sv` on `Claims` (Phase 4 Decision 1,
//! `ppoppo_token::access_token::claims`). Surfacing the *token's* sv
//! would push enforcement onto every caller. The userinfo
//! `session_version` field surfaces the *current substrate value*, not
//! the token's claim — a different role. Consumers wiring this module
//! never see the token's sv; they hand authoritative-substrate lookups
//! to the engine via [`crate::PasJwtVerifier::with_epoch_revocation`].
//!
//! See `0context/RFC_2026-05-09_pas-external-0.9.0-sv-axis-surfacing.md`
//! §3 + §3.5 + §4 for the full architecture frame.
//!
//! [`AuthError::SessionVersionLookupUnavailable`]: ppoppo_token::access_token::AuthError::SessionVersionLookupUnavailable

mod cache;
mod composite;
mod fetcher;
mod ttl_cache;
mod userinfo;

pub use cache::Cache;
pub use composite::CompositeEpochRevocation;
pub use fetcher::{FetchError, Fetcher};
pub use ttl_cache::InProcessTtlCache;
pub use userinfo::UserinfoFetcher;

// Engine port re-export. The textbook deep module: small interface
// (`current(sub) -> Result<i64, _>`), large implementation
// (`engine::check_epoch::run` — R6 legacy admit, transient mapping,
// M37 observability, raw-payload sv extraction). Re-exporting here
// lets consumers depend only on `pas-external` without a transitive
// `ppoppo-token` Cargo entry.
pub use ppoppo_token::access_token::{EpochRevocation, EpochRevocationError};

// Shared key shape constants. PAS writes `sv:{sub}` to the canonical
// shared cache; consumers reading the same key share the namespace.
// SSOT lives in `ppoppo-token` so PAS writer and SDK consumer cannot
// drift.
pub use ppoppo_token::{SV_CACHE_TTL, sv_cache_key};