lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

capability.rs (3615B)


      1 //! Signer capability declarations.
      2 
      3 use crate::recovery::ReplayCapability;
      4 
      5 /// How a signer implementation obtains signatures.
      6 #[non_exhaustive]
      7 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
      8 #[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
      9 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
     10 pub enum SignerKind {
     11     /// A local adapter performs signing without publishing a remote request.
     12     Local,
     13     /// A remote service or device performs signing.
     14     Remote,
     15     /// A composing host mediates signing through an explicit user interaction.
     16     HostMediated,
     17 }
     18 
     19 /// Cancellation behavior advertised by a signer.
     20 #[non_exhaustive]
     21 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
     22 #[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
     23 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
     24 pub enum CancellationSupport {
     25     /// Cancellation is observed only before a remote request is published.
     26     BeforePublication,
     27     /// Cancellation remains observable after publication, without implying
     28     /// rollback of the already-published request.
     29     BeforeAndAfterPublication,
     30 }
     31 
     32 /// Portable signer behavior advertised to a composing host.
     33 #[non_exhaustive]
     34 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
     35 #[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
     36 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
     37 pub struct SignerCapability {
     38     kind: SignerKind,
     39     replay: ReplayCapability,
     40     cancellation: CancellationSupport,
     41     reports_progress: bool,
     42     may_require_authentication: bool,
     43 }
     44 
     45 impl SignerCapability {
     46     /// Creates an explicit capability declaration.
     47     #[must_use]
     48     pub const fn new(
     49         kind: SignerKind,
     50         replay: ReplayCapability,
     51         cancellation: CancellationSupport,
     52         reports_progress: bool,
     53         may_require_authentication: bool,
     54     ) -> Self {
     55         Self {
     56             kind,
     57             replay,
     58             cancellation,
     59             reports_progress,
     60             may_require_authentication,
     61         }
     62     }
     63 
     64     /// Returns the implementation kind.
     65     #[must_use]
     66     pub const fn kind(self) -> SignerKind {
     67         self.kind
     68     }
     69 
     70     /// Returns the exact replay contract.
     71     #[must_use]
     72     pub const fn replay(self) -> ReplayCapability {
     73         self.replay
     74     }
     75 
     76     /// Returns the advertised cancellation contract.
     77     #[must_use]
     78     pub const fn cancellation(self) -> CancellationSupport {
     79         self.cancellation
     80     }
     81 
     82     /// Reports whether the signer emits progress updates.
     83     #[must_use]
     84     pub const fn reports_progress(self) -> bool {
     85         self.reports_progress
     86     }
     87 
     88     /// Reports whether the signer may emit an authentication challenge.
     89     #[must_use]
     90     pub const fn may_require_authentication(self) -> bool {
     91         self.may_require_authentication
     92     }
     93 }
     94 
     95 #[cfg(all(test, feature = "serde"))]
     96 mod tests {
     97     use super::*;
     98 
     99     #[test]
    100     fn capability_round_trips_with_stable_wire_labels() {
    101         let capability = SignerCapability::new(
    102             SignerKind::Remote,
    103             ReplayCapability::ExactReplayByRequestId,
    104             CancellationSupport::BeforeAndAfterPublication,
    105             true,
    106             true,
    107         );
    108         let encoded = serde_json::to_string(&capability).expect("serialize capability");
    109         let decoded: SignerCapability =
    110             serde_json::from_str(&encoded).expect("deserialize capability");
    111 
    112         assert_eq!(decoded, capability);
    113         assert!(encoded.contains("remote"));
    114         assert!(encoded.contains("before_and_after_publication"));
    115     }
    116 }