alibi_core/oauth_token_conversion.rs
1//! Physical, operator-controlled OAuth token replacement; never a runtime upgrade.
2
3use crate::{AuthResult, AuthSchema};
4use async_trait::async_trait;
5
6/// Exact physical values reviewed in a trusted ownership manifest.
7///
8/// Ciphertext authentication does **not** prove historical ownership. Operators
9/// must establish that separately before constructing this snapshot. Do not log
10/// snapshots: they may contain plaintext credentials.
11#[derive(Clone)]
12pub struct OAuthTokenSnapshot {
13 pub id: String,
14 pub user_id: String,
15 pub provider_id: String,
16 pub account_id: String,
17 pub tokens: OAuthTokenValues,
18}
19
20/// Nullable physical access, refresh and ID token columns. Deliberately not Debug.
21#[derive(Clone, PartialEq, Eq)]
22pub struct OAuthTokenValues {
23 pub access_token: Option<String>,
24 pub refresh_token: Option<String>,
25 pub id_token: Option<String>,
26}
27
28/// Administrative storage capability, separate from live account operations.
29/// Use a physical adapter, without output transforms or account-update hooks.
30#[async_trait]
31pub trait OAuthTokenConversionStore<S: AuthSchema>: Send + Sync {
32 /// Replace all three token columns in one atomic statement only if the row
33 /// identity, owner and every nullable token equal `observed` exactly.
34 /// Return false for a missing/changed row; leave all other columns untouched.
35 ///
36 /// # Errors
37 /// Returns a storage error without committing a partial token replacement.
38 async fn compare_and_swap_oauth_tokens(
39 &self,
40 observed: &OAuthTokenSnapshot,
41 replacement: &OAuthTokenValues,
42 ) -> AuthResult<bool>;
43}