Skip to main content

forge_ir/
security.rs

1//! Security schemes and requirements.
2
3use serde::{Deserialize, Serialize};
4
5use crate::value::ValueRef;
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub struct SecurityScheme {
9    pub id: String,
10    pub kind: SecuritySchemeKind,
11    #[serde(default, skip_serializing_if = "Option::is_none")]
12    pub documentation: Option<String>,
13    /// OAS 3.2 `deprecated` flag. Generators should surface this as a
14    /// deprecation hint (doc comment, `@deprecated`, etc.) so consumers
15    /// migrate off the scheme. Defaults to `false`.
16    #[serde(default, skip_serializing_if = "is_false")]
17    pub deprecated: bool,
18    /// `x-*` extensions declared on the security scheme object. Compound
19    /// extensions drop with `parser/W-EXTENSION-DROPPED`.
20    #[serde(default, skip_serializing_if = "Vec::is_empty")]
21    pub extensions: Vec<(String, ValueRef)>,
22}
23
24fn is_false(b: &bool) -> bool {
25    !*b
26}
27
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
29#[serde(tag = "type", rename_all = "kebab-case")]
30pub enum SecuritySchemeKind {
31    ApiKey(ApiKeyScheme),
32    HttpBasic,
33    HttpBearer {
34        #[serde(default, skip_serializing_if = "Option::is_none")]
35        bearer_format: Option<String>,
36    },
37    /// OAS 3.0+ `mutualTLS` — client-cert auth (mTLS). The IR carries
38    /// the declaration; certificate provisioning is out of scope and
39    /// left to the consumer's transport configuration.
40    MutualTls,
41    Oauth2(OAuth2Scheme),
42    OpenIdConnect {
43        url: String,
44    },
45}
46
47#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
48pub struct ApiKeyScheme {
49    pub name: String,
50    pub location: ApiKeyLocation,
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
54#[serde(rename_all = "kebab-case")]
55pub enum ApiKeyLocation {
56    Header,
57    Query,
58    Cookie,
59}
60
61#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
62pub struct OAuth2Scheme {
63    pub flows: Vec<OAuth2Flow>,
64}
65
66#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
67pub struct OAuth2Flow {
68    pub kind: OAuth2FlowKind,
69    #[serde(default, skip_serializing_if = "Option::is_none")]
70    pub authorization_url: Option<String>,
71    #[serde(default, skip_serializing_if = "Option::is_none")]
72    pub token_url: Option<String>,
73    #[serde(default, skip_serializing_if = "Option::is_none")]
74    pub refresh_url: Option<String>,
75    #[serde(default, skip_serializing_if = "Vec::is_empty")]
76    pub scopes: Vec<(String, String)>,
77    /// `x-*` extensions declared on the OAuth2 flow object. Compound
78    /// extensions drop with `parser/W-EXTENSION-DROPPED`.
79    #[serde(default, skip_serializing_if = "Vec::is_empty")]
80    pub extensions: Vec<(String, ValueRef)>,
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
84#[serde(rename_all = "kebab-case")]
85pub enum OAuth2FlowKind {
86    Implicit,
87    Password,
88    ClientCredentials,
89    AuthorizationCode,
90}
91
92#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
93pub struct SecurityRequirement {
94    pub scheme_id: String,
95    #[serde(default, skip_serializing_if = "Vec::is_empty")]
96    pub scopes: Vec<String>,
97}