common_access_token/
cat_claims.rs

1//! # CAT-specific Claims
2//!
3//! This module provides helper functions and structures for working with
4//! Common Access Token (CAT) specific claims as defined in the CAT specification.
5//!
6//! ## Available CAT Claims
7//!
8//! - **CATU** (Common Access Token URI) - limits the URI to which the token can provide access
9//! - **CATR** (Common Access Token Renewal) - instructions for token renewal
10//! - **CATM** (Common Access Token Methods) - limits HTTP methods
11//! - **CATREPLAY** - controls token replay behavior
12//! - **CATV** (Common Access Token Version) - CAT specification version
13//! - **CATPOR** (Common Access Token Probability of Rejection) - probabilistic rate limiting
14//! - **CATNIP** (Common Access Token Network IP) - IP address restrictions
15//! - **CATALPN** (Common Access Token ALPN) - TLS ALPN protocol restrictions
16//! - **CATH** (Common Access Token Header) - HTTP header requirements
17//! - **CATGEOISO3166** - geographic country/region restrictions
18//! - **CATGEOCOORD** - geographic coordinate restrictions
19//! - **CATGEOALT** - altitude restrictions
20//! - **CATTPK** (Common Access Token TLS Public Key) - TLS public key pinning
21//! - **CATDPOP** (Common Access Token DPoP Settings) - DPoP configuration
22//! - **CATIF** (Common Access Token If) - conditional logic
23//! - **CATIFDATA** (Common Access Token If Data) - data for conditional evaluation
24//!
25//! ## CATU Claim (URI Validation)
26//!
27//! The CATU claim allows you to specify URI component restrictions. For example:
28//!
29//! ```rust
30//! use common_access_token::{catu, uri_components, cat_keys};
31//! use std::collections::BTreeMap;
32//!
33//! // Create a CATU claim for URI validation
34//! let mut catu_components = BTreeMap::new();
35//!
36//! // Restrict to https scheme
37//! catu_components.insert(uri_components::SCHEME, catu::exact_match("https"));
38//!
39//! // Restrict to example.com host
40//! catu_components.insert(uri_components::HOST, catu::suffix_match(".example.com"));
41//!
42//! // Restrict to paths starting with /api
43//! catu_components.insert(uri_components::PATH, catu::prefix_match("/api"));
44//!
45//! // Create the CATU claim
46//! let catu_claim = catu::create(catu_components);
47//! ```
48//!
49//! ## CATM Claim (HTTP Methods)
50//!
51//! The CATM claim restricts which HTTP methods are allowed:
52//!
53//! ```rust
54//! use common_access_token::{catm, cat_keys};
55//!
56//! // Create a CATM claim allowing only GET and HEAD methods
57//! let allowed_methods = vec!["GET", "HEAD"];
58//! let catm_claim = catm::create(allowed_methods);
59//! ```
60//!
61//! ## CATREPLAY Claim (Replay Protection)
62//!
63//! The CATREPLAY claim controls token replay behavior:
64//!
65//! ```rust
66//! use common_access_token::{catreplay, cat_keys};
67//!
68//! // Create a CATREPLAY claim that prohibits token reuse
69//! let catreplay_claim = catreplay::prohibited();
70//!
71//! // Or allow token reuse
72//! let catreplay_permitted = catreplay::permitted();
73//!
74//! // Or enable reuse detection
75//! let catreplay_detect = catreplay::reuse_detection();
76//! ```
77//!
78//! ## CATR Claim (Token Renewal)
79//!
80//! The CATR claim provides instructions for token renewal:
81//!
82//! ```rust
83//! use common_access_token::{catr, cat_keys};
84//! use common_access_token::current_timestamp;
85//!
86//! let now = current_timestamp();
87//!
88//! // Create an automatic renewal claim
89//! // This extends expiration by 3600 seconds with a deadline 3000 seconds from now
90//! let renewal_params = catr::automatic_renewal(3600, Some((now + 3000) as i64));
91//! let catr_claim = catr::create(renewal_params);
92//!
93//! // Or create a cookie-based renewal claim
94//! let cookie_renewal = catr::cookie_renewal(
95//!     3600,
96//!     Some((now + 3000) as i64),
97//!     Some("session"),
98//!     Some(vec!["Secure", "HttpOnly"])
99//! );
100//! ```
101
102use crate::header::CborValue;
103use std::collections::BTreeMap;
104
105/// CAT-specific claim keys
106pub mod keys {
107    use crate::constants::cat_keys;
108
109    /// Common Access Token Replay (catreplay) claim key
110    pub const CATREPLAY: i32 = cat_keys::CATREPLAY;
111    /// Common Access Token Probability of Rejection (catpor) claim key
112    pub const CATPOR: i32 = cat_keys::CATPOR;
113    /// Common Access Token Version (catv) claim key
114    pub const CATV: i32 = cat_keys::CATV;
115    /// Common Access Token Network IP (catnip) claim key
116    pub const CATNIP: i32 = cat_keys::CATNIP;
117    /// Common Access Token URI (catu) claim key
118    pub const CATU: i32 = cat_keys::CATU;
119    /// Common Access Token Methods (catm) claim key
120    pub const CATM: i32 = cat_keys::CATM;
121    /// Common Access Token ALPN (catalpn) claim key
122    pub const CATALPN: i32 = cat_keys::CATALPN;
123    /// Common Access Token Header (cath) claim key
124    pub const CATH: i32 = cat_keys::CATH;
125    /// Common Access Token Geographic ISO3166 (catgeoiso3166) claim key
126    pub const CATGEOISO3166: i32 = cat_keys::CATGEOISO3166;
127    /// Common Access Token Geographic Coordinate (catgeocoord) claim key
128    pub const CATGEOCOORD: i32 = cat_keys::CATGEOCOORD;
129    /// Common Access Token Altitude (catgeoalt) claim key
130    pub const CATGEOALT: i32 = cat_keys::CATGEOALT;
131    /// Common Access Token TLS Public Key (cattpk) claim key
132    pub const CATTPK: i32 = cat_keys::CATTPK;
133    /// Common Access Token If Data (catifdata) claim key
134    pub const CATIFDATA: i32 = cat_keys::CATIFDATA;
135    /// Common Access Token DPoP Settings (catdpop) claim key
136    pub const CATDPOP: i32 = cat_keys::CATDPOP;
137    /// Common Access Token If (catif) claim key
138    pub const CATIF: i32 = cat_keys::CATIF;
139    /// Common Access Token Renewal (catr) claim key
140    pub const CATR: i32 = cat_keys::CATR;
141}
142
143/// Helper functions for creating CATU (Common Access Token URI) claims
144pub mod catu {
145    use super::*;
146    use crate::constants::match_types;
147
148    /// Creates a CATU claim with the specified URI component restrictions
149    pub fn create(components: BTreeMap<i32, BTreeMap<i32, CborValue>>) -> CborValue {
150        let mut map = BTreeMap::new();
151        for (component_key, match_map) in components {
152            let mut inner_map = BTreeMap::new();
153            for (match_type, match_value) in match_map {
154                inner_map.insert(match_type, match_value);
155            }
156            map.insert(component_key, CborValue::Map(inner_map));
157        }
158        CborValue::Map(map)
159    }
160
161    /// Creates a match condition for exact text matching
162    pub fn exact_match(text: &str) -> BTreeMap<i32, CborValue> {
163        let mut map = BTreeMap::new();
164        map.insert(match_types::EXACT, CborValue::Text(text.to_string()));
165        map
166    }
167
168    /// Creates a match condition for prefix matching
169    pub fn prefix_match(prefix: &str) -> BTreeMap<i32, CborValue> {
170        let mut map = BTreeMap::new();
171        map.insert(match_types::PREFIX, CborValue::Text(prefix.to_string()));
172        map
173    }
174
175    /// Creates a match condition for suffix matching
176    pub fn suffix_match(suffix: &str) -> BTreeMap<i32, CborValue> {
177        let mut map = BTreeMap::new();
178        map.insert(match_types::SUFFIX, CborValue::Text(suffix.to_string()));
179        map
180    }
181
182    /// Creates a match condition for contains matching
183    pub fn contains_match(text: &str) -> BTreeMap<i32, CborValue> {
184        let mut map = BTreeMap::new();
185        map.insert(match_types::CONTAINS, CborValue::Text(text.to_string()));
186        map
187    }
188
189    /// Creates a match condition for regex matching
190    pub fn regex_match(pattern: &str, groups: Vec<Option<String>>) -> BTreeMap<i32, CborValue> {
191        let mut map = BTreeMap::new();
192
193        let mut array = vec![CborValue::Text(pattern.to_string())];
194        for group in groups {
195            match group {
196                Some(text) => array.push(CborValue::Text(text)),
197                None => array.push(CborValue::Null),
198            }
199        }
200
201        map.insert(match_types::REGEX, CborValue::Array(array));
202        map
203    }
204
205    /// Creates a match condition for SHA-256 matching
206    pub fn sha256_match(hash: Vec<u8>) -> BTreeMap<i32, CborValue> {
207        let mut map = BTreeMap::new();
208        map.insert(match_types::SHA256, CborValue::Bytes(hash));
209        map
210    }
211
212    /// Creates a match condition for SHA-512/256 matching
213    pub fn sha512_256_match(hash: Vec<u8>) -> BTreeMap<i32, CborValue> {
214        let mut map = BTreeMap::new();
215        map.insert(match_types::SHA512_256, CborValue::Bytes(hash));
216        map
217    }
218}
219
220/// Helper functions for creating CATR (Common Access Token Renewal) claims
221pub mod catr {
222    use super::*;
223    use crate::constants::{renewal_params, renewal_types};
224
225    /// Creates a CATR claim with the specified renewal parameters
226    pub fn create(params: BTreeMap<i32, CborValue>) -> CborValue {
227        CborValue::Map(params)
228    }
229
230    /// Creates an automatic renewal claim
231    pub fn automatic_renewal(exp_add: i64, deadline: Option<i64>) -> BTreeMap<i32, CborValue> {
232        let mut map = BTreeMap::new();
233        map.insert(
234            renewal_params::TYPE,
235            CborValue::Integer(renewal_types::AUTOMATIC as i64),
236        );
237        map.insert(renewal_params::EXPADD, CborValue::Integer(exp_add));
238
239        if let Some(deadline_value) = deadline {
240            map.insert(renewal_params::DEADLINE, CborValue::Integer(deadline_value));
241        }
242
243        map
244    }
245
246    /// Creates a cookie renewal claim
247    pub fn cookie_renewal(
248        exp_add: i64,
249        deadline: Option<i64>,
250        cookie_name: Option<&str>,
251        additional_params: Option<Vec<&str>>,
252    ) -> BTreeMap<i32, CborValue> {
253        let mut map = BTreeMap::new();
254        map.insert(
255            renewal_params::TYPE,
256            CborValue::Integer(renewal_types::COOKIE as i64),
257        );
258        map.insert(renewal_params::EXPADD, CborValue::Integer(exp_add));
259
260        if let Some(deadline_value) = deadline {
261            map.insert(renewal_params::DEADLINE, CborValue::Integer(deadline_value));
262        }
263
264        if let Some(name) = cookie_name {
265            map.insert(
266                renewal_params::COOKIE_NAME,
267                CborValue::Text(name.to_string()),
268            );
269        }
270
271        if let Some(params) = additional_params {
272            let params_array: Vec<CborValue> = params
273                .into_iter()
274                .map(|s| CborValue::Text(s.to_string()))
275                .collect();
276            map.insert(
277                renewal_params::COOKIE_PARAMS,
278                CborValue::Array(params_array),
279            );
280        }
281
282        map
283    }
284
285    /// Creates a header renewal claim
286    pub fn header_renewal(
287        exp_add: i64,
288        deadline: Option<i64>,
289        header_name: Option<&str>,
290        additional_params: Option<Vec<&str>>,
291    ) -> BTreeMap<i32, CborValue> {
292        let mut map = BTreeMap::new();
293        map.insert(
294            renewal_params::TYPE,
295            CborValue::Integer(renewal_types::HEADER as i64),
296        );
297        map.insert(renewal_params::EXPADD, CborValue::Integer(exp_add));
298
299        if let Some(deadline_value) = deadline {
300            map.insert(renewal_params::DEADLINE, CborValue::Integer(deadline_value));
301        }
302
303        if let Some(name) = header_name {
304            map.insert(
305                renewal_params::HEADER_NAME,
306                CborValue::Text(name.to_string()),
307            );
308        }
309
310        if let Some(params) = additional_params {
311            let params_array: Vec<CborValue> = params
312                .into_iter()
313                .map(|s| CborValue::Text(s.to_string()))
314                .collect();
315            map.insert(
316                renewal_params::HEADER_PARAMS,
317                CborValue::Array(params_array),
318            );
319        }
320
321        map
322    }
323
324    /// Creates a redirect renewal claim
325    pub fn redirect_renewal(
326        exp_add: i64,
327        deadline: Option<i64>,
328        status_code: Option<i64>,
329    ) -> BTreeMap<i32, CborValue> {
330        let mut map = BTreeMap::new();
331        map.insert(
332            renewal_params::TYPE,
333            CborValue::Integer(renewal_types::REDIRECT as i64),
334        );
335        map.insert(renewal_params::EXPADD, CborValue::Integer(exp_add));
336
337        if let Some(deadline_value) = deadline {
338            map.insert(renewal_params::DEADLINE, CborValue::Integer(deadline_value));
339        }
340
341        if let Some(code) = status_code {
342            map.insert(renewal_params::STATUS_CODE, CborValue::Integer(code));
343        }
344
345        map
346    }
347}
348
349/// Helper functions for creating CATM (Common Access Token Methods) claims
350pub mod catm {
351    use super::*;
352
353    /// Creates a CATM claim with the specified HTTP methods
354    pub fn create(methods: Vec<&str>) -> Vec<CborValue> {
355        methods
356            .into_iter()
357            .map(|s| CborValue::Text(s.to_string()))
358            .collect()
359    }
360}
361
362/// Helper functions for creating CATREPLAY claims
363pub mod catreplay {
364    use super::*;
365    use crate::constants::replay_values;
366
367    /// Creates a CATREPLAY claim with the specified value
368    pub fn create(value: i32) -> CborValue {
369        CborValue::Integer(value as i64)
370    }
371
372    /// Creates a CATREPLAY claim with "permitted" value
373    pub fn permitted() -> CborValue {
374        CborValue::Integer(replay_values::PERMITTED as i64)
375    }
376
377    /// Creates a CATREPLAY claim with "prohibited" value
378    pub fn prohibited() -> CborValue {
379        CborValue::Integer(replay_values::PROHIBITED as i64)
380    }
381
382    /// Creates a CATREPLAY claim with "reuse detection" value
383    pub fn reuse_detection() -> CborValue {
384        CborValue::Integer(replay_values::REUSE_DETECTION as i64)
385    }
386}
387
388/// Helper functions for creating CATV (Common Access Token Version) claims
389pub mod catv {
390    use super::*;
391
392    /// Creates a CATV claim with version 1
393    pub fn create() -> CborValue {
394        CborValue::Integer(1)
395    }
396
397    /// Creates a CATV claim with a specific version number
398    pub fn with_version(version: i64) -> CborValue {
399        CborValue::Integer(version)
400    }
401}
402
403/// Helper functions for creating CATPOR (Common Access Token Probability of Rejection) claims
404///
405/// CATPOR specifies the probability that a token might be rejected, used for probabilistic
406/// rate limiting or load shedding.
407pub mod catpor {
408    use super::*;
409
410    /// Creates a CATPOR claim with a probability value (0.0 to 1.0)
411    ///
412    /// The probability is encoded as an integer representing the percentage (0-100).
413    ///
414    /// # Example
415    ///
416    /// ```
417    /// use common_access_token::cat_claims::catpor;
418    ///
419    /// // 25% probability of rejection
420    /// let catpor_claim = catpor::create(25);
421    /// ```
422    pub fn create(probability_percent: i64) -> CborValue {
423        CborValue::Integer(probability_percent)
424    }
425}
426
427/// Helper functions for creating CATNIP (Common Access Token Network IP) claims
428///
429/// CATNIP restricts the IP addresses from which the token can be used.
430pub mod catnip {
431    use super::*;
432
433    /// Creates a CATNIP claim with a list of allowed IP addresses or ranges
434    ///
435    /// # Example
436    ///
437    /// ```
438    /// use common_access_token::cat_claims::catnip;
439    ///
440    /// // Allow specific IP addresses
441    /// let catnip_claim = catnip::create(vec!["192.168.1.100", "10.0.0.0/8"]);
442    /// ```
443    pub fn create(ip_addresses: Vec<&str>) -> Vec<CborValue> {
444        ip_addresses
445            .into_iter()
446            .map(|ip| CborValue::Text(ip.to_string()))
447            .collect()
448    }
449
450    /// Creates a CATNIP claim with a single IP address
451    pub fn single(ip_address: &str) -> Vec<CborValue> {
452        vec![CborValue::Text(ip_address.to_string())]
453    }
454}
455
456/// Helper functions for creating CATALPN (Common Access Token ALPN) claims
457///
458/// CATALPN restricts the TLS Application-Layer Protocol Negotiation values.
459pub mod catalpn {
460    use super::*;
461
462    /// Creates a CATALPN claim with a list of allowed ALPN protocols
463    ///
464    /// # Example
465    ///
466    /// ```
467    /// use common_access_token::cat_claims::catalpn;
468    ///
469    /// // Allow HTTP/2 and HTTP/1.1
470    /// let catalpn_claim = catalpn::create(vec!["h2", "http/1.1"]);
471    /// ```
472    pub fn create(protocols: Vec<&str>) -> Vec<CborValue> {
473        protocols
474            .into_iter()
475            .map(|proto| CborValue::Text(proto.to_string()))
476            .collect()
477    }
478
479    /// Creates a CATALPN claim for HTTP/2 only
480    pub fn http2_only() -> Vec<CborValue> {
481        vec![CborValue::Text("h2".to_string())]
482    }
483
484    /// Creates a CATALPN claim for HTTP/1.1 only
485    pub fn http1_only() -> Vec<CborValue> {
486        vec![CborValue::Text("http/1.1".to_string())]
487    }
488}
489
490/// Helper functions for creating CATH (Common Access Token Header) claims
491///
492/// CATH specifies HTTP header requirements or restrictions.
493pub mod cath {
494    use super::*;
495
496    /// Creates a CATH claim with header name-value pairs
497    ///
498    /// # Example
499    ///
500    /// ```
501    /// use common_access_token::cat_claims::cath;
502    /// use std::collections::BTreeMap;
503    ///
504    /// let mut headers = BTreeMap::new();
505    /// headers.insert("X-Custom-Header", "required-value");
506    /// headers.insert("User-Agent", "MyApp/1.0");
507    /// let cath_claim = cath::create(headers);
508    /// ```
509    pub fn create(headers: BTreeMap<&str, &str>) -> CborValue {
510        let mut map = BTreeMap::new();
511        for (i, (key, value)) in headers.iter().enumerate() {
512            let mut header_map = BTreeMap::new();
513            header_map.insert(0, CborValue::Text(key.to_string()));
514            header_map.insert(1, CborValue::Text(value.to_string()));
515            map.insert(i as i32, CborValue::Map(header_map));
516        }
517        CborValue::Map(map)
518    }
519}
520
521/// Helper functions for creating CATGEOISO3166 (Common Access Token Geographic ISO3166) claims
522///
523/// CATGEOISO3166 restricts token usage to specific countries or regions.
524pub mod catgeoiso3166 {
525    use super::*;
526
527    /// Creates a CATGEOISO3166 claim with ISO 3166 country codes
528    ///
529    /// # Example
530    ///
531    /// ```
532    /// use common_access_token::cat_claims::catgeoiso3166;
533    ///
534    /// // Allow usage in US and Canada
535    /// let catgeoiso3166_claim = catgeoiso3166::create(vec!["US", "CA"]);
536    /// ```
537    pub fn create(country_codes: Vec<&str>) -> Vec<CborValue> {
538        country_codes
539            .into_iter()
540            .map(|code| CborValue::Text(code.to_string()))
541            .collect()
542    }
543}
544
545/// Helper functions for creating CATGEOCOORD (Common Access Token Geographic Coordinate) claims
546///
547/// CATGEOCOORD restricts token usage based on geographic coordinates.
548pub mod catgeocoord {
549    use super::*;
550
551    /// Creates a CATGEOCOORD claim with latitude and longitude
552    ///
553    /// # Example
554    ///
555    /// ```
556    /// use common_access_token::cat_claims::catgeocoord;
557    ///
558    /// // Center of New York City
559    /// let catgeocoord_claim = catgeocoord::create(40.7128, -74.0060);
560    /// ```
561    pub fn create(latitude: f64, longitude: f64) -> CborValue {
562        let mut map = BTreeMap::new();
563        // Using i64 representation of coordinates (multiply by 1e7 for precision)
564        map.insert(0, CborValue::Integer((latitude * 10_000_000.0) as i64));
565        map.insert(1, CborValue::Integer((longitude * 10_000_000.0) as i64));
566        CborValue::Map(map)
567    }
568
569    /// Creates a CATGEOCOORD claim with latitude, longitude, and radius in meters
570    pub fn with_radius(latitude: f64, longitude: f64, radius_meters: i64) -> CborValue {
571        let mut map = BTreeMap::new();
572        map.insert(0, CborValue::Integer((latitude * 10_000_000.0) as i64));
573        map.insert(1, CborValue::Integer((longitude * 10_000_000.0) as i64));
574        map.insert(2, CborValue::Integer(radius_meters));
575        CborValue::Map(map)
576    }
577}
578
579/// Helper functions for creating CATGEOALT (Common Access Token Geographic Altitude) claims
580///
581/// CATGEOALT restricts token usage based on altitude.
582pub mod catgeoalt {
583    use super::*;
584
585    /// Creates a CATGEOALT claim with altitude in meters
586    ///
587    /// # Example
588    ///
589    /// ```
590    /// use common_access_token::cat_claims::catgeoalt;
591    ///
592    /// // Sea level
593    /// let catgeoalt_claim = catgeoalt::create(0);
594    /// ```
595    pub fn create(altitude_meters: i64) -> CborValue {
596        CborValue::Integer(altitude_meters)
597    }
598
599    /// Creates a CATGEOALT claim with altitude range (min and max in meters)
600    pub fn range(min_meters: i64, max_meters: i64) -> CborValue {
601        let mut map = BTreeMap::new();
602        map.insert(0, CborValue::Integer(min_meters));
603        map.insert(1, CborValue::Integer(max_meters));
604        CborValue::Map(map)
605    }
606}
607
608/// Helper functions for creating CATTPK (Common Access Token TLS Public Key) claims
609///
610/// CATTPK pins the token to a specific TLS public key or certificate.
611pub mod cattpk {
612    use super::*;
613
614    /// Creates a CATTPK claim with a public key hash
615    ///
616    /// # Example
617    ///
618    /// ```
619    /// use common_access_token::cat_claims::cattpk;
620    ///
621    /// // SHA-256 hash of the public key
622    /// let key_hash = vec![0x01, 0x02, 0x03]; // truncated for example
623    /// let cattpk_claim = cattpk::create(key_hash);
624    /// ```
625    pub fn create(public_key_hash: Vec<u8>) -> CborValue {
626        CborValue::Bytes(public_key_hash)
627    }
628
629    /// Creates a CATTPK claim with multiple public key hashes
630    pub fn multiple(public_key_hashes: Vec<Vec<u8>>) -> Vec<CborValue> {
631        public_key_hashes
632            .into_iter()
633            .map(CborValue::Bytes)
634            .collect()
635    }
636}
637
638/// Helper functions for creating CATDPOP (Common Access Token DPoP Settings) claims
639///
640/// CATDPOP provides settings for Demonstrating Proof-of-Possession.
641pub mod catdpop {
642    use super::*;
643
644    /// Creates a CATDPOP claim with DPoP configuration
645    ///
646    /// # Example
647    ///
648    /// ```
649    /// use common_access_token::cat_claims::catdpop;
650    /// use std::collections::BTreeMap;
651    ///
652    /// let mut dpop_config = BTreeMap::new();
653    /// dpop_config.insert(0, common_access_token::CborValue::Integer(1)); // version
654    /// dpop_config.insert(1, common_access_token::CborValue::Text("RS256".to_string())); // algorithm
655    /// let catdpop_claim = catdpop::create(dpop_config);
656    /// ```
657    pub fn create(config: BTreeMap<i32, CborValue>) -> CborValue {
658        CborValue::Map(config)
659    }
660
661    /// Creates a basic CATDPOP claim requiring DPoP
662    pub fn required() -> CborValue {
663        let mut map = BTreeMap::new();
664        map.insert(0, CborValue::Integer(1)); // required
665        CborValue::Map(map)
666    }
667}
668
669/// Helper functions for creating CATIF (Common Access Token If) claims
670///
671/// CATIF provides conditional logic for token handling.
672pub mod catif {
673    use super::*;
674
675    /// Creates a CATIF claim with conditional expressions
676    ///
677    /// # Example
678    ///
679    /// ```
680    /// use common_access_token::cat_claims::catif;
681    /// use std::collections::BTreeMap;
682    ///
683    /// let mut condition = BTreeMap::new();
684    /// condition.insert(0, common_access_token::CborValue::Text("status".to_string()));
685    /// condition.insert(1, common_access_token::CborValue::Text("eq".to_string()));
686    /// condition.insert(2, common_access_token::CborValue::Integer(200));
687    /// let catif_claim = catif::create(condition);
688    /// ```
689    pub fn create(condition: BTreeMap<i32, CborValue>) -> CborValue {
690        CborValue::Map(condition)
691    }
692}
693
694/// Helper functions for creating CATIFDATA (Common Access Token If Data) claims
695///
696/// CATIFDATA provides data for conditional evaluation in CATIF.
697pub mod catifdata {
698    use super::*;
699
700    /// Creates a CATIFDATA claim with data values
701    ///
702    /// # Example
703    ///
704    /// ```
705    /// use common_access_token::cat_claims::catifdata;
706    /// use std::collections::BTreeMap;
707    ///
708    /// let mut data = BTreeMap::new();
709    /// data.insert(0, common_access_token::CborValue::Text("user_role".to_string()));
710    /// data.insert(1, common_access_token::CborValue::Text("admin".to_string()));
711    /// let catifdata_claim = catifdata::create(data);
712    /// ```
713    pub fn create(data: BTreeMap<i32, CborValue>) -> CborValue {
714        CborValue::Map(data)
715    }
716}