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
//! The **write** side of the revocation split.
//!
//! Edge-verifiable auth (R019) keeps revocation's two sides physically apart.
//! This crate holds the origin half:
//!
//! - [`RevocationWriter`] — the **cold path**, run at the origin on logout /
//! device-revoke. Adds a token's `jti` to the set.
//! - The **hot-path** reader (`cheers_verify::RevocationReader`) lives in
//! `cheers-verify` — the verify-only edge holds it without the power to revoke
//! anyone else's sessions.
//!
//! The set is **eventually consistent** by design: a `revoke` here propagates to
//! edge readers asynchronously (KV replication / gossip), bounded by the access
//! token TTL (see [`SessionPolicy`](crate::session::SessionPolicy)). Full
//! contract on `cheers_verify::RevocationReader`.
//!
//! # Revoking a session vs. a whole login
//!
//! The set is keyed on `jti`, so [`RevocationWriter::revoke`] kills **one**
//! access token immediately (edge-visible within the propagation window). The
//! coarser flows compose it with the refresh cold path:
//!
//! - **Logout / single device-revoke:** call
//! [`RefreshStore::revoke_chain`](crate::store::RefreshStore::revoke_chain) so
//! the chain can mint no *further* access tokens, and `revoke(jti)` for the
//! session's current access token. Any access tokens already issued on that
//! chain die on their own within the access TTL.
//! - **Account-wide revoke:** revoke every chain via the
//! [`UserStore`](crate::store::UserStore) device list; same TTL bound applies.
//!
//! [`SessionAuthority`](crate::session::SessionAuthority) is where these calls
//! are composed — it holds both the [`RevocationWriter`] and the
//! [`RefreshStore`](crate::store::RefreshStore).
use async_trait;
use StoreError;
/// Origin-side revocation write. Held by
/// [`SessionAuthority`](crate::session::SessionAuthority) on the cold path.