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