Skip to main content

plexus_auth_core/
lib.rs

1//! Sealed-type primitives for the Plexus auth framework.
2//!
3//! This crate exists to host the Plexus authentication primitives —
4//! `AuthContext`, `VerifiedUser`, `Principal`, and the forthcoming
5//! `Credential<T>`, `Tenanted<S>`, `ForwardDerivation` — behind a crate
6//! boundary that no consuming crate can bypass. The crate boundary, plus
7//! Rust's orphan rules, plus crate-private constructors, escalate the
8//! sealed-type defense from procedural (visibility within plexus-core) to
9//! structural (visibility across crates).
10//!
11//! See `plans/AUTHZ/AUTHZ-0.md` §"Crate-level isolation amplifies the seal"
12//! for the full rationale.
13//!
14//! # Public surface
15//!
16//! - [`AuthContext`] — the runtime auth value carried with every method
17//!   invocation. The shape and current public API are preserved verbatim
18//!   from `plexus-core`'s `plexus::auth` module to keep this migration
19//!   mechanical; tightening the seal on `AuthContext::new` and field
20//!   visibility is tracked as follow-up work (see
21//!   `plans/AUTHZ/AUTHZ-CORE-CRATE-1-RUN-NOTES.md`).
22//! - [`SessionValidator`] — the trait perimeter validators implement.
23//! - [`VerifiedUser`] — sealed proof that an IdP-signed token was verified.
24//! - [`Principal`] — sealed authenticated-actor identity (user, service, anon).
25//! - [`BackendAuthCapabilities`] — capability-advertisement payload served
26//!   at `_info` so generic clients can discover supported auth mechanisms
27//!   (AUTHZ-CORE-3). Composed of [`AuthMechanism`] variants
28//!   (`Bearer`, `Cookie`, `Oidc`, `Anonymous`) and the strong-typed
29//!   primitives [`MethodPath`], [`IssuerUrl`], [`ClientId`],
30//!   [`CookieName`], [`HeaderName`].
31//! - [`Tenant`] — sealed unit of data isolation (AUTHZ-0 layer 4). The
32//!   constructor is crate-private; the only path to a `Tenant` value is
33//!   through the framework's [`TenantResolver`].
34//! - [`TenantResolver`] — derives a `Tenant` from a verified
35//!   `AuthContext`. Reference impls: [`ClaimTenantResolver`] (the 80%
36//!   case) and [`SingleTenantResolver`] (explicit single-tenant
37//!   opt-out).
38//! - [`Credential`] — sealed framework-level credential primitive. The only
39//!   path to a `Credential<T>` value is through [`CredentialMinter::mint`],
40//!   itself reachable only by accepting a framework-injected reference. The
41//!   custom `Serialize` impl emits a sentinel `{"$credential": "<id>"}` by
42//!   default; the dispatch layer routes the inner value to a sidecar via an
43//!   RAII guard while it builds the wire envelope (Tier B Q-WIRE-3).
44//! - [`CredentialMinter`] — the injected service that mints credentials.
45//! - [`CredentialMetadata`] — typed contract describing what the credential
46//!   is and how to attach it on subsequent calls (kind, attach site, scheme,
47//!   scopes, expiry, refresh/revoke hints, issuer, sensitivity).
48//! - [`AuditRecord`] — the audit primitive consumed by AUTHZ default-deny
49//!   dispatch (AUTHZ-CORE-5) and AUTHLANG-3's forwarding-policy path. Carries
50//!   the principal chain, decision, reason, latency, and correlation ID for
51//!   one scope check. [`AuditSink`] is the framework's persistence trait;
52//!   [`TracingAuditSink`] is the default impl emitting `tracing::info!`
53//!   events under `target = "plexus::audit"`.
54//!
55//! # Sealing protections (per AUTHZ-0)
56//!
57//! `VerifiedUser` and `Principal` are introduced here with the strict seal
58//! the AUTHZ-0 doc calls for:
59//!
60//! 1. **No fabrication.** Constructors are `pub(crate)` and callable only
61//!    from inside `plexus-auth-core`. The trybuild test
62//!    `tests/compile_fail/seal_*.rs` asserts this.
63//! 2. **No backdoor `From`/`Into`.** Orphan rules forbid implementing
64//!    foreign traits for foreign types from a third crate; only this crate
65//!    can add such impls.
66//! 3. **No accidental `Default`.** Explicitly NOT derived.
67//! 4. **No leaky `Deserialize`.** Not derived for these types; raw JSON
68//!    cannot fabricate a sealed value.
69//! 5. **No mutation.** Fields are private; no setters; even with a sealed
70//!    value in hand, no caller can mutate it.
71//!
72//! `AuthContext` retains its current public constructors (`new`,
73//! `anonymous`) and `pub` fields for now, to preserve the public API that
74//! callers across the workspace depend on. The crate boundary still gives
75//! `AuthContext` the orphan-rule protection (no foreign `From`/`Into` from
76//! third crates) and a single audit point for the type. Tightening the
77//! `AuthContext` seal to match `VerifiedUser`/`Principal` is the next step
78//! in the auth track and lands as a follow-up ticket.
79
80/// Crate version, populated at compile time from `CARGO_PKG_VERSION`.
81///
82/// Exposed so the `plexus-rpc` umbrella can stamp it into the
83/// `Capabilities` manifest backends embed in `_info`. See UMB-2.
84pub const VERSION: &str = env!("CARGO_PKG_VERSION");
85
86pub mod audit;
87pub mod auth;
88pub mod capabilities;
89pub mod credential;
90pub mod principal;
91pub mod tenant;
92pub mod verified_user;
93
94pub mod forward;
95
96pub use audit::{
97    AuditDecision, AuditDenyReason, AuditRecord, AuditRecordKind, AuditSink, ForwardPolicyApplied,
98    RoleName, ScopeCheck, SensitiveField, SessionId, TracingAuditSink, UserId,
99};
100pub use auth::{AuthContext, SessionValidator};
101pub use capabilities::{
102    AuthMechanism, BackendAuthCapabilities, BackendAuthCapabilitiesError, ClientId, ClientIdError,
103    CookieName, CookieNameError, HeaderName, HeaderNameError, IssuerUrl, IssuerUrlError,
104    MethodPath, MethodPathError,
105};
106#[allow(deprecated)]
107pub use credential::CredentialsRegistry;
108pub use credential::{
109    AttachmentSite, CapturedCredential, Credential, CredentialFieldMarker, CredentialId,
110    CredentialIssuer, CredentialKind, CredentialKindName, CredentialMetadata, CredentialMinter,
111    CredentialScheme, CredentialsRegistryFallback, CredentialsRegistryProbe, DispatchSidecar,
112    HasCredentialMarkers, Origin, ParamName, Scope,
113};
114pub use forward::{
115    Anonymous, CallSite, ForwardDerivation, ForwardPolicy, ForwardPolicyName, IdentityOnly,
116    PassThrough, ANONYMOUS_NAME, IDENTITY_ONLY_NAME, PASS_THROUGH_NAME,
117};
118pub use principal::{Principal, ServiceIdentity};
119pub use tenant::{
120    ClaimTenantResolver, Scoped, SingleTenantResolver, Tenant, TenantBoundary, TenantError,
121    TenantResolver, TenantScopedStore, Tenanted,
122};
123pub use verified_user::VerifiedUser;