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
//! The **read** side of the revocation split.
//!
//! Revocation has two physically distinct sides, and edge-verifiable auth (R019)
//! depends on keeping them apart. This crate holds the edge half:
//!
//! - [`RevocationReader`] — the **hot path**, run at the edge on every request.
//! A point membership check (`is_revoked(jti)`) against a locally-replicated,
//! read-mostly set (CF KV / a Yubaba gossip replica).
//! - The **cold path** writer (`RevocationWriter`) lives in `cheers-server` —
//! keeping it out of this crate means a verify-only edge consumer can check
//! revocation without holding the power to revoke anyone else's sessions, the
//! same capability-by-type discipline as the `TokenVerifier` / `TokenMinter`
//! split.
//!
//! # The consistency contract
//!
//! The set is **eventually consistent** by design. A `revoke` at the origin
//! propagates to edge readers asynchronously (KV replication / gossip), so an
//! edge reader may briefly answer `false` for a `jti` the origin has already
//! revoked. That lag is bounded by the **access-token TTL**
//! (`cheers_server::SessionPolicy`): a revoked-but-not-yet-propagated access
//! token outlives its revocation by at most one short TTL, then expires on its
//! own signature.
//!
//! This is sound because auth has no cross-session OLTP — every check validates
//! *one* session, so the global hot path never needs a consistent view across
//! sessions. Revocation membership is the *only* shared auth state the edge
//! reads, and it tolerates lag.
use async_trait;
use StoreError;
/// Edge-side revocation check. The verify-only consumer depends on *this* — it
/// can ask whether a `jti` is revoked but holds no power to revoke.
///
/// `async` + dyn-compatible (via [`async_trait`]) to match the rest of the store
/// surface, so an edge can hold a `dyn RevocationReader` backed by CF KV.