Ppoppo SDK shared primitives — internal mechanism for the
Ppoppo SDK family (pas-external, future pas-plims, pcs-external).
Stability — not a stable public API
This crate is published to crates.io as a transitive dependency of
the SDK family above (cargo enforces "all transitive deps of a
published crate must themselves be published"). It is not a
stable public API; it carries no SemVer guarantees beyond the
current minor and may rearrange shapes between minors. Consume
the SDK crates that re-export from it (pas-external::*,
eventually pas-plims::* / pcs-external::*); do not depend on
ppoppo-sdk-core directly from a 3rd-party application.
Phase A foundation (RFC RFC_2026-05-08_app-credential-collapse.md)
— collapses the verifier port + audit trait + session-liveness port +
discovery primitive + perimeter Bearer-auth Layer kit + identity
types out of pas-external so multiple SDK crates and 1st-party
services (chat-auth, chat-api) all consume the same primitives.
Surface (Slice 1a)
error::SdkCoreError— narrow error type for sdk-core primitives.types::{Ppnum, PpnumId, SessionId, UserId, KeyId}— SDK-shared identity types.Ppnum::TryFrom<String>is the validated boundary.audit::*—AuditSinktrait +AuditEvent+VerifyErrorKind+IdTokenFailureKind+RateLimitertrait +RateLimitKey+compose_source_id+compose_id_token_source_id. Plus the in-tree utility impls (NoopAuditSink,MemoryAuditSink,MemoryRateLimiter,RateLimitedAuditSink) — utility impls live here too because the audit module is one cohesive unit.session_liveness::{SessionLiveness, SessionLivenessError}— per-request L2 row liveness port. Wired into the verifier slot. Trait-only (nocipher/livenessAES wrapper code — that stays in pas-external as a feature-gated submodule).
Surface (Slice 1b — populated when verifier cohesive group lands)
verifier::*—BearerVerifiertrait +JwtVerifierimpl +MemoryBearerVerifier+VerifiedClaims+VerifyConfig+VerifyError+JwksCache. Audit decision E (cohesive group — no trait/impl split across crates).
Surface (Slice 2 — populated)
discovery::{Discovery, DiscoveryError, fetch_discovery}— OIDC discovery document fetch (<issuer>/.well-known/openid-configuration). RFC 8414 §3.3 issuer-mismatch defense lives here. Gated onwell-known-fetch(HTTP fetch + URL types).
Surface (Slice 4 — populated)
bearer::*— perimeter Bearer-auth Layer kit.AuthProvider<S>port +BearerAuthLayer<Sess, P>tower::Layer +BearerAuthConfigVerifyError+MemoryAuthProvider<S>(test-support). Gated onaxumfeature. 1st-party services (chat-auth) import direct fromppoppo_sdk_core::bearer::*(audit decision B); 3rd-party consumers (RCW/CTW) reach the same kit throughpas_external::bearer::*re-export (audit decision D).
Surface (Phase E — populated)
token_cache::{TokenCache, TokenCacheConfig, TokenSource, TokenCacheError, ClientCredentialsSource}— JWT retention layer with single-flight refresh.TokenCacheowns aBox<dyn TokenSource>; the built-inClientCredentialsSourcecovers the OAuth2client_credentialsgrant. Gated ontoken-cache(cache+trait) andclient-credentials(HTTP source).interceptor::{AuthInterceptor, BearerCredential}— tonic syncInterceptorthat attachesAuthorization: Bearer <token>per outgoing gRPC call. Constructed from a pre-fetchedBearerCredential(one instance per call). Gated ontonic-interceptor.
Out of scope (later phases)
scopes::*— sealed-trait family parent for SDK-specific scope marker types.