lib

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

conformance.rs (4254B)


      1 use radroots_signing::{
      2     Error, Signer,
      3     capability::{CancellationSupport, SignerCapability, SignerKind},
      4     error::{CATALOG, Kind},
      5     recovery::ReplayCapability,
      6     request::{CancellationPolicy, SignPolicy},
      7 };
      8 
      9 #[test]
     10 fn public_error_catalog_is_unique_consistent_and_protocol_redacted() {
     11     let mut codes = std::collections::BTreeSet::new();
     12     for descriptor in CATALOG.iter().copied() {
     13         assert!(codes.insert(descriptor.code()));
     14         let error = Error::new(descriptor.kind());
     15         assert_eq!(error.kind(), descriptor.kind());
     16         assert_eq!(error.code(), descriptor.code());
     17         assert_eq!(error.class(), descriptor.class());
     18         assert_eq!(error.retryable(), descriptor.retryable());
     19         assert_eq!(error.recovery_actions(), descriptor.recovery_actions());
     20         let report = error.to_report(None);
     21         assert_eq!(report.code().as_str(), descriptor.code());
     22         assert_eq!(report.message().as_str(), "[redacted]");
     23     }
     24     assert_eq!(codes.len(), Kind::ALL.len());
     25 }
     26 
     27 #[test]
     28 fn deadline_and_cancellation_contracts_are_explicit() {
     29     let error = SignPolicy::new(0, CancellationPolicy::LocalCooperative)
     30         .expect_err("zero deadline must fail");
     31     assert_eq!(error.kind(), Kind::InvalidArgument);
     32 
     33     let local = SignPolicy::new(42, CancellationPolicy::LocalCooperative).expect("local policy");
     34     let remote =
     35         SignPolicy::new(42, CancellationPolicy::PreservePublishedRequest).expect("remote policy");
     36     assert_eq!(local.deadline_unix_ms(), 42);
     37     assert_eq!(local.cancellation(), CancellationPolicy::LocalCooperative);
     38     assert_eq!(
     39         remote.cancellation(),
     40         CancellationPolicy::PreservePublishedRequest
     41     );
     42 
     43     let capability = SignerCapability::new(
     44         SignerKind::Remote,
     45         ReplayCapability::ExactReplayByRequestId,
     46         CancellationSupport::BeforeAndAfterPublication,
     47         true,
     48         true,
     49     );
     50     assert_eq!(capability.kind(), SignerKind::Remote);
     51     assert_eq!(
     52         capability.replay(),
     53         ReplayCapability::ExactReplayByRequestId
     54     );
     55     assert_eq!(
     56         capability.cancellation(),
     57         CancellationSupport::BeforeAndAfterPublication
     58     );
     59     assert!(capability.reports_progress());
     60     assert!(capability.may_require_authentication());
     61 }
     62 
     63 #[cfg(feature = "serde")]
     64 #[test]
     65 fn policy_wire_labels_are_stable_and_round_trip() {
     66     let policy =
     67         SignPolicy::new(42, CancellationPolicy::PreservePublishedRequest).expect("remote policy");
     68     let json = serde_json::to_string(&policy).expect("serialize policy");
     69     assert!(json.contains("preserve_published_request"));
     70     assert_eq!(
     71         serde_json::from_str::<SignPolicy>(&json).expect("deserialize policy"),
     72         policy
     73     );
     74     assert!(serde_json::from_str::<SignPolicy>(
     75         r#"{"deadline_unix_ms":0,"cancellation":"local_cooperative","deprecated_plan":"deny","managed_signing":"any_validated_source"}"#
     76     )
     77     .is_err());
     78 }
     79 
     80 #[test]
     81 fn public_service_types_preserve_dyn_and_thread_safety() {
     82     fn assert_dyn(_: &dyn Signer) {}
     83     fn assert_send_sync<T: Send + Sync + ?Sized>() {}
     84 
     85     let _ = assert_dyn;
     86     assert_send_sync::<dyn Signer>();
     87     assert_send_sync::<Error>();
     88 }
     89 
     90 #[cfg(feature = "std")]
     91 #[test]
     92 fn native_sources_are_opt_in_and_never_appear_in_diagnostics() {
     93     use std::error::Error as _;
     94 
     95     #[derive(Debug)]
     96     struct Sensitive;
     97 
     98     impl core::fmt::Display for Sensitive {
     99         fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    100             formatter.write_str("nsec1-integration-secret")
    101         }
    102     }
    103 
    104     impl std::error::Error for Sensitive {}
    105 
    106     let error = Error::with_source(Kind::SignerUnavailable, Sensitive);
    107     assert!(error.source().is_some());
    108     assert!(!error.to_string().contains("nsec1"));
    109     assert!(!format!("{error:?}").contains("nsec1"));
    110     assert!(!serde_or_debug_report(&error).contains("nsec1"));
    111 }
    112 
    113 #[cfg(all(feature = "std", feature = "serde"))]
    114 fn serde_or_debug_report(error: &Error) -> String {
    115     serde_json::to_string(&error.to_report(None)).expect("serialize report")
    116 }
    117 
    118 #[cfg(all(feature = "std", not(feature = "serde")))]
    119 fn serde_or_debug_report(error: &Error) -> String {
    120     format!("{:?}", error.to_report(None))
    121 }