Skip to main content

codlet_core/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4//! # codlet-core
5//!
6//! Runtime-neutral authentication primitives. This crate contains pure types,
7//! policy objects, cryptographic lookup-key derivation, lifecycle state
8//! machines, storage traits, and audit events. It deliberately contains no web
9//! framework, database, or async-executor dependencies (RFC-002).
10//!
11//! ## Boundary
12//!
13//! codlet authenticates a subject. The host application authorizes that
14//! subject (RFC-001). Nothing in this crate decides community membership,
15//! roles, permissions, or resource access.
16//!
17//! ## Status
18//!
19//! This release completes the M3 primitive layer:
20//!
21//! - [`code`]    — code policy, generation, normalization, validation (RFC-003)
22//! - [`hashing`] — HMAC lookup-key derivation, key providers, domain
23//!                 separation, key versioning (RFC-004)
24//! - [`rng`]     — fail-closed randomness abstraction (RFC-020)
25//! - [`secret`]  — redacted secret newtypes and opaque IDs (RFC-019)
26//! - [`clock`]   — `Clock` trait for testable time (RFC-020)
27//! - [`state`]   — pure lifecycle classifiers: claim, session, form-token
28//!                 consume (RFC-005/006/007)
29//! - [`store`]   — `CodeStore`, `SessionStore`, `FormTokenStore`,
30//!                 `RateLimitStore` traits (RFC-005/006/007/008)
31//! - [`cookie`]  — secure cookie policy and builder (RFC-006)
32//! - [`audit`]   — `CodeAuthEvent` vocabulary and `AuditSink` trait (RFC-012)
33//! - [`metrics`] — `MetricsObserver` trait, counter names, `Outcome` (RFC-024)
34//! - [`admin`]   — `CodeAdminStore` extension trait, `CodeMeta`, admin API
35//!                 (RFC-030)
36//! - [`auth`]    — high-level orchestration managers: `CodeAuth`,
37//!                 `SessionManager`, `FormTokenManager`, `NoRateLimit`
38//!                 (RFC-013)
39//! - [`error`]   — two-layer error model: internal causes + public-safe
40//!                 failures (RFC-012/021)
41//! - `mem`       — in-memory stores (`test-utils` feature only, RFC-011/008)
42
43/// The codlet wire/format version embedded in domain-separated HMAC inputs.
44///
45/// Bumping this is a breaking change to every stored lookup key and MUST be
46/// accompanied by a key-version migration (RFC-004).
47pub const FORMAT_VERSION: &str = "codlet/v1";
48
49pub mod admin;
50pub mod audit;
51pub mod auth;
52pub mod clock;
53pub mod code;
54pub mod cookie;
55pub mod error;
56pub mod hashing;
57pub mod metrics;
58pub mod rng;
59pub mod secret;
60pub mod state;
61pub mod store;
62
63/// In-memory store implementations for tests and local development.
64///
65/// **Not for production.** Gated behind the `test-utils` feature.
66#[cfg(any(test, feature = "test-utils"))]
67pub mod mem;
68
69// Convenience re-exports for the most common types.
70pub use audit::{AuditSink, CodeAuthEvent, NoopAuditSink};
71pub use auth::{
72    CodeAuth, FormTokenError, FormTokenManager, IssuedSession, NoRateLimit, RedeemError,
73    RedeemSuccess, SessionError, SessionManager,
74};
75pub use clock::{Clock, SystemClock};
76pub use code::{Alphabet, CodePolicy, generate_code, normalize, validate_code_input};
77pub use cookie::{CookiePolicy, CookieProfile, SameSitePolicy};
78pub use error::{
79    CodeInputError, KeyError, PolicyError, PublicFormError, PublicRedemptionError,
80    PublicSessionError, RandomError, RedemptionFailReason,
81};
82pub use hashing::{
83    HmacKeyRef, KeyProvider, KeyVersion, LookupKey, SecretDomain, SecretHasher, StaticKeyProvider,
84};
85pub use metrics::{MetricsObserver, NoopMetrics, Outcome, counter};
86pub use rng::{RandomSource, SystemRandom};
87pub use secret::{
88    CodeId, FormTokenSecret, NormalizedCode, PlainCode, Purpose, ScopeKey, SecretString, SessionId,
89    SessionSecret, SubjectId,
90};
91pub use state::{
92    ClaimOutcome, SessionValidationOutcome, TokenConsumeOutcome, classify_claim, classify_session,
93    classify_token_consume,
94};
95pub use store::{
96    error::{PublicAuthError, StoreError},
97    ratelimit::{
98        RateLimitKey, RateLimitOutcome, RateLimitPolicy, RateLimitStore, RateLimitUnavailable,
99    },
100    token::TokenSubject,
101};
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106
107    #[test]
108    fn format_version_is_stable() {
109        // Guard against an accidental format bump. Changing this string is a
110        // breaking change requiring a key-version migration (RFC-004).
111        assert_eq!(FORMAT_VERSION, "codlet/v1");
112    }
113}