1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//! Framework-agnostic authentication engine for axum + sqlx fullstack apps.
//!
//! `arium` owns the auth domain — password hashing, sessions, OAuth and
//! OpenID Connect (GitHub, Google, Microsoft, or any OIDC issuer), MFA/TOTP,
//! email verification + password reset, RBAC, API tokens, and an audit log —
//! plus the `install` helper that bolts the whole thing onto an
//! `axum::Router`. It has no UI-framework dependency; framework adapters such
//! as `arium-dioxus` wrap these primitives in their own server fns + UI.
//!
//! Typical server-side usage:
//!
//! ```rust,no_run
//! # async fn doc() -> anyhow::Result<()> {
//! use arium::{
//! AuthConfig, Mailer, install, migrator,
//! oauth::{github::GithubProvider, OAuthRegistry},
//! };
//!
//! let pool = sqlx::sqlite::SqlitePoolOptions::new()
//! .connect_with("sqlite://./app.db?mode=rwc".parse()?)
//! .await?;
//! migrator().run(&pool).await?;
//!
//! let mut oauth = OAuthRegistry::new(pool.clone())?;
//! if let Some(gh) = GithubProvider::from_env()? {
//! oauth = oauth.with_provider(gh);
//! }
//!
//! let cfg = AuthConfig::builder(pool.clone(), Mailer::from_env()?)
//! .oauth(oauth)
//! .build()?;
//!
//! // `router` is any `axum::Router` (e.g. your framework's server router).
//! # let router = axum::Router::new();
//! let router = install(router, cfg).await?;
//! # let _ = router;
//! # Ok(()) }
//! ```
//!
//! `oauth-github` is on by default. The opt-in `oauth-oidc`, `oauth-google`,
//! and `oauth-microsoft` features add a generic OpenID Connect provider plus
//! Google/Microsoft presets — each `from_env()`-constructed and registered the
//! same way as `GithubProvider` above.
//!
//! ## Per-resource authorization
//!
//! Beyond global RBAC (flat permission tokens), the `authz` module adds
//! relationship-based checks — "what role does this user hold on *this*
//! resource?" Implement `authz::ResourceAuthority` over your own membership
//! storage and guard resource-scoped mutations with `require_resource`; it
//! does a fresh per-request lookup and default-denies. arium ships no
//! membership table — the app owns that storage; arium owns the enforcement
//! boundary and the `ResourceRole` lattice.
/// Wire types shared with framework adapters and clients, re-exported from the
/// standalone `arium-wire` crate so `arium::wire::*` keeps resolving.
pub use arium_wire as wire;
/// Bearer-token authentication: the axum middleware that turns an
/// `Authorization: Bearer <token>` header into an [`api_key::ApiKeyUser`]
/// request extension, applied automatically by [`install`]. Gated on `tokens`
/// (it hashes the presented token with `auth::tokens`).
/// Per-resource authorization, re-exported from the standalone [`arium_authz`]
/// crate so `arium::authz::*` and `arium::membership::*` keep resolving for
/// existing code (and the framework adapters). The global↔resource bridge
/// (`require_resource_or_permission`) and the bundled `SqlMembershipStore`
/// stay in this crate — they touch the auth engine and its schema.
pub use ;
pub use ;
pub use RateLimitConfig;
// Per-resource authz primitives + lifecycle composites — flattened to the
// crate root, sourced from arium-authz.
pub use ;
// The global↔resource composition bridge lives here (it reads the auth
// engine's permission set).
pub use ApiKeyUser;
pub use ;
pub use ;
pub use install;
pub use SqlMembershipStore;
/// Returns the embedded migrator that creates the `users`, `oauth_accounts`,
/// `roles`, `audit_events`, `api_keys`, and related tables arium owns.
///
/// Run this once at startup before installing the router:
///
/// ```rust,no_run
/// # async fn doc() -> anyhow::Result<()> {
/// # let pool: arium::pool::Pool = unimplemented!();
/// arium::migrator().run(&pool).await?;
/// # Ok(()) }
/// ```
///
/// This migrator does **not** create the `arium_resource_members` table; that
/// lives in [`membership_migrator`] (the `sql-membership` feature) so apps that
/// own their own membership table never get a dead table. Run both migrators
/// (core first — `arium_resource_members` has an FK to `users`) when using the
/// bundled [`SqlMembershipStore`](sql_membership::SqlMembershipStore).
///
/// Returned with `ignore_missing = true` so consumers can keep their own
/// domain migrations in the same `_sqlx_migrations` table without the
/// "version X was previously applied but is missing in the resolved
/// migrations" cross-migrator error firing on every startup. The dialect
/// (sqlite vs postgres) is selected by the active backend feature.
/// Returns the embedded migrator. See the sqlite-feature variant for the
/// full doc — same contract, postgres dialect.
/// Returns the migrator that creates the `arium_resource_members` table backing
/// the bundled [`SqlMembershipStore`](sql_membership::SqlMembershipStore).
///
/// Separate from [`migrator`] so this table is opt-in: only apps that actually
/// use the bundled store (the `sql-membership` feature) ever create it. Run it
/// *after* [`migrator`] — the table has an FK to `users`:
///
/// ```rust,no_run
/// # async fn doc() -> anyhow::Result<()> {
/// # let pool: arium::pool::Pool = unimplemented!();
/// arium::migrator().run(&pool).await?;
/// arium::membership_migrator().run(&pool).await?;
/// # Ok(()) }
/// ```
///
/// `ignore_missing = true` for the same cross-migrator coexistence reason as
/// [`migrator`] (it shares the `_sqlx_migrations` table).
/// Returns the membership migrator. See the sqlite-feature variant for the
/// full doc — same contract, postgres dialect.
pub use Mailer;
// Wire-types re-exported at the crate root for ergonomics.
pub use ;
pub use ;