Skip to main content

pdk_core/policy_context/
api.rs

1// Copyright (c) 2026, Salesforce, Inc.,
2// All rights reserved.
3// For full license text, see the LICENSE.txt file
4
5//! Data types that exposes metadata for the policy.
6
7use crate::policy_context::metadata::{Api, EnvironmentContext};
8use crate::policy_context::static_policy_context_cache::StaticPolicyContextCache;
9use classy::extract::context::ConfigureContext;
10use classy::extract::FromContext;
11use classy::hl::Service;
12use std::convert::Infallible;
13
14#[derive(Clone, Debug)]
15/// Metadata about the API and the policy.
16pub struct Metadata {
17    /// Metadata regarding the flex instance where the policy is running.
18    pub flex_metadata: FlexMetadata,
19    /// Metadata regarding the policy.
20    pub policy_metadata: PolicyMetadata,
21    /// Metadata regarding the api where the policy is applied.
22    pub api_metadata: ApiMetadata,
23    /// Metadata regarding the management plane.
24    pub platform_metadata: PlatformMetadata,
25}
26
27#[derive(Clone, Debug)]
28/// Information about the Flex Gateway where the policy is running.
29pub struct FlexMetadata {
30    /// Name of the flex instance
31    pub flex_name: String,
32    /// Version of the flex instance
33    pub flex_version: String,
34}
35
36#[derive(Clone, Debug)]
37/// Metadata regarding the policy.
38pub struct PolicyMetadata {
39    /// Name of the policy.
40    pub policy_name: String,
41    /// Namespace of the policy.
42    pub policy_namespace: String,
43    #[cfg(feature = "experimental_filter_name")]
44    /// The name of the filter.
45    pub filter_name: String,
46}
47
48#[derive(Clone, Debug)]
49/// Metadata regarding the api where the policy is applied.
50pub struct ApiMetadata {
51    /// The ID of the API.
52    pub id: Option<String>,
53    /// The name of the API.
54    pub name: Option<String>,
55    /// The version of the API.
56    pub version: Option<String>,
57    /// The base_path of the API.
58    pub base_path: Option<String>,
59    /// The slas associated to the API.
60    pub slas: Option<Vec<ApiSla>>,
61    #[cfg(feature = "experimental")]
62    /// The asset associated to the API.
63    pub asset: Option<ApiAsset>,
64}
65
66#[derive(Clone, Debug, Default)]
67/// Metadata regarding the management plane.
68pub struct PlatformMetadata {
69    /// Organization ID
70    pub organization_id: String,
71    /// Environment ID
72    pub environment_id: String,
73    /// The root organization ID
74    pub root_organization_id: String,
75}
76
77#[derive(Clone, Debug)]
78/// The SLA associated to the API.
79pub struct ApiSla {
80    /// The id of the SLA.
81    pub id: String,
82    /// The tiers associated to the SLA.
83    pub tiers: Vec<Tier>,
84}
85
86#[derive(Clone, Debug)]
87/// The limits associated to a [`ApiSla`]
88pub struct Tier {
89    /// Number of requests allowed on a given time.
90    pub requests: u64,
91    /// Time in which the requests are tracked.
92    pub period_in_millis: u64,
93}
94
95#[derive(Clone, Debug)]
96/// The asset associated to the API.
97pub struct ApiAsset {
98    /// The [`Service`] to use to download the schema.
99    pub service: Service,
100}
101
102impl From<&crate::policy_context::metadata::PolicyMetadata> for Metadata {
103    fn from(value: &crate::policy_context::metadata::PolicyMetadata) -> Self {
104        Metadata {
105            flex_metadata: value.into(),
106            policy_metadata: value.into(),
107            api_metadata: value.into(),
108            platform_metadata: value.into(),
109        }
110    }
111}
112
113impl From<&crate::policy_context::metadata::PolicyMetadata> for FlexMetadata {
114    fn from(value: &crate::policy_context::metadata::PolicyMetadata) -> Self {
115        FlexMetadata {
116            flex_name: value.flex_name().to_string(),
117            flex_version: value
118                .anypoint_environment()
119                .and_then(EnvironmentContext::flex_version)
120                .map(str::to_string)
121                // Will always be set since min flex version is 1.6.1
122                .unwrap_or_default(),
123        }
124    }
125}
126
127impl From<&crate::policy_context::metadata::PolicyMetadata> for PolicyMetadata {
128    fn from(value: &crate::policy_context::metadata::PolicyMetadata) -> Self {
129        PolicyMetadata {
130            policy_name: value.policy_id().to_string(),
131            policy_namespace: value.policy_namespace().to_string(),
132            #[cfg(feature = "experimental_filter_name")]
133            filter_name: value.filter_name().to_string(),
134        }
135    }
136}
137
138impl From<&crate::policy_context::metadata::PolicyMetadata> for ApiMetadata {
139    fn from(value: &crate::policy_context::metadata::PolicyMetadata) -> Self {
140        ApiMetadata {
141            id: value.api_info().map(Api::id).map(str::to_string),
142            name: value.api_info().map(Api::name).map(str::to_string),
143            version: value.api_info().map(Api::version).map(str::to_string),
144            base_path: value
145                .api_info()
146                .and_then(Api::base_path)
147                .map(str::to_string),
148            slas: value
149                .api_tiers()
150                .map(|slas| slas.iter().map(|sla| sla.into()).collect()),
151            #[cfg(feature = "experimental")]
152            asset: value
153                .api_info()
154                .and_then(Api::exchange)
155                .map(|exchange| ApiAsset {
156                    service: exchange.service(),
157                }),
158        }
159    }
160}
161
162impl From<&crate::policy_context::metadata::ApiSla> for ApiSla {
163    fn from(value: &crate::policy_context::metadata::ApiSla) -> Self {
164        ApiSla {
165            id: value.id().to_string(),
166            tiers: value.tiers().iter().map(|s| s.into()).collect(),
167        }
168    }
169}
170
171impl From<&crate::policy_context::metadata::Tier> for Tier {
172    fn from(value: &crate::policy_context::metadata::Tier) -> Self {
173        Tier {
174            requests: value.requests(),
175            period_in_millis: value.period_in_millis(),
176        }
177    }
178}
179
180impl From<&crate::policy_context::metadata::PolicyMetadata> for PlatformMetadata {
181    fn from(value: &crate::policy_context::metadata::PolicyMetadata) -> Self {
182        // PlatformMetadata should always be set since it is read from the registration yaml.
183        value
184            .anypoint_environment()
185            .map(|env| PlatformMetadata {
186                organization_id: env.organization_id().to_string(),
187                environment_id: env.environment_id().to_string(),
188                root_organization_id: env.master_organization_id().to_string(),
189            })
190            .unwrap_or_default()
191    }
192}
193
194impl FromContext<ConfigureContext> for Metadata {
195    type Error = Infallible;
196
197    fn from_context(_context: &ConfigureContext) -> Result<Self, Self::Error> {
198        Ok(Metadata::new())
199    }
200}
201
202impl Metadata {
203    pub fn new() -> Metadata {
204        let context = StaticPolicyContextCache::read_metadata();
205        Metadata::from(context.as_ref())
206    }
207}
208
209impl Default for Metadata {
210    fn default() -> Self {
211        Metadata::new()
212    }
213}