ssi_status/
lib.rs

1use std::time::Duration;
2
3mod r#impl;
4use iref::Uri;
5pub use r#impl::*;
6pub mod client;
7
8/// Encoded [`StatusMap`].
9pub trait EncodedStatusMap {
10    type Decoded: StatusMap;
11    type DecodeError: std::error::Error;
12
13    fn decode(self) -> Result<Self::Decoded, Self::DecodeError>;
14}
15
16#[derive(Debug, Default, Clone, Copy)]
17pub struct FromBytesOptions {
18    /// Allow unsecured claims.
19    pub allow_unsecured: bool,
20}
21
22impl FromBytesOptions {
23    pub const ALLOW_UNSECURED: Self = Self {
24        allow_unsecured: true,
25    };
26}
27
28pub trait FromBytes<V>: Sized {
29    type Error: std::error::Error;
30
31    #[allow(async_fn_in_trait)]
32    async fn from_bytes_with(
33        bytes: &[u8],
34        media_type: &str,
35        verification_params: &V,
36        options: FromBytesOptions,
37    ) -> Result<Self, Self::Error>;
38
39    #[allow(async_fn_in_trait)]
40    async fn from_bytes(bytes: &[u8], media_type: &str, verifier: &V) -> Result<Self, Self::Error> {
41        Self::from_bytes_with(bytes, media_type, verifier, FromBytesOptions::default()).await
42    }
43}
44
45#[derive(Debug, thiserror::Error)]
46pub enum StatusSizeError {
47    #[error("missing status size")]
48    Missing,
49
50    #[error("invalid status size")]
51    Invalid,
52}
53
54/// Status map.
55///
56/// A status map is a map from [`StatusMapEntry`] to [`StatusMap::Status`].
57/// The [`StatusMapEntry`] is generally found in the credential or claims you
58/// need to verify.
59pub trait StatusMap: Clone {
60    /// Key indexing each status in the map.
61    type Key;
62
63    /// Status bit size type.
64    type StatusSize;
65
66    /// Status type.
67    type Status;
68
69    /// Maximum duration an implementer is allowed to cache a
70    /// status list.
71    fn time_to_live(&self) -> Option<Duration> {
72        None
73    }
74
75    /// Returns a status using the given status size and key.
76    ///
77    /// If `status_size` is `None`, it is assumed that the map itself knows the
78    /// status size. If it does not, a [`StatusSizeError::Missing`] error is
79    /// returned.
80    fn get_by_key(
81        &self,
82        status_size: Option<Self::StatusSize>,
83        key: Self::Key,
84    ) -> Result<Option<Self::Status>, StatusSizeError>;
85
86    /// Returns the status associated to the given entry.
87    fn get_entry<E: StatusMapEntry<Key = Self::Key, StatusSize = Self::StatusSize>>(
88        &self,
89        entry: &E,
90    ) -> Result<Option<Self::Status>, StatusSizeError> {
91        self.get_by_key(entry.status_size(), entry.key())
92    }
93}
94
95pub trait StatusMapEntrySet {
96    type Entry<'a>: StatusMapEntry
97    where
98        Self: 'a;
99
100    fn get_entry(&self, purpose: StatusPurpose<&str>) -> Option<Self::Entry<'_>>;
101}
102
103/// Status map entry.
104///
105/// A status map entry is a reference to a particular status in a status map.
106/// It links to a status map, providing a key in this map.
107pub trait StatusMapEntry {
108    /// Key indexing each status in the referenced status list.
109    type Key;
110
111    /// Status map status size type.
112    type StatusSize;
113
114    /// URL to the status map.
115    fn status_list_url(&self) -> &Uri;
116
117    /// Size of each status in the status map, if it is known by the entry.
118    ///
119    /// For some [`StatusMap`] implementations such as
120    /// [`crate::token_status_list::StatusList`] the status size is stored in
121    /// the map, while for some other implementations such as
122    /// [`crate::bitstring_status_list::StatusList`] the status size is stored
123    /// in the entry
124    /// ([`crate::bitstring_status_list::BitstringStatusListEntry`]).
125    ///
126    /// If this function returns `None`, it is assumed that the status size
127    /// will be provided by the status map.
128    fn status_size(&self) -> Option<Self::StatusSize>;
129
130    /// Entry key.
131    fn key(&self) -> Self::Key;
132}
133
134impl<E: StatusMapEntry> StatusMapEntry for &E {
135    type Key = E::Key;
136    type StatusSize = E::StatusSize;
137
138    fn status_list_url(&self) -> &Uri {
139        E::status_list_url(*self)
140    }
141
142    fn status_size(&self) -> Option<Self::StatusSize> {
143        E::status_size(*self)
144    }
145
146    fn key(&self) -> Self::Key {
147        E::key(*self)
148    }
149}
150
151pub enum StatusPurpose<T = String> {
152    /// Cancel the validity of a verifiable credential.
153    ///
154    /// This status is not reversible.
155    Revocation,
156
157    /// Temporarily prevent the acceptance of a verifiable credential.
158    ///
159    /// This status is reversible.
160    Suspension,
161
162    /// Other purpose whose semantics is not supported by `ssi-status`.
163    Other(T),
164}