diff --git a/Cargo.lock b/Cargo.lock index 6dd7c2c7e..36b3ea8c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,9 +85,9 @@ dependencies = [ [[package]] name = "aide" -version = "0.14.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2477554ebf38aea815a9c4729100cfc32f766876c45b9c9c38ef221b9d1a703" +checksum = "4d34f0f6ce85b460bf2f9e7eea6612f217ba700ae14e9e476805d2413480f64b" dependencies = [ "aide-macros", "axum", @@ -108,11 +108,12 @@ dependencies = [ [[package]] name = "aide-macros" -version = "0.8.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8e0d4af7cc08353807aaf80722125a229bf2d67be7fe0b89163c648db3d223" +checksum = "9f2a08f14808f3c46f3e3004b727bace64af44c3c5996d0480a14d3852b1b25a" dependencies = [ "darling", + "proc-macro2", "quote", "syn", ] @@ -2812,7 +2813,6 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" dependencies = [ - "schemars", "serde", ] @@ -4970,6 +4970,26 @@ dependencies = [ "bitflags", ] +[[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "regalloc2" version = "0.11.2" @@ -5344,14 +5364,14 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.22" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" dependencies = [ "chrono", "dyn-clone", - "indexmap 1.9.3", "indexmap 2.9.0", + "ref-cast", "schemars_derive", "serde", "serde_json", @@ -5360,9 +5380,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.22" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +checksum = "5016d94c77c6d32f0b8e08b781f7dc8a90c2007d4e77472cc2807bc10a8438fe" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 68f867595..958ba8e3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ syn2mas = { path = "./crates/syn2mas", version = "=0.17.0-rc.0" } # OpenAPI schema generation and validation [workspace.dependencies.aide] -version = "0.14.2" +version = "0.15.0" features = ["axum", "axum-extra", "axum-json", "axum-query", "macros"] # An `Arc` that can be atomically updated @@ -330,7 +330,7 @@ features = ["yaml", "json"] # IP network address types [workspace.dependencies.ipnetwork] version = "0.20.0" -features = ["serde", "schemars"] +features = ["serde"] # Iterator utilities [workspace.dependencies.itertools] @@ -531,8 +531,8 @@ version = "0.4.5" # JSON Schema generation [workspace.dependencies.schemars] -version = "0.8.22" -features = ["url", "chrono", "preserve_order"] +version = "0.9.0" +features = ["url2", "chrono04", "preserve_order"] # SEC1 encoding format [workspace.dependencies.sec1] diff --git a/crates/config/src/bin/schema.rs b/crates/config/src/bin/schema.rs index 3f409d406..401d52baa 100644 --- a/crates/config/src/bin/schema.rs +++ b/crates/config/src/bin/schema.rs @@ -4,14 +4,15 @@ // SPDX-License-Identifier: AGPL-3.0-only // Please see LICENSE in the repository root for full details. -use schemars::r#gen::SchemaSettings; +use schemars::{ + generate::SchemaSettings, + transform::{AddNullable, RecursiveTransform}, +}; fn main() { - let settings = SchemaSettings::draft07().with(|s| { - s.option_nullable = false; - s.option_add_null_type = false; - }); - let generator = settings.into_generator(); + let generator = SchemaSettings::draft07() + .with_transform(RecursiveTransform(AddNullable::default())) + .into_generator(); let schema = generator.into_root_schema_for::(); serde_json::to_writer_pretty(std::io::stdout(), &schema).expect("Failed to serialize schema"); diff --git a/crates/config/src/schema.rs b/crates/config/src/schema.rs index 2a9aaa914..537c0ffb6 100644 --- a/crates/config/src/schema.rs +++ b/crates/config/src/schema.rs @@ -6,29 +6,22 @@ //! Useful JSON Schema definitions -use schemars::{ - JsonSchema, - r#gen::SchemaGenerator, - schema::{InstanceType, Schema, SchemaObject}, -}; +use std::borrow::Cow; + +use schemars::{JsonSchema, Schema, SchemaGenerator, json_schema}; /// A network hostname pub struct Hostname; impl JsonSchema for Hostname { - fn schema_name() -> String { - "Hostname".to_string() + fn schema_name() -> Cow<'static, str> { + Cow::Borrowed("Hostname") } - fn json_schema(generator: &mut SchemaGenerator) -> Schema { - hostname(generator) + fn json_schema(_generator: &mut SchemaGenerator) -> Schema { + json_schema!({ + "type": "string", + "format": "hostname", + }) } } - -fn hostname(_gen: &mut SchemaGenerator) -> Schema { - Schema::Object(SchemaObject { - instance_type: Some(InstanceType::String.into()), - format: Some("hostname".to_owned()), - ..SchemaObject::default() - }) -} diff --git a/crates/config/src/sections/http.rs b/crates/config/src/sections/http.rs index 8bf4a7588..1c11a8cbc 100644 --- a/crates/config/src/sections/http.rs +++ b/crates/config/src/sections/http.rs @@ -23,19 +23,6 @@ fn default_public_base() -> Url { "http://[::]:8080".parse().unwrap() } -fn http_address_example_1() -> &'static str { - "[::1]:8080" -} -fn http_address_example_2() -> &'static str { - "[::]:8080" -} -fn http_address_example_3() -> &'static str { - "127.0.0.1:8080" -} -fn http_address_example_4() -> &'static str { - "0.0.0.0:8080" -} - #[cfg(not(any(feature = "docker", feature = "dist")))] fn http_listener_assets_path_default() -> Utf8PathBuf { "./frontend/dist/".into() @@ -111,10 +98,10 @@ pub enum BindConfig { Address { /// Host and port on which to listen #[schemars( - example = "http_address_example_1", - example = "http_address_example_2", - example = "http_address_example_3", - example = "http_address_example_4" + example = &"[::1]:8080", + example = &"[::]:8080", + example = &"127.0.0.1:8080", + example = &"0.0.0.0:8080", )] address: String, }, @@ -354,6 +341,7 @@ pub struct HttpConfig { /// List of trusted reverse proxies that can set the `X-Forwarded-For` /// header #[serde(default = "default_trusted_proxies")] + #[schemars(with = "Vec", inner(ip))] pub trusted_proxies: Vec, /// Public URL base from where the authentication service is reachable diff --git a/crates/config/src/sections/secrets.rs b/crates/config/src/sections/secrets.rs index e93817b68..a28be9121 100644 --- a/crates/config/src/sections/secrets.rs +++ b/crates/config/src/sections/secrets.rs @@ -24,10 +24,6 @@ use tracing::info; use super::ConfigurationSection; -fn example_secret() -> &'static str { - "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" -} - /// Password config option. /// /// It either holds the password value directly or references a file where the @@ -204,7 +200,7 @@ struct EncryptionRaw { #[schemars( with = "Option", regex(pattern = r"[0-9a-fA-F]{64}"), - example = "example_secret" + example = &"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" )] #[serde_as(as = "Option")] #[serde(skip_serializing_if = "Option::is_none")] diff --git a/crates/config/src/sections/telemetry.rs b/crates/config/src/sections/telemetry.rs index 0c11e0285..5b71b330e 100644 --- a/crates/config/src/sections/telemetry.rs +++ b/crates/config/src/sections/telemetry.rs @@ -11,10 +11,6 @@ use url::Url; use super::ConfigurationSection; -fn sample_rate_example() -> f64 { - 0.5 -} - /// Propagation format for incoming and outgoing requests #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "lowercase")] @@ -70,7 +66,7 @@ pub struct TracingConfig { /// /// Defaults to `1.0` if not set. #[serde(skip_serializing_if = "Option::is_none")] - #[schemars(example = "sample_rate_example", range(min = 0.0, max = 1.0))] + #[schemars(example = 0.5, range(min = 0.0, max = 1.0))] pub sample_rate: Option, } @@ -123,26 +119,18 @@ impl MetricsConfig { } } -fn sentry_dsn_example() -> &'static str { - "https://public@host:port/1" -} - -fn sentry_environment_example() -> &'static str { - "production" -} - /// Configuration related to the Sentry integration #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] pub struct SentryConfig { /// Sentry DSN - #[schemars(url, example = "sentry_dsn_example")] + #[schemars(url, example = &"https://public@host:port/1")] #[serde(skip_serializing_if = "Option::is_none")] pub dsn: Option, /// Environment to use when sending events to Sentry /// /// Defaults to `production` if not set. - #[schemars(example = "sentry_environment_example")] + #[schemars(example = &"production")] #[serde(skip_serializing_if = "Option::is_none")] pub environment: Option, @@ -150,14 +138,14 @@ pub struct SentryConfig { /// /// Defaults to `1.0` if not set. #[serde(skip_serializing_if = "Option::is_none")] - #[schemars(example = "sample_rate_example", range(min = 0.0, max = 1.0))] + #[schemars(example = 0.5, range(min = 0.0, max = 1.0))] pub sample_rate: Option, /// Sample rate for tracing transactions /// /// Defaults to `0.0` if not set. #[serde(skip_serializing_if = "Option::is_none")] - #[schemars(example = "sample_rate_example", range(min = 0.0, max = 1.0))] + #[schemars(example = 0.5, range(min = 0.0, max = 1.0))] pub traces_sample_rate: Option, } diff --git a/crates/handlers/src/admin/mod.rs b/crates/handlers/src/admin/mod.rs index 6890848ac..1938980dd 100644 --- a/crates/handlers/src/admin/mod.rs +++ b/crates/handlers/src/admin/mod.rs @@ -29,6 +29,7 @@ use mas_router::{ }; use mas_storage::BoxRng; use mas_templates::{ApiDocContext, Templates}; +use schemars::transform::{AddNullable, RecursiveTransform}; use tower_http::cors::{Any, CorsLayer}; mod call_context; @@ -159,8 +160,10 @@ where aide::generate::infer_responses(false); aide::generate::in_context(|ctx| { - ctx.schema = - schemars::r#gen::SchemaGenerator::new(schemars::r#gen::SchemaSettings::openapi3()); + ctx.schema = schemars::generate::SchemaGenerator::new( + schemars::generate::SchemaSettings::openapi3() + .with_transform(RecursiveTransform(AddNullable::default())), + ); }); let mut api = OpenApi::default(); diff --git a/crates/handlers/src/admin/schema.rs b/crates/handlers/src/admin/schema.rs index 99f1c20b7..2c50dcd26 100644 --- a/crates/handlers/src/admin/schema.rs +++ b/crates/handlers/src/admin/schema.rs @@ -6,11 +6,9 @@ //! Common schema definitions -use schemars::{ - JsonSchema, - r#gen::SchemaGenerator, - schema::{InstanceType, Metadata, Schema, SchemaObject, StringValidation}, -}; +use std::borrow::Cow; + +use schemars::{JsonSchema, Schema, SchemaGenerator, json_schema}; /// A type to use for schema definitions of ULIDs /// @@ -18,32 +16,21 @@ use schemars::{ pub struct Ulid; impl JsonSchema for Ulid { - fn schema_name() -> String { - "ULID".to_owned() + fn schema_name() -> Cow<'static, str> { + Cow::Borrowed("ULID") } fn json_schema(_gen: &mut SchemaGenerator) -> Schema { - SchemaObject { - instance_type: Some(InstanceType::String.into()), - - metadata: Some(Box::new(Metadata { - title: Some("ULID".into()), - description: Some("A ULID as per https://github.com/ulid/spec".into()), - examples: vec![ - "01ARZ3NDEKTSV4RRFFQ69G5FAV".into(), - "01J41912SC8VGAQDD50F6APK91".into(), - ], - ..Metadata::default() - })), - - string: Some(Box::new(StringValidation { - pattern: Some(r"^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$".into()), - ..StringValidation::default() - })), - - ..SchemaObject::default() - } - .into() + json_schema!({ + "type": "string", + "title": "ULID", + "description": "A ULID as per https://github.com/ulid/spec", + "examples": [ + "01ARZ3NDEKTSV4RRFFQ69G5FAV", + "01J41912SC8VGAQDD50F6APK91", + ], + "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$", + }) } } @@ -53,27 +40,20 @@ impl JsonSchema for Ulid { pub struct Device; impl JsonSchema for Device { - fn schema_name() -> String { - "DeviceID".to_owned() + fn schema_name() -> Cow<'static, str> { + Cow::Borrowed("DeviceID") } fn json_schema(_gen: &mut SchemaGenerator) -> Schema { - SchemaObject { - instance_type: Some(InstanceType::String.into()), - - metadata: Some(Box::new(Metadata { - title: Some("Device ID".into()), - examples: vec!["AABBCCDDEE".into(), "FFGGHHIIJJ".into()], - ..Metadata::default() - })), - - string: Some(Box::new(StringValidation { - pattern: Some(r"^[A-Za-z0-9._~!$&'()*+,;=:&/-]+$".into()), - ..StringValidation::default() - })), - - ..SchemaObject::default() - } - .into() + json_schema!({ + "type": "string", + "title": "Device ID", + "description": "A device ID as per https://matrix.org/docs/spec/client_server/r0.6.0#device-ids", + "examples": [ + "AABBCCDDEE", + "FFGGHHIIJJ", + ], + "pattern": "^[A-Za-z0-9._~!$&'()*+,;=:&/-]+$", + }) } } diff --git a/crates/handlers/src/admin/v1/policy_data/set.rs b/crates/handlers/src/admin/v1/policy_data/set.rs index bc28e96e3..73dce7307 100644 --- a/crates/handlers/src/admin/v1/policy_data/set.rs +++ b/crates/handlers/src/admin/v1/policy_data/set.rs @@ -58,7 +58,7 @@ fn data_example() -> serde_json::Value { #[derive(Deserialize, JsonSchema)] #[serde(rename = "SetPolicyDataRequest")] pub struct SetPolicyDataRequest { - #[schemars(example = "data_example")] + #[schemars(example = data_example())] pub data: serde_json::Value, } diff --git a/crates/handlers/src/admin/v1/users/set_password.rs b/crates/handlers/src/admin/v1/users/set_password.rs index 06797c3f8..4de8acd73 100644 --- a/crates/handlers/src/admin/v1/users/set_password.rs +++ b/crates/handlers/src/admin/v1/users/set_password.rs @@ -55,16 +55,12 @@ impl IntoResponse for RouteError { } } -fn password_example() -> String { - "hunter2".to_owned() -} - /// # JSON payload for the `POST /api/admin/v1/users/:id/set-password` endpoint #[derive(Deserialize, JsonSchema)] #[schemars(rename = "SetUserPasswordRequest")] pub struct Request { /// The password to set for the user - #[schemars(example = "password_example")] + #[schemars(example = &"hunter2")] password: String, /// Skip the password complexity check diff --git a/crates/iana-codegen/src/generation.rs b/crates/iana-codegen/src/generation.rs index 82f67b05b..8558ef389 100644 --- a/crates/iana-codegen/src/generation.rs +++ b/crates/iana-codegen/src/generation.rs @@ -165,12 +165,12 @@ pub fn json_schema_impl( write!( f, r#"impl schemars::JsonSchema for {} {{ - fn schema_name() -> String {{ - "{}".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> {{ + std::borrow::Cow::Borrowed("{}") }} #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {{ + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema {{ let enums = vec!["#, section.key, section.key, )?; @@ -180,20 +180,14 @@ pub fn json_schema_impl( f, r" // --- - schemars::schema::SchemaObject {{", + schemars::json_schema!({{", )?; if let Some(description) = &member.description { write!( f, - r" - metadata: Some(Box::new(schemars::schema::Metadata {{ - description: Some( - // --- - {}.to_owned(), - ), - ..Default::default() - }})),", + r#" + "description": {},"#, raw_string(description), )?; } @@ -201,34 +195,24 @@ pub fn json_schema_impl( write!( f, r#" - const_value: Some("{}".into()), - ..Default::default() - }} - .into(),"#, + "const": "{}", + }}),"#, member.value )?; } writeln!( f, - r" + r#" ]; let description = {}; - schemars::schema::SchemaObject {{ - metadata: Some(Box::new(schemars::schema::Metadata {{ - description: Some(description.to_owned()), - ..Default::default() - }})), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation {{ - any_of: Some(enums), - ..Default::default() - }})), - ..Default::default() - }} - .into() + schemars::json_schema!({{ + "description": description, + "anyOf": enums, + }}) }} -}}", +}}"#, raw_string(section.doc), ) } diff --git a/crates/iana/src/jose.rs b/crates/iana/src/jose.rs index 8ffc395ca..5f9a84ce4 100644 --- a/crates/iana/src/jose.rs +++ b/crates/iana/src/jose.rs @@ -144,249 +144,105 @@ impl serde::Serialize for JsonWebSignatureAlg { } impl schemars::JsonSchema for JsonWebSignatureAlg { - fn schema_name() -> String { - "JsonWebSignatureAlg".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("JsonWebSignatureAlg") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"HMAC using SHA-256".to_owned(), - ), - ..Default::default() - })), - const_value: Some("HS256".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"HMAC using SHA-384".to_owned(), - ), - ..Default::default() - })), - const_value: Some("HS384".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"HMAC using SHA-512".to_owned(), - ), - ..Default::default() - })), - const_value: Some("HS512".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSASSA-PKCS1-v1_5 using SHA-256".to_owned(), - ), - ..Default::default() - })), - const_value: Some("RS256".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSASSA-PKCS1-v1_5 using SHA-384".to_owned(), - ), - ..Default::default() - })), - const_value: Some("RS384".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSASSA-PKCS1-v1_5 using SHA-512".to_owned(), - ), - ..Default::default() - })), - const_value: Some("RS512".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"ECDSA using P-256 and SHA-256".to_owned(), - ), - ..Default::default() - })), - const_value: Some("ES256".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"ECDSA using P-384 and SHA-384".to_owned(), - ), - ..Default::default() - })), - const_value: Some("ES384".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"ECDSA using P-521 and SHA-512".to_owned(), - ), - ..Default::default() - })), - const_value: Some("ES512".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSASSA-PSS using SHA-256 and MGF1 with SHA-256".to_owned(), - ), - ..Default::default() - })), - const_value: Some("PS256".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSASSA-PSS using SHA-384 and MGF1 with SHA-384".to_owned(), - ), - ..Default::default() - })), - const_value: Some("PS384".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSASSA-PSS using SHA-512 and MGF1 with SHA-512".to_owned(), - ), - ..Default::default() - })), - const_value: Some("PS512".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"No digital signature or MAC performed".to_owned(), - ), - ..Default::default() - })), - const_value: Some("none".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"EdDSA signature algorithms".to_owned(), - ), - ..Default::default() - })), - const_value: Some("EdDSA".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"ECDSA using secp256k1 curve and SHA-256".to_owned(), - ), - ..Default::default() - })), - const_value: Some("ES256K".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"EdDSA using Ed25519 curve".to_owned(), - ), - ..Default::default() - })), - const_value: Some("Ed25519".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"EdDSA using Ed448 curve".to_owned(), - ), - ..Default::default() - })), - const_value: Some("Ed448".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "description": r"HMAC using SHA-256", + "const": "HS256", + }), + // --- + schemars::json_schema!({ + "description": r"HMAC using SHA-384", + "const": "HS384", + }), + // --- + schemars::json_schema!({ + "description": r"HMAC using SHA-512", + "const": "HS512", + }), + // --- + schemars::json_schema!({ + "description": r"RSASSA-PKCS1-v1_5 using SHA-256", + "const": "RS256", + }), + // --- + schemars::json_schema!({ + "description": r"RSASSA-PKCS1-v1_5 using SHA-384", + "const": "RS384", + }), + // --- + schemars::json_schema!({ + "description": r"RSASSA-PKCS1-v1_5 using SHA-512", + "const": "RS512", + }), + // --- + schemars::json_schema!({ + "description": r"ECDSA using P-256 and SHA-256", + "const": "ES256", + }), + // --- + schemars::json_schema!({ + "description": r"ECDSA using P-384 and SHA-384", + "const": "ES384", + }), + // --- + schemars::json_schema!({ + "description": r"ECDSA using P-521 and SHA-512", + "const": "ES512", + }), + // --- + schemars::json_schema!({ + "description": r"RSASSA-PSS using SHA-256 and MGF1 with SHA-256", + "const": "PS256", + }), + // --- + schemars::json_schema!({ + "description": r"RSASSA-PSS using SHA-384 and MGF1 with SHA-384", + "const": "PS384", + }), + // --- + schemars::json_schema!({ + "description": r"RSASSA-PSS using SHA-512 and MGF1 with SHA-512", + "const": "PS512", + }), + // --- + schemars::json_schema!({ + "description": r"No digital signature or MAC performed", + "const": "none", + }), + // --- + schemars::json_schema!({ + "description": r"EdDSA signature algorithms", + "const": "EdDSA", + }), + // --- + schemars::json_schema!({ + "description": r"ECDSA using secp256k1 curve and SHA-256", + "const": "ES256K", + }), + // --- + schemars::json_schema!({ + "description": r"EdDSA using Ed25519 curve", + "const": "Ed25519", + }), + // --- + schemars::json_schema!({ + "description": r"EdDSA using Ed448 curve", + "const": "Ed448", + }), ]; let description = r#"JSON Web Signature "alg" parameter"#; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -533,275 +389,115 @@ impl serde::Serialize for JsonWebEncryptionAlg { } impl schemars::JsonSchema for JsonWebEncryptionAlg { - fn schema_name() -> String { - "JsonWebEncryptionAlg".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("JsonWebEncryptionAlg") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSAES-PKCS1-v1_5".to_owned(), - ), - ..Default::default() - })), - const_value: Some("RSA1_5".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSAES OAEP using default parameters".to_owned(), - ), - ..Default::default() - })), - const_value: Some("RSA-OAEP".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSAES OAEP using SHA-256 and MGF1 with SHA-256".to_owned(), - ), - ..Default::default() - })), - const_value: Some("RSA-OAEP-256".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"AES Key Wrap using 128-bit key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A128KW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"AES Key Wrap using 192-bit key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A192KW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"AES Key Wrap using 256-bit key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A256KW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Direct use of a shared symmetric key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("dir".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"ECDH-ES using Concat KDF".to_owned(), - ), - ..Default::default() - })), - const_value: Some("ECDH-ES".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r#"ECDH-ES using Concat KDF and "A128KW" wrapping"#.to_owned(), - ), - ..Default::default() - })), - const_value: Some("ECDH-ES+A128KW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r#"ECDH-ES using Concat KDF and "A192KW" wrapping"#.to_owned(), - ), - ..Default::default() - })), - const_value: Some("ECDH-ES+A192KW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r#"ECDH-ES using Concat KDF and "A256KW" wrapping"#.to_owned(), - ), - ..Default::default() - })), - const_value: Some("ECDH-ES+A256KW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Key wrapping with AES GCM using 128-bit key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A128GCMKW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Key wrapping with AES GCM using 192-bit key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A192GCMKW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Key wrapping with AES GCM using 256-bit key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A256GCMKW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r#"PBES2 with HMAC SHA-256 and "A128KW" wrapping"#.to_owned(), - ), - ..Default::default() - })), - const_value: Some("PBES2-HS256+A128KW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r#"PBES2 with HMAC SHA-384 and "A192KW" wrapping"#.to_owned(), - ), - ..Default::default() - })), - const_value: Some("PBES2-HS384+A192KW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r#"PBES2 with HMAC SHA-512 and "A256KW" wrapping"#.to_owned(), - ), - ..Default::default() - })), - const_value: Some("PBES2-HS512+A256KW".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSA-OAEP using SHA-384 and MGF1 with SHA-384".to_owned(), - ), - ..Default::default() - })), - const_value: Some("RSA-OAEP-384".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSA-OAEP using SHA-512 and MGF1 with SHA-512".to_owned(), - ), - ..Default::default() - })), - const_value: Some("RSA-OAEP-512".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "description": r"RSAES-PKCS1-v1_5", + "const": "RSA1_5", + }), + // --- + schemars::json_schema!({ + "description": r"RSAES OAEP using default parameters", + "const": "RSA-OAEP", + }), + // --- + schemars::json_schema!({ + "description": r"RSAES OAEP using SHA-256 and MGF1 with SHA-256", + "const": "RSA-OAEP-256", + }), + // --- + schemars::json_schema!({ + "description": r"AES Key Wrap using 128-bit key", + "const": "A128KW", + }), + // --- + schemars::json_schema!({ + "description": r"AES Key Wrap using 192-bit key", + "const": "A192KW", + }), + // --- + schemars::json_schema!({ + "description": r"AES Key Wrap using 256-bit key", + "const": "A256KW", + }), + // --- + schemars::json_schema!({ + "description": r"Direct use of a shared symmetric key", + "const": "dir", + }), + // --- + schemars::json_schema!({ + "description": r"ECDH-ES using Concat KDF", + "const": "ECDH-ES", + }), + // --- + schemars::json_schema!({ + "description": r#"ECDH-ES using Concat KDF and "A128KW" wrapping"#, + "const": "ECDH-ES+A128KW", + }), + // --- + schemars::json_schema!({ + "description": r#"ECDH-ES using Concat KDF and "A192KW" wrapping"#, + "const": "ECDH-ES+A192KW", + }), + // --- + schemars::json_schema!({ + "description": r#"ECDH-ES using Concat KDF and "A256KW" wrapping"#, + "const": "ECDH-ES+A256KW", + }), + // --- + schemars::json_schema!({ + "description": r"Key wrapping with AES GCM using 128-bit key", + "const": "A128GCMKW", + }), + // --- + schemars::json_schema!({ + "description": r"Key wrapping with AES GCM using 192-bit key", + "const": "A192GCMKW", + }), + // --- + schemars::json_schema!({ + "description": r"Key wrapping with AES GCM using 256-bit key", + "const": "A256GCMKW", + }), + // --- + schemars::json_schema!({ + "description": r#"PBES2 with HMAC SHA-256 and "A128KW" wrapping"#, + "const": "PBES2-HS256+A128KW", + }), + // --- + schemars::json_schema!({ + "description": r#"PBES2 with HMAC SHA-384 and "A192KW" wrapping"#, + "const": "PBES2-HS384+A192KW", + }), + // --- + schemars::json_schema!({ + "description": r#"PBES2 with HMAC SHA-512 and "A256KW" wrapping"#, + "const": "PBES2-HS512+A256KW", + }), + // --- + schemars::json_schema!({ + "description": r"RSA-OAEP using SHA-384 and MGF1 with SHA-384", + "const": "RSA-OAEP-384", + }), + // --- + schemars::json_schema!({ + "description": r"RSA-OAEP using SHA-512 and MGF1 with SHA-512", + "const": "RSA-OAEP-512", + }), ]; let description = r#"JSON Web Encryption "alg" parameter"#; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -883,106 +579,50 @@ impl serde::Serialize for JsonWebEncryptionEnc { } impl schemars::JsonSchema for JsonWebEncryptionEnc { - fn schema_name() -> String { - "JsonWebEncryptionEnc".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("JsonWebEncryptionEnc") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A128CBC-HS256".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A192CBC-HS384".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A256CBC-HS512".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"AES GCM using 128-bit key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A128GCM".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"AES GCM using 192-bit key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A192GCM".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"AES GCM using 256-bit key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("A256GCM".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "description": r"AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm", + "const": "A128CBC-HS256", + }), + // --- + schemars::json_schema!({ + "description": r"AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm", + "const": "A192CBC-HS384", + }), + // --- + schemars::json_schema!({ + "description": r"AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm", + "const": "A256CBC-HS512", + }), + // --- + schemars::json_schema!({ + "description": r"AES GCM using 128-bit key", + "const": "A128GCM", + }), + // --- + schemars::json_schema!({ + "description": r"AES GCM using 192-bit key", + "const": "A192GCM", + }), + // --- + schemars::json_schema!({ + "description": r"AES GCM using 256-bit key", + "const": "A256GCM", + }), ]; let description = r#"JSON Web Encryption "enc" parameter"#; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -1039,41 +679,25 @@ impl serde::Serialize for JsonWebEncryptionCompressionAlgorithm { } impl schemars::JsonSchema for JsonWebEncryptionCompressionAlgorithm { - fn schema_name() -> String { - "JsonWebEncryptionCompressionAlgorithm".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("JsonWebEncryptionCompressionAlgorithm") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"DEFLATE".to_owned(), - ), - ..Default::default() - })), - const_value: Some("DEF".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "description": r"DEFLATE", + "const": "DEF", + }), ]; let description = r"JSON Web Encryption Compression Algorithm"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -1145,80 +769,40 @@ impl serde::Serialize for JsonWebKeyType { } impl schemars::JsonSchema for JsonWebKeyType { - fn schema_name() -> String { - "JsonWebKeyType".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("JsonWebKeyType") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Elliptic Curve".to_owned(), - ), - ..Default::default() - })), - const_value: Some("EC".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"RSA".to_owned(), - ), - ..Default::default() - })), - const_value: Some("RSA".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Octet sequence".to_owned(), - ), - ..Default::default() - })), - const_value: Some("oct".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Octet string key pairs".to_owned(), - ), - ..Default::default() - })), - const_value: Some("OKP".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "description": r"Elliptic Curve", + "const": "EC", + }), + // --- + schemars::json_schema!({ + "description": r"RSA", + "const": "RSA", + }), + // --- + schemars::json_schema!({ + "description": r"Octet sequence", + "const": "oct", + }), + // --- + schemars::json_schema!({ + "description": r"Octet string key pairs", + "const": "OKP", + }), ]; let description = r"JSON Web Key Type"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -1290,80 +874,40 @@ impl serde::Serialize for JsonWebKeyEcEllipticCurve { } impl schemars::JsonSchema for JsonWebKeyEcEllipticCurve { - fn schema_name() -> String { - "JsonWebKeyEcEllipticCurve".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("JsonWebKeyEcEllipticCurve") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"P-256 Curve".to_owned(), - ), - ..Default::default() - })), - const_value: Some("P-256".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"P-384 Curve".to_owned(), - ), - ..Default::default() - })), - const_value: Some("P-384".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"P-521 Curve".to_owned(), - ), - ..Default::default() - })), - const_value: Some("P-521".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"SECG secp256k1 curve".to_owned(), - ), - ..Default::default() - })), - const_value: Some("secp256k1".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "description": r"P-256 Curve", + "const": "P-256", + }), + // --- + schemars::json_schema!({ + "description": r"P-384 Curve", + "const": "P-384", + }), + // --- + schemars::json_schema!({ + "description": r"P-521 Curve", + "const": "P-521", + }), + // --- + schemars::json_schema!({ + "description": r"SECG secp256k1 curve", + "const": "secp256k1", + }), ]; let description = r"JSON Web Key EC Elliptic Curve"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -1435,80 +979,40 @@ impl serde::Serialize for JsonWebKeyOkpEllipticCurve { } impl schemars::JsonSchema for JsonWebKeyOkpEllipticCurve { - fn schema_name() -> String { - "JsonWebKeyOkpEllipticCurve".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("JsonWebKeyOkpEllipticCurve") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Ed25519 signature algorithm key pairs".to_owned(), - ), - ..Default::default() - })), - const_value: Some("Ed25519".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Ed448 signature algorithm key pairs".to_owned(), - ), - ..Default::default() - })), - const_value: Some("Ed448".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"X25519 function key pairs".to_owned(), - ), - ..Default::default() - })), - const_value: Some("X25519".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"X448 function key pairs".to_owned(), - ), - ..Default::default() - })), - const_value: Some("X448".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "description": r"Ed25519 signature algorithm key pairs", + "const": "Ed25519", + }), + // --- + schemars::json_schema!({ + "description": r"Ed448 signature algorithm key pairs", + "const": "Ed448", + }), + // --- + schemars::json_schema!({ + "description": r"X25519 function key pairs", + "const": "X25519", + }), + // --- + schemars::json_schema!({ + "description": r"X448 function key pairs", + "const": "X448", + }), ]; let description = r"JSON Web Key OKP Elliptic Curve"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -1570,54 +1074,30 @@ impl serde::Serialize for JsonWebKeyUse { } impl schemars::JsonSchema for JsonWebKeyUse { - fn schema_name() -> String { - "JsonWebKeyUse".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("JsonWebKeyUse") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Digital Signature or MAC".to_owned(), - ), - ..Default::default() - })), - const_value: Some("sig".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Encryption".to_owned(), - ), - ..Default::default() - })), - const_value: Some("enc".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "description": r"Digital Signature or MAC", + "const": "sig", + }), + // --- + schemars::json_schema!({ + "description": r"Encryption", + "const": "enc", + }), ]; let description = r"JSON Web Key Use"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -1709,131 +1189,59 @@ impl serde::Serialize for JsonWebKeyOperation { } impl schemars::JsonSchema for JsonWebKeyOperation { - fn schema_name() -> String { - "JsonWebKeyOperation".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("JsonWebKeyOperation") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Compute digital signature or MAC".to_owned(), - ), - ..Default::default() - })), - const_value: Some("sign".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Verify digital signature or MAC".to_owned(), - ), - ..Default::default() - })), - const_value: Some("verify".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Encrypt content".to_owned(), - ), - ..Default::default() - })), - const_value: Some("encrypt".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Decrypt content and validate decryption, if applicable".to_owned(), - ), - ..Default::default() - })), - const_value: Some("decrypt".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Encrypt key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("wrapKey".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Decrypt key and validate decryption, if applicable".to_owned(), - ), - ..Default::default() - })), - const_value: Some("unwrapKey".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Derive key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("deriveKey".into()), - ..Default::default() - } - .into(), - // --- - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some( - // --- - r"Derive bits not to be used as a key".to_owned(), - ), - ..Default::default() - })), - const_value: Some("deriveBits".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "description": r"Compute digital signature or MAC", + "const": "sign", + }), + // --- + schemars::json_schema!({ + "description": r"Verify digital signature or MAC", + "const": "verify", + }), + // --- + schemars::json_schema!({ + "description": r"Encrypt content", + "const": "encrypt", + }), + // --- + schemars::json_schema!({ + "description": r"Decrypt content and validate decryption, if applicable", + "const": "decrypt", + }), + // --- + schemars::json_schema!({ + "description": r"Encrypt key", + "const": "wrapKey", + }), + // --- + schemars::json_schema!({ + "description": r"Decrypt key and validate decryption, if applicable", + "const": "unwrapKey", + }), + // --- + schemars::json_schema!({ + "description": r"Derive key", + "const": "deriveKey", + }), + // --- + schemars::json_schema!({ + "description": r"Derive bits not to be used as a key", + "const": "deriveBits", + }), ]; let description = r"JSON Web Key Operation"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } diff --git a/crates/iana/src/oauth.rs b/crates/iana/src/oauth.rs index 530e4bd7b..e1835e16c 100644 --- a/crates/iana/src/oauth.rs +++ b/crates/iana/src/oauth.rs @@ -79,52 +79,36 @@ impl serde::Serialize for OAuthAccessTokenType { } impl schemars::JsonSchema for OAuthAccessTokenType { - fn schema_name() -> String { - "OAuthAccessTokenType".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("OAuthAccessTokenType") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - const_value: Some("Bearer".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "Bearer", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("N_A".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "N_A", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("PoP".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "PoP", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("DPoP".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "DPoP", + }), ]; let description = r"OAuth Access Token Type"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -211,76 +195,52 @@ impl serde::Serialize for OAuthAuthorizationEndpointResponseType { } impl schemars::JsonSchema for OAuthAuthorizationEndpointResponseType { - fn schema_name() -> String { - "OAuthAuthorizationEndpointResponseType".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("OAuthAuthorizationEndpointResponseType") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - const_value: Some("code".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "code", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("code id_token".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "code id_token", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("code id_token token".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "code id_token token", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("code token".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "code token", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("id_token".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "id_token", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("id_token token".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "id_token token", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("none".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "none", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("token".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "token", + }), ]; let description = r"OAuth Authorization Endpoint Response Type"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -347,46 +307,32 @@ impl serde::Serialize for OAuthTokenTypeHint { } impl schemars::JsonSchema for OAuthTokenTypeHint { - fn schema_name() -> String { - "OAuthTokenTypeHint".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("OAuthTokenTypeHint") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - const_value: Some("access_token".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "access_token", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("refresh_token".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "refresh_token", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("pct".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "pct", + }), ]; let description = r"OAuth Token Type Hint"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -473,70 +419,48 @@ impl serde::Serialize for OAuthClientAuthenticationMethod { } impl schemars::JsonSchema for OAuthClientAuthenticationMethod { - fn schema_name() -> String { - "OAuthClientAuthenticationMethod".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("OAuthClientAuthenticationMethod") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - const_value: Some("none".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "none", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("client_secret_post".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "client_secret_post", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("client_secret_basic".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "client_secret_basic", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("client_secret_jwt".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "client_secret_jwt", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("private_key_jwt".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "private_key_jwt", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("tls_client_auth".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "tls_client_auth", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("self_signed_tls_client_auth".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "self_signed_tls_client_auth", + }), ]; let description = r"OAuth Token Endpoint Authentication Method"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } @@ -598,39 +522,27 @@ impl serde::Serialize for PkceCodeChallengeMethod { } impl schemars::JsonSchema for PkceCodeChallengeMethod { - fn schema_name() -> String { - "PkceCodeChallengeMethod".to_owned() + fn schema_name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("PkceCodeChallengeMethod") } #[allow(clippy::too_many_lines)] - fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(_gen: &mut schemars::SchemaGenerator) -> schemars::Schema { let enums = vec![ // --- - schemars::schema::SchemaObject { - const_value: Some("plain".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "plain", + }), // --- - schemars::schema::SchemaObject { - const_value: Some("S256".into()), - ..Default::default() - } - .into(), + schemars::json_schema!({ + "const": "S256", + }), ]; let description = r"PKCE Code Challenge Method"; - schemars::schema::SchemaObject { - metadata: Some(Box::new(schemars::schema::Metadata { - description: Some(description.to_owned()), - ..Default::default() - })), - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(enums), - ..Default::default() - })), - ..Default::default() - } - .into() + schemars::json_schema!({ + "description": description, + "anyOf": enums, + }) } } diff --git a/crates/policy/src/bin/schema.rs b/crates/policy/src/bin/schema.rs index 3fbe09adb..a07919276 100644 --- a/crates/policy/src/bin/schema.rs +++ b/crates/policy/src/bin/schema.rs @@ -14,7 +14,11 @@ use std::path::{Path, PathBuf}; use mas_policy::model::{ AuthorizationGrantInput, ClientRegistrationInput, EmailInput, RegisterInput, }; -use schemars::{JsonSchema, r#gen::SchemaSettings}; +use schemars::{ + JsonSchema, + generate::SchemaSettings, + transform::{AddNullable, RecursiveTransform}, +}; fn write_schema(out_dir: Option<&Path>, file: &str) { let mut writer: Box = if let Some(out_dir) = out_dir { @@ -27,11 +31,9 @@ fn write_schema(out_dir: Option<&Path>, file: &str) { Box::new(std::io::stdout()) }; - let settings = SchemaSettings::draft07().with(|s| { - s.option_nullable = false; - s.option_add_null_type = false; - }); - let generator = settings.into_generator(); + let generator = SchemaSettings::draft07() + .with_transform(RecursiveTransform(AddNullable::default())) + .into_generator(); let schema = generator.into_root_schema_for::(); serde_json::to_writer_pretty(&mut writer, &schema).expect("Failed to serialize schema"); writer.flush().expect("Failed to flush writer"); diff --git a/deny.toml b/deny.toml index 152c525e5..6d69a4b38 100644 --- a/deny.toml +++ b/deny.toml @@ -60,8 +60,6 @@ skip = [ { name = "regex-syntax", version = "0.6.29" }, # tracing-subscriber[env-filter] -> matchers depends on the old version { name = "regex-automata", version = "0.1.10" }, # ^ { name = "itertools", version = "0.13.0" }, # zxcvbn depends on this old version - { name = "indexmap", version = "1.9.3" }, # schemars depends on this old version - { name = "hashbrown", version = "0.12.3" }, # schemars -> indexmap depends on this old version { name = "hashbrown", version = "0.14.5" }, # a few crates depend on this old version # a few dependencies depend on the 1.x version of thiserror { name = "thiserror", version = "1.0.69" }, diff --git a/docs/api/spec.json b/docs/api/spec.json index 0082ea37c..c5d6c6fbd 100644 --- a/docs/api/spec.json +++ b/docs/api/spec.json @@ -31,8 +31,14 @@ "description": "Retrieve the items before the given ID", "schema": { "description": "Retrieve the items before the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -42,8 +48,14 @@ "description": "Retrieve the items after the given ID", "schema": { "description": "Retrieve the items after the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -53,10 +65,12 @@ "description": "Retrieve the first N items", "schema": { "description": "Retrieve the first N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -66,10 +80,12 @@ "description": "Retrieve the last N items", "schema": { "description": "Retrieve the last N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -79,8 +95,14 @@ "description": "Retrieve the items for the given user", "schema": { "description": "Retrieve the items for the given user", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -90,19 +112,31 @@ "description": "Retrieve the items started from the given browser session", "schema": { "description": "Retrieve the items started from the given browser session", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, { "in": "query", "name": "filter[status]", - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all sessions, including finished ones.\n\n* `active`: Only retrieve active sessions\n\n* `finished`: Only retrieve finished sessions", + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all sessions, including finished ones.\n\n * `active`: Only retrieve active sessions\n\n * `finished`: Only retrieve finished sessions", "schema": { - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all sessions, including finished ones.\n\n* `active`: Only retrieve active sessions\n\n* `finished`: Only retrieve finished sessions", - "$ref": "#/components/schemas/CompatSessionStatus", - "nullable": true + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all sessions, including finished ones.\n\n * `active`: Only retrieve active sessions\n\n * `finished`: Only retrieve finished sessions", + "anyOf": [ + { + "$ref": "#/components/schemas/CompatSessionStatus" + }, + { + "type": "null" + } + ] }, "style": "form" } @@ -297,8 +331,14 @@ "description": "Retrieve the items before the given ID", "schema": { "description": "Retrieve the items before the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -308,8 +348,14 @@ "description": "Retrieve the items after the given ID", "schema": { "description": "Retrieve the items after the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -319,10 +365,12 @@ "description": "Retrieve the first N items", "schema": { "description": "Retrieve the first N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -332,10 +380,12 @@ "description": "Retrieve the last N items", "schema": { "description": "Retrieve the last N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -345,8 +395,14 @@ "description": "Retrieve the items for the given user", "schema": { "description": "Retrieve the items for the given user", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -356,8 +412,14 @@ "description": "Retrieve the items for the given client", "schema": { "description": "Retrieve the items for the given client", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -367,8 +429,14 @@ "description": "Retrieve the items only for a specific client kind", "schema": { "description": "Retrieve the items only for a specific client kind", - "$ref": "#/components/schemas/OAuth2ClientKind", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/OAuth2ClientKind" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -378,8 +446,14 @@ "description": "Retrieve the items started from the given browser session", "schema": { "description": "Retrieve the items started from the given browser session", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -389,22 +463,28 @@ "description": "Retrieve the items with the given scope", "schema": { "description": "Retrieve the items with the given scope", - "default": [], "type": "array", "items": { "type": "string" - } + }, + "default": [] }, "style": "form" }, { "in": "query", "name": "filter[status]", - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all sessions, including finished ones.\n\n* `active`: Only retrieve active sessions\n\n* `finished`: Only retrieve finished sessions", + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all sessions, including finished ones.\n\n * `active`: Only retrieve active sessions\n\n * `finished`: Only retrieve finished sessions", "schema": { - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all sessions, including finished ones.\n\n* `active`: Only retrieve active sessions\n\n* `finished`: Only retrieve finished sessions", - "$ref": "#/components/schemas/OAuth2SessionStatus", - "nullable": true + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all sessions, including finished ones.\n\n * `active`: Only retrieve active sessions\n\n * `finished`: Only retrieve finished sessions", + "anyOf": [ + { + "$ref": "#/components/schemas/OAuth2SessionStatus" + }, + { + "type": "null" + } + ] }, "style": "form" } @@ -817,8 +897,14 @@ "description": "Retrieve the items before the given ID", "schema": { "description": "Retrieve the items before the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -828,8 +914,14 @@ "description": "Retrieve the items after the given ID", "schema": { "description": "Retrieve the items after the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -839,10 +931,12 @@ "description": "Retrieve the first N items", "schema": { "description": "Retrieve the first N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -852,10 +946,12 @@ "description": "Retrieve the last N items", "schema": { "description": "Retrieve the last N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -865,19 +961,27 @@ "description": "Retrieve users with (or without) the `admin` flag set", "schema": { "description": "Retrieve users with (or without) the `admin` flag set", - "type": "boolean", - "nullable": true + "type": [ + "boolean", + "null" + ] }, "style": "form" }, { "in": "query", "name": "filter[status]", - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all users, including locked ones.\n\n* `active`: Only retrieve active users\n\n* `locked`: Only retrieve locked users (includes deactivated users)\n\n* `deactivated`: Only retrieve deactivated users", + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all users, including locked ones.\n\n * `active`: Only retrieve active users\n\n * `locked`: Only retrieve locked users (includes deactivated users)\n\n * `deactivated`: Only retrieve deactivated users", "schema": { - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all users, including locked ones.\n\n* `active`: Only retrieve active users\n\n* `locked`: Only retrieve locked users (includes deactivated users)\n\n* `deactivated`: Only retrieve deactivated users", - "$ref": "#/components/schemas/UserStatus", - "nullable": true + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all users, including locked ones.\n\n * `active`: Only retrieve active users\n\n * `locked`: Only retrieve locked users (includes deactivated users)\n\n * `deactivated`: Only retrieve deactivated users", + "anyOf": [ + { + "$ref": "#/components/schemas/UserStatus" + }, + { + "type": "null" + } + ] }, "style": "form" } @@ -1563,8 +1667,14 @@ "description": "Retrieve the items before the given ID", "schema": { "description": "Retrieve the items before the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -1574,8 +1684,14 @@ "description": "Retrieve the items after the given ID", "schema": { "description": "Retrieve the items after the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -1585,10 +1701,12 @@ "description": "Retrieve the first N items", "schema": { "description": "Retrieve the first N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -1598,10 +1716,12 @@ "description": "Retrieve the last N items", "schema": { "description": "Retrieve the last N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -1611,8 +1731,14 @@ "description": "Retrieve the items for the given user", "schema": { "description": "Retrieve the items for the given user", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -1622,8 +1748,10 @@ "description": "Retrieve the user email with the given email address", "schema": { "description": "Retrieve the user email with the given email address", - "type": "string", - "nullable": true + "type": [ + "string", + "null" + ] }, "style": "form" } @@ -1908,8 +2036,14 @@ "description": "Retrieve the items before the given ID", "schema": { "description": "Retrieve the items before the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -1919,8 +2053,14 @@ "description": "Retrieve the items after the given ID", "schema": { "description": "Retrieve the items after the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -1930,10 +2070,12 @@ "description": "Retrieve the first N items", "schema": { "description": "Retrieve the first N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -1943,10 +2085,12 @@ "description": "Retrieve the last N items", "schema": { "description": "Retrieve the last N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -1956,19 +2100,31 @@ "description": "Retrieve the items for the given user", "schema": { "description": "Retrieve the items for the given user", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, { "in": "query", "name": "filter[status]", - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all sessions, including finished ones.\n\n* `active`: Only retrieve active sessions\n\n* `finished`: Only retrieve finished sessions", + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all sessions, including finished ones.\n\n * `active`: Only retrieve active sessions\n\n * `finished`: Only retrieve finished sessions", "schema": { - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all sessions, including finished ones.\n\n* `active`: Only retrieve active sessions\n\n* `finished`: Only retrieve finished sessions", - "$ref": "#/components/schemas/UserSessionStatus", - "nullable": true + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all sessions, including finished ones.\n\n * `active`: Only retrieve active sessions\n\n * `finished`: Only retrieve finished sessions", + "anyOf": [ + { + "$ref": "#/components/schemas/UserSessionStatus" + }, + { + "type": "null" + } + ] }, "style": "form" } @@ -2146,8 +2302,14 @@ "description": "Retrieve the items before the given ID", "schema": { "description": "Retrieve the items before the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -2157,8 +2319,14 @@ "description": "Retrieve the items after the given ID", "schema": { "description": "Retrieve the items after the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -2168,10 +2336,12 @@ "description": "Retrieve the first N items", "schema": { "description": "Retrieve the first N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -2181,10 +2351,12 @@ "description": "Retrieve the last N items", "schema": { "description": "Retrieve the last N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -2194,8 +2366,10 @@ "description": "Retrieve tokens that have (or have not) been used at least once", "schema": { "description": "Retrieve tokens that have (or have not) been used at least once", - "type": "boolean", - "nullable": true + "type": [ + "boolean", + "null" + ] }, "style": "form" }, @@ -2205,8 +2379,10 @@ "description": "Retrieve tokens that are (or are not) revoked", "schema": { "description": "Retrieve tokens that are (or are not) revoked", - "type": "boolean", - "nullable": true + "type": [ + "boolean", + "null" + ] }, "style": "form" }, @@ -2216,19 +2392,23 @@ "description": "Retrieve tokens that are (or are not) expired", "schema": { "description": "Retrieve tokens that are (or are not) expired", - "type": "boolean", - "nullable": true + "type": [ + "boolean", + "null" + ] }, "style": "form" }, { "in": "query", "name": "filter[valid]", - "description": "Retrieve tokens that are (or are not) valid\n\nValid means that the token has not expired, is not revoked, and has not reached its usage limit.", + "description": "Retrieve tokens that are (or are not) valid\n\n Valid means that the token has not expired, is not revoked, and has not\n reached its usage limit.", "schema": { - "description": "Retrieve tokens that are (or are not) valid\n\nValid means that the token has not expired, is not revoked, and has not reached its usage limit.", - "type": "boolean", - "nullable": true + "description": "Retrieve tokens that are (or are not) valid\n\n Valid means that the token has not expired, is not revoked, and has not\n reached its usage limit.", + "type": [ + "boolean", + "null" + ] }, "style": "form" } @@ -2693,8 +2873,14 @@ "description": "Retrieve the items before the given ID", "schema": { "description": "Retrieve the items before the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -2704,8 +2890,14 @@ "description": "Retrieve the items after the given ID", "schema": { "description": "Retrieve the items after the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -2715,10 +2907,12 @@ "description": "Retrieve the first N items", "schema": { "description": "Retrieve the first N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -2728,10 +2922,12 @@ "description": "Retrieve the last N items", "schema": { "description": "Retrieve the last N items", - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint", - "minimum": 1.0, - "nullable": true + "minimum": 1 }, "style": "form" }, @@ -2741,8 +2937,14 @@ "description": "Retrieve the items for the given user", "schema": { "description": "Retrieve the items for the given user", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -2752,8 +2954,14 @@ "description": "Retrieve the items for the given provider", "schema": { "description": "Retrieve the items for the given provider", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "type": "null" + } + ] }, "style": "form" }, @@ -2763,8 +2971,10 @@ "description": "Retrieve the items with the given subject", "schema": { "description": "Retrieve the items with the given subject", - "type": "string", - "nullable": true + "type": [ + "string", + "null" + ] }, "style": "form" } @@ -3111,26 +3321,44 @@ "properties": { "page[before]": { "description": "Retrieve the items before the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "page[after]": { "description": "Retrieve the items after the given ID", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "page[first]": { "description": "Retrieve the first N items", "type": "integer", "format": "uint", - "minimum": 1.0, + "minimum": 1, "nullable": true }, "page[last]": { "description": "Retrieve the last N items", "type": "integer", "format": "uint", - "minimum": 1.0, + "minimum": 1, "nullable": true } } @@ -3138,30 +3366,54 @@ "ULID": { "title": "ULID", "description": "A ULID as per https://github.com/ulid/spec", - "examples": [ - "01ARZ3NDEKTSV4RRFFQ69G5FAV", - "01J41912SC8VGAQDD50F6APK91" - ], "type": "string", - "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$" + "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$", + "example": "01ARZ3NDEKTSV4RRFFQ69G5FAV" }, "CompatSessionFilter": { "type": "object", "properties": { "filter[user]": { "description": "Retrieve the items for the given user", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "filter[user-session]": { "description": "Retrieve the items started from the given browser session", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "filter[status]": { - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all sessions, including finished ones.\n\n* `active`: Only retrieve active sessions\n\n* `finished`: Only retrieve finished sessions", - "$ref": "#/components/schemas/CompatSessionStatus", - "nullable": true + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all sessions, including finished ones.\n\n * `active`: Only retrieve active sessions\n\n * `finished`: Only retrieve finished sessions", + "anyOf": [ + { + "$ref": "#/components/schemas/CompatSessionStatus" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] } } }, @@ -3175,15 +3427,14 @@ "PaginatedResponse_for_CompatSession": { "description": "A top-level response with a page of resources", "type": "object", - "required": [ - "data", - "links", - "meta" - ], "properties": { "meta": { "description": "Response metadata", - "$ref": "#/components/schemas/PaginationMeta" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationMeta" + } + ] }, "data": { "description": "The list of resources", @@ -3194,33 +3445,36 @@ }, "links": { "description": "Related links", - "$ref": "#/components/schemas/PaginationLinks" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationLinks" + } + ] } - } + }, + "required": [ + "meta", + "data", + "links" + ] }, "PaginationMeta": { "type": "object", - "required": [ - "count" - ], "properties": { "count": { "description": "The total number of results", "type": "integer", "format": "uint", - "minimum": 0.0 + "minimum": 0 } - } + }, + "required": [ + "count" + ] }, "SingleResource_for_CompatSession": { "description": "A single resource, with its type, ID, attributes and related links", "type": "object", - "required": [ - "attributes", - "id", - "links", - "type" - ], "properties": { "type": { "description": "The type of the resource", @@ -3228,39 +3482,63 @@ }, "id": { "description": "The ID of the resource", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "attributes": { "description": "The attributes of the resource", - "$ref": "#/components/schemas/CompatSession" + "allOf": [ + { + "$ref": "#/components/schemas/CompatSession" + } + ] }, "links": { "description": "Related links", - "$ref": "#/components/schemas/SelfLinks" + "allOf": [ + { + "$ref": "#/components/schemas/SelfLinks" + } + ] } - } + }, + "required": [ + "type", + "id", + "attributes", + "links" + ] }, "CompatSession": { "description": "A compatibility session for legacy clients", "type": "object", - "required": [ - "created_at", - "device_id", - "user_id", - "user_session_id" - ], "properties": { "user_id": { "description": "The ID of the user that owns this session", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "device_id": { "description": "The Matrix device ID of this session", - "$ref": "#/components/schemas/DeviceID" + "allOf": [ + { + "$ref": "#/components/schemas/DeviceID" + } + ] }, "user_session_id": { "description": "The ID of the user session that started this session, if any", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "redirect_uri": { "description": "The redirect URI used to login in the client, if it was an SSO login", @@ -3301,38 +3579,37 @@ "type": "string", "nullable": true } - } + }, + "required": [ + "user_id", + "device_id", + "user_session_id", + "created_at" + ] }, "DeviceID": { "title": "Device ID", - "examples": [ - "AABBCCDDEE", - "FFGGHHIIJJ" - ], + "description": "A device ID as per https://matrix.org/docs/spec/client_server/r0.6.0#device-ids", "type": "string", - "pattern": "^[A-Za-z0-9._~!$&'()*+,;=:&/-]+$" + "pattern": "^[A-Za-z0-9._~!$&'()*+,;=:&/-]+$", + "example": "AABBCCDDEE" }, "SelfLinks": { "description": "Related links", "type": "object", - "required": [ - "self" - ], "properties": { "self": { "description": "The canonical link to the current resource", "type": "string" } - } + }, + "required": [ + "self" + ] }, "PaginationLinks": { "description": "Related links", "type": "object", - "required": [ - "first", - "last", - "self" - ], "properties": { "self": { "description": "The canonical link to the current page", @@ -3347,23 +3624,25 @@ "type": "string" }, "next": { - "description": "The link to the next page of results\n\nOnly present if there is a next page", + "description": "The link to the next page of results\n\n Only present if there is a next page", "type": "string", "nullable": true }, "prev": { - "description": "The link to the previous page of results\n\nOnly present if there is a previous page", + "description": "The link to the previous page of results\n\n Only present if there is a previous page", "type": "string", "nullable": true } - } + }, + "required": [ + "self", + "first", + "last" + ] }, "ErrorResponse": { "description": "A top-level response with a list of errors", "type": "object", - "required": [ - "errors" - ], "properties": { "errors": { "description": "The list of errors", @@ -3372,40 +3651,43 @@ "$ref": "#/components/schemas/Error" } } - } + }, + "required": [ + "errors" + ] }, "Error": { "description": "A single error", "type": "object", - "required": [ - "title" - ], "properties": { "title": { "description": "A human-readable title for the error", "type": "string" } - } + }, + "required": [ + "title" + ] }, "UlidInPath": { "type": "object", - "required": [ - "id" - ], "properties": { "id": { "title": "The ID of the resource", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] } - } + }, + "required": [ + "id" + ] }, "SingleResponse_for_CompatSession": { "description": "A top-level response with a single resource", "type": "object", - "required": [ - "data", - "links" - ], "properties": { "data": { "$ref": "#/components/schemas/SingleResource_for_CompatSession" @@ -3413,43 +3695,92 @@ "links": { "$ref": "#/components/schemas/SelfLinks" } - } + }, + "required": [ + "data", + "links" + ] }, "OAuth2SessionFilter": { "type": "object", "properties": { "filter[user]": { "description": "Retrieve the items for the given user", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "filter[client]": { "description": "Retrieve the items for the given client", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "filter[client-kind]": { "description": "Retrieve the items only for a specific client kind", - "$ref": "#/components/schemas/OAuth2ClientKind", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/OAuth2ClientKind" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "filter[user-session]": { "description": "Retrieve the items started from the given browser session", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "filter[scope]": { "description": "Retrieve the items with the given scope", - "default": [], "type": "array", "items": { "type": "string" - } + }, + "default": [] }, "filter[status]": { - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all sessions, including finished ones.\n\n* `active`: Only retrieve active sessions\n\n* `finished`: Only retrieve finished sessions", - "$ref": "#/components/schemas/OAuth2SessionStatus", - "nullable": true + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all sessions, including finished ones.\n\n * `active`: Only retrieve active sessions\n\n * `finished`: Only retrieve finished sessions", + "anyOf": [ + { + "$ref": "#/components/schemas/OAuth2SessionStatus" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] } } }, @@ -3470,15 +3801,14 @@ "PaginatedResponse_for_OAuth2Session": { "description": "A top-level response with a page of resources", "type": "object", - "required": [ - "data", - "links", - "meta" - ], "properties": { "meta": { "description": "Response metadata", - "$ref": "#/components/schemas/PaginationMeta" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationMeta" + } + ] }, "data": { "description": "The list of resources", @@ -3489,19 +3819,22 @@ }, "links": { "description": "Related links", - "$ref": "#/components/schemas/PaginationLinks" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationLinks" + } + ] } - } + }, + "required": [ + "meta", + "data", + "links" + ] }, "SingleResource_for_OAuth2Session": { "description": "A single resource, with its type, ID, attributes and related links", "type": "object", - "required": [ - "attributes", - "id", - "links", - "type" - ], "properties": { "type": { "description": "The type of the resource", @@ -3509,26 +3842,39 @@ }, "id": { "description": "The ID of the resource", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "attributes": { "description": "The attributes of the resource", - "$ref": "#/components/schemas/OAuth2Session" + "allOf": [ + { + "$ref": "#/components/schemas/OAuth2Session" + } + ] }, "links": { "description": "Related links", - "$ref": "#/components/schemas/SelfLinks" - } - } + "allOf": [ + { + "$ref": "#/components/schemas/SelfLinks" + } + ] + } + }, + "required": [ + "type", + "id", + "attributes", + "links" + ] }, "OAuth2Session": { "description": "A OAuth 2.0 session", "type": "object", - "required": [ - "client_id", - "created_at", - "scope" - ], "properties": { "created_at": { "description": "When the object was created", @@ -3543,17 +3889,39 @@ }, "user_id": { "description": "The ID of the user who owns the session", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "user_session_id": { "description": "The ID of the browser session which started this session", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "client_id": { "description": "The ID of the client which requested this session", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "scope": { "description": "The scope granted for this session", @@ -3581,15 +3949,16 @@ "type": "string", "nullable": true } - } + }, + "required": [ + "created_at", + "client_id", + "scope" + ] }, "SingleResponse_for_OAuth2Session": { "description": "A top-level response with a single resource", "type": "object", - "required": [ - "data", - "links" - ], "properties": { "data": { "$ref": "#/components/schemas/SingleResource_for_OAuth2Session" @@ -3597,33 +3966,31 @@ "links": { "$ref": "#/components/schemas/SelfLinks" } - } + }, + "required": [ + "data", + "links" + ] }, "SetPolicyDataRequest": { "title": "JSON payload for the `POST /api/admin/v1/policy-data`", "type": "object", - "required": [ - "data" - ], "properties": { "data": { - "examples": [ - { - "hello": "world", - "foo": 42, - "bar": true - } - ] + "example": { + "hello": "world", + "foo": 42, + "bar": true + } } - } + }, + "required": [ + "data" + ] }, "SingleResponse_for_PolicyData": { "description": "A top-level response with a single resource", "type": "object", - "required": [ - "data", - "links" - ], "properties": { "data": { "$ref": "#/components/schemas/SingleResource_for_PolicyData" @@ -3631,17 +3998,15 @@ "links": { "$ref": "#/components/schemas/SelfLinks" } - } + }, + "required": [ + "data", + "links" + ] }, "SingleResource_for_PolicyData": { "description": "A single resource, with its type, ID, attributes and related links", "type": "object", - "required": [ - "attributes", - "id", - "links", - "type" - ], "properties": { "type": { "description": "The type of the resource", @@ -3649,25 +4014,39 @@ }, "id": { "description": "The ID of the resource", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "attributes": { "description": "The attributes of the resource", - "$ref": "#/components/schemas/PolicyData" + "allOf": [ + { + "$ref": "#/components/schemas/PolicyData" + } + ] }, "links": { "description": "Related links", - "$ref": "#/components/schemas/SelfLinks" + "allOf": [ + { + "$ref": "#/components/schemas/SelfLinks" + } + ] } - } + }, + "required": [ + "type", + "id", + "attributes", + "links" + ] }, "PolicyData": { "description": "The policy data", "type": "object", - "required": [ - "created_at", - "data" - ], "properties": { "created_at": { "description": "The creation date of the policy data", @@ -3677,7 +4056,11 @@ "data": { "description": "The policy data content" } - } + }, + "required": [ + "created_at", + "data" + ] }, "UserFilter": { "type": "object", @@ -3688,9 +4071,18 @@ "nullable": true }, "filter[status]": { - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all users, including locked ones.\n\n* `active`: Only retrieve active users\n\n* `locked`: Only retrieve locked users (includes deactivated users)\n\n* `deactivated`: Only retrieve deactivated users", - "$ref": "#/components/schemas/UserStatus", - "nullable": true + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all users, including locked ones.\n\n * `active`: Only retrieve active users\n\n * `locked`: Only retrieve locked users (includes deactivated users)\n\n * `deactivated`: Only retrieve deactivated users", + "anyOf": [ + { + "$ref": "#/components/schemas/UserStatus" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] } } }, @@ -3705,15 +4097,14 @@ "PaginatedResponse_for_User": { "description": "A top-level response with a page of resources", "type": "object", - "required": [ - "data", - "links", - "meta" - ], "properties": { "meta": { "description": "Response metadata", - "$ref": "#/components/schemas/PaginationMeta" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationMeta" + } + ] }, "data": { "description": "The list of resources", @@ -3724,19 +4115,22 @@ }, "links": { "description": "Related links", - "$ref": "#/components/schemas/PaginationLinks" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationLinks" + } + ] } - } + }, + "required": [ + "meta", + "data", + "links" + ] }, "SingleResource_for_User": { "description": "A single resource, with its type, ID, attributes and related links", "type": "object", - "required": [ - "attributes", - "id", - "links", - "type" - ], "properties": { "type": { "description": "The type of the resource", @@ -3744,26 +4138,39 @@ }, "id": { "description": "The ID of the resource", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "attributes": { "description": "The attributes of the resource", - "$ref": "#/components/schemas/User" + "allOf": [ + { + "$ref": "#/components/schemas/User" + } + ] }, "links": { "description": "Related links", - "$ref": "#/components/schemas/SelfLinks" + "allOf": [ + { + "$ref": "#/components/schemas/SelfLinks" + } + ] } - } + }, + "required": [ + "type", + "id", + "attributes", + "links" + ] }, "User": { "description": "A user", "type": "object", - "required": [ - "admin", - "created_at", - "username" - ], "properties": { "username": { "description": "The username (localpart) of the user", @@ -3790,33 +4197,34 @@ "description": "Whether the user can request admin privileges.", "type": "boolean" } - } + }, + "required": [ + "username", + "created_at", + "admin" + ] }, "AddUserRequest": { "title": "JSON payload for the `POST /api/admin/v1/users` endpoint", "type": "object", - "required": [ - "username" - ], "properties": { "username": { "description": "The username of the user to add.", "type": "string" }, "skip_homeserver_check": { - "description": "Skip checking with the homeserver whether the username is available.\n\nUse this with caution! The main reason to use this, is when a user used by an application service needs to exist in MAS to craft special tokens (like with admin access) for them", - "default": false, - "type": "boolean" + "description": "Skip checking with the homeserver whether the username is available.\n\n Use this with caution! The main reason to use this, is when a user used\n by an application service needs to exist in MAS to craft special\n tokens (like with admin access) for them", + "type": "boolean", + "default": false } - } + }, + "required": [ + "username" + ] }, "SingleResponse_for_User": { "description": "A top-level response with a single resource", "type": "object", - "required": [ - "data", - "links" - ], "properties": { "data": { "$ref": "#/components/schemas/SingleResource_for_User" @@ -3824,61 +4232,72 @@ "links": { "$ref": "#/components/schemas/SelfLinks" } - } + }, + "required": [ + "data", + "links" + ] }, "SetUserPasswordRequest": { "title": "JSON payload for the `POST /api/admin/v1/users/:id/set-password` endpoint", "type": "object", - "required": [ - "password" - ], "properties": { "password": { "description": "The password to set for the user", - "examples": [ - "hunter2" - ], - "type": "string" + "type": "string", + "example": "hunter2" }, "skip_password_check": { "description": "Skip the password complexity check", "type": "boolean", "nullable": true } - } + }, + "required": [ + "password" + ] }, "UsernamePathParam": { "type": "object", - "required": [ - "username" - ], "properties": { "username": { "description": "The username (localpart) of the user to get", "type": "string" } - } + }, + "required": [ + "username" + ] }, "UserSetAdminRequest": { "title": "JSON payload for the `POST /api/admin/v1/users/:id/set-admin` endpoint", "type": "object", - "required": [ - "admin" - ], "properties": { "admin": { "description": "Whether the user can request admin privileges.", "type": "boolean" } - } + }, + "required": [ + "admin" + ] }, "UserEmailFilter": { "type": "object", "properties": { "filter[user]": { "description": "Retrieve the items for the given user", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "filter[email]": { "description": "Retrieve the user email with the given email address", @@ -3890,15 +4309,14 @@ "PaginatedResponse_for_UserEmail": { "description": "A top-level response with a page of resources", "type": "object", - "required": [ - "data", - "links", - "meta" - ], "properties": { "meta": { "description": "Response metadata", - "$ref": "#/components/schemas/PaginationMeta" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationMeta" + } + ] }, "data": { "description": "The list of resources", @@ -3909,19 +4327,22 @@ }, "links": { "description": "Related links", - "$ref": "#/components/schemas/PaginationLinks" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationLinks" + } + ] } - } + }, + "required": [ + "meta", + "data", + "links" + ] }, "SingleResource_for_UserEmail": { "description": "A single resource, with its type, ID, attributes and related links", "type": "object", - "required": [ - "attributes", - "id", - "links", - "type" - ], "properties": { "type": { "description": "The type of the resource", @@ -3929,26 +4350,39 @@ }, "id": { "description": "The ID of the resource", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "attributes": { "description": "The attributes of the resource", - "$ref": "#/components/schemas/UserEmail" + "allOf": [ + { + "$ref": "#/components/schemas/UserEmail" + } + ] }, "links": { "description": "Related links", - "$ref": "#/components/schemas/SelfLinks" + "allOf": [ + { + "$ref": "#/components/schemas/SelfLinks" + } + ] } - } + }, + "required": [ + "type", + "id", + "attributes", + "links" + ] }, "UserEmail": { "description": "An email address for a user", "type": "object", - "required": [ - "created_at", - "email", - "user_id" - ], "properties": { "created_at": { "description": "When the object was created", @@ -3957,40 +4391,49 @@ }, "user_id": { "description": "The ID of the user who owns this email address", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "email": { "description": "The email address", "type": "string" } - } + }, + "required": [ + "created_at", + "user_id", + "email" + ] }, "AddUserEmailRequest": { "title": "JSON payload for the `POST /api/admin/v1/user-emails`", "type": "object", - "required": [ - "email", - "user_id" - ], "properties": { "user_id": { "description": "The ID of the user to which the email should be added.", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "email": { "description": "The email address of the user to add.", "type": "string", "format": "email" } - } + }, + "required": [ + "user_id", + "email" + ] }, "SingleResponse_for_UserEmail": { "description": "A top-level response with a single resource", "type": "object", - "required": [ - "data", - "links" - ], "properties": { "data": { "$ref": "#/components/schemas/SingleResource_for_UserEmail" @@ -3998,20 +4441,42 @@ "links": { "$ref": "#/components/schemas/SelfLinks" } - } + }, + "required": [ + "data", + "links" + ] }, "UserSessionFilter": { "type": "object", "properties": { "filter[user]": { "description": "Retrieve the items for the given user", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "filter[status]": { - "description": "Retrieve the items with the given status\n\nDefaults to retrieve all sessions, including finished ones.\n\n* `active`: Only retrieve active sessions\n\n* `finished`: Only retrieve finished sessions", - "$ref": "#/components/schemas/UserSessionStatus", - "nullable": true + "description": "Retrieve the items with the given status\n\n Defaults to retrieve all sessions, including finished ones.\n\n * `active`: Only retrieve active sessions\n\n * `finished`: Only retrieve finished sessions", + "anyOf": [ + { + "$ref": "#/components/schemas/UserSessionStatus" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] } } }, @@ -4025,15 +4490,14 @@ "PaginatedResponse_for_UserSession": { "description": "A top-level response with a page of resources", "type": "object", - "required": [ - "data", - "links", - "meta" - ], "properties": { "meta": { "description": "Response metadata", - "$ref": "#/components/schemas/PaginationMeta" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationMeta" + } + ] }, "data": { "description": "The list of resources", @@ -4044,19 +4508,22 @@ }, "links": { "description": "Related links", - "$ref": "#/components/schemas/PaginationLinks" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationLinks" + } + ] } - } + }, + "required": [ + "meta", + "data", + "links" + ] }, "SingleResource_for_UserSession": { "description": "A single resource, with its type, ID, attributes and related links", "type": "object", - "required": [ - "attributes", - "id", - "links", - "type" - ], "properties": { "type": { "description": "The type of the resource", @@ -4064,25 +4531,39 @@ }, "id": { "description": "The ID of the resource", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "attributes": { "description": "The attributes of the resource", - "$ref": "#/components/schemas/UserSession" + "allOf": [ + { + "$ref": "#/components/schemas/UserSession" + } + ] }, "links": { "description": "Related links", - "$ref": "#/components/schemas/SelfLinks" + "allOf": [ + { + "$ref": "#/components/schemas/SelfLinks" + } + ] } - } + }, + "required": [ + "type", + "id", + "attributes", + "links" + ] }, "UserSession": { "description": "The browser (cookie) session for a user", "type": "object", - "required": [ - "created_at", - "user_id" - ], "properties": { "created_at": { "description": "When the object was created", @@ -4097,7 +4578,11 @@ }, "user_id": { "description": "The ID of the user who owns the session", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "user_agent": { "description": "The user agent string of the client which started this session", @@ -4116,15 +4601,15 @@ "format": "ip", "nullable": true } - } + }, + "required": [ + "created_at", + "user_id" + ] }, "SingleResponse_for_UserSession": { "description": "A top-level response with a single resource", "type": "object", - "required": [ - "data", - "links" - ], "properties": { "data": { "$ref": "#/components/schemas/SingleResource_for_UserSession" @@ -4132,7 +4617,11 @@ "links": { "$ref": "#/components/schemas/SelfLinks" } - } + }, + "required": [ + "data", + "links" + ] }, "RegistrationTokenFilter": { "type": "object", @@ -4153,7 +4642,7 @@ "nullable": true }, "filter[valid]": { - "description": "Retrieve tokens that are (or are not) valid\n\nValid means that the token has not expired, is not revoked, and has not reached its usage limit.", + "description": "Retrieve tokens that are (or are not) valid\n\n Valid means that the token has not expired, is not revoked, and has not\n reached its usage limit.", "type": "boolean", "nullable": true } @@ -4162,15 +4651,14 @@ "PaginatedResponse_for_UserRegistrationToken": { "description": "A top-level response with a page of resources", "type": "object", - "required": [ - "data", - "links", - "meta" - ], "properties": { "meta": { "description": "Response metadata", - "$ref": "#/components/schemas/PaginationMeta" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationMeta" + } + ] }, "data": { "description": "The list of resources", @@ -4181,19 +4669,22 @@ }, "links": { "description": "Related links", - "$ref": "#/components/schemas/PaginationLinks" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationLinks" + } + ] } - } + }, + "required": [ + "meta", + "data", + "links" + ] }, "SingleResource_for_UserRegistrationToken": { "description": "A single resource, with its type, ID, attributes and related links", "type": "object", - "required": [ - "attributes", - "id", - "links", - "type" - ], "properties": { "type": { "description": "The type of the resource", @@ -4201,27 +4692,39 @@ }, "id": { "description": "The ID of the resource", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "attributes": { "description": "The attributes of the resource", - "$ref": "#/components/schemas/UserRegistrationToken" + "allOf": [ + { + "$ref": "#/components/schemas/UserRegistrationToken" + } + ] }, "links": { "description": "Related links", - "$ref": "#/components/schemas/SelfLinks" + "allOf": [ + { + "$ref": "#/components/schemas/SelfLinks" + } + ] } - } + }, + "required": [ + "type", + "id", + "attributes", + "links" + ] }, "UserRegistrationToken": { "description": "A registration token", "type": "object", - "required": [ - "created_at", - "times_used", - "token", - "valid" - ], "properties": { "token": { "description": "The token string", @@ -4235,14 +4738,14 @@ "description": "Maximum number of times this token can be used", "type": "integer", "format": "uint32", - "minimum": 0.0, + "minimum": 0, "nullable": true }, "times_used": { "description": "Number of times this token has been used", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "created_at": { "description": "When the token was created", @@ -4267,7 +4770,13 @@ "format": "date-time", "nullable": true } - } + }, + "required": [ + "token", + "valid", + "times_used", + "created_at" + ] }, "AddUserRegistrationTokenRequest": { "title": "JSON payload for the `POST /api/admin/v1/user-registration-tokens`", @@ -4279,10 +4788,10 @@ "nullable": true }, "usage_limit": { - "description": "Maximum number of times this token can be used. If not provided, the token can be used an unlimited number of times.", + "description": "Maximum number of times this token can be used. If not provided, the\n token can be used an unlimited number of times.", "type": "integer", "format": "uint32", - "minimum": 0.0, + "minimum": 0, "nullable": true }, "expires_at": { @@ -4296,10 +4805,6 @@ "SingleResponse_for_UserRegistrationToken": { "description": "A top-level response with a single resource", "type": "object", - "required": [ - "data", - "links" - ], "properties": { "data": { "$ref": "#/components/schemas/SingleResource_for_UserRegistrationToken" @@ -4307,7 +4812,11 @@ "links": { "$ref": "#/components/schemas/SelfLinks" } - } + }, + "required": [ + "data", + "links" + ] }, "EditUserRegistrationTokenRequest": { "title": "JSON payload for the `PUT /api/admin/v1/user-registration-tokens/{id}` endpoint", @@ -4323,7 +4832,7 @@ "description": "New usage limit for the token, or null to remove the limit", "type": "integer", "format": "uint32", - "minimum": 0.0, + "minimum": 0, "nullable": true } } @@ -4333,13 +4842,31 @@ "properties": { "filter[user]": { "description": "Retrieve the items for the given user", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "filter[provider]": { "description": "Retrieve the items for the given provider", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "filter[subject]": { "description": "Retrieve the items with the given subject", @@ -4351,15 +4878,14 @@ "PaginatedResponse_for_UpstreamOAuthLink": { "description": "A top-level response with a page of resources", "type": "object", - "required": [ - "data", - "links", - "meta" - ], "properties": { "meta": { "description": "Response metadata", - "$ref": "#/components/schemas/PaginationMeta" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationMeta" + } + ] }, "data": { "description": "The list of resources", @@ -4370,19 +4896,22 @@ }, "links": { "description": "Related links", - "$ref": "#/components/schemas/PaginationLinks" + "allOf": [ + { + "$ref": "#/components/schemas/PaginationLinks" + } + ] } - } + }, + "required": [ + "meta", + "data", + "links" + ] }, "SingleResource_for_UpstreamOAuthLink": { "description": "A single resource, with its type, ID, attributes and related links", "type": "object", - "required": [ - "attributes", - "id", - "links", - "type" - ], "properties": { "type": { "description": "The type of the resource", @@ -4390,26 +4919,39 @@ }, "id": { "description": "The ID of the resource", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "attributes": { "description": "The attributes of the resource", - "$ref": "#/components/schemas/UpstreamOAuthLink" + "allOf": [ + { + "$ref": "#/components/schemas/UpstreamOAuthLink" + } + ] }, "links": { "description": "Related links", - "$ref": "#/components/schemas/SelfLinks" + "allOf": [ + { + "$ref": "#/components/schemas/SelfLinks" + } + ] } - } + }, + "required": [ + "type", + "id", + "attributes", + "links" + ] }, "UpstreamOAuthLink": { "description": "An upstream OAuth 2.0 link", "type": "object", - "required": [ - "created_at", - "provider_id", - "subject" - ], "properties": { "created_at": { "description": "When the object was created", @@ -4418,7 +4960,11 @@ }, "provider_id": { "description": "The ID of the provider", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "subject": { "description": "The subject of the upstream account, unique per provider", @@ -4426,32 +4972,49 @@ }, "user_id": { "description": "The ID of the user who owns this link, if any", - "$ref": "#/components/schemas/ULID", - "nullable": true + "anyOf": [ + { + "$ref": "#/components/schemas/ULID" + }, + { + "nullable": true, + "enum": [ + null + ] + } + ] }, "human_account_name": { "description": "A human-readable name of the upstream account", "type": "string", "nullable": true } - } + }, + "required": [ + "created_at", + "provider_id", + "subject" + ] }, "AddUpstreamOauthLinkRequest": { "title": "JSON payload for the `POST /api/admin/v1/upstream-oauth-links`", "type": "object", - "required": [ - "provider_id", - "subject", - "user_id" - ], "properties": { "user_id": { "description": "The ID of the user to which the link should be added.", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "provider_id": { "description": "The ID of the upstream provider to which the link is for.", - "$ref": "#/components/schemas/ULID" + "allOf": [ + { + "$ref": "#/components/schemas/ULID" + } + ] }, "subject": { "description": "The subject (sub) claim of the user on the provider.", @@ -4462,15 +5025,16 @@ "type": "string", "nullable": true } - } + }, + "required": [ + "user_id", + "provider_id", + "subject" + ] }, "SingleResponse_for_UpstreamOAuthLink": { "description": "A top-level response with a single resource", "type": "object", - "required": [ - "data", - "links" - ], "properties": { "data": { "$ref": "#/components/schemas/SingleResource_for_UpstreamOAuthLink" @@ -4478,7 +5042,11 @@ "links": { "$ref": "#/components/schemas/SelfLinks" } - } + }, + "required": [ + "data", + "links" + ] } } }, diff --git a/docs/config.schema.json b/docs/config.schema.json index 534165920..d69168bc8 100644 --- a/docs/config.schema.json +++ b/docs/config.schema.json @@ -3,10 +3,6 @@ "title": "RootConfig", "description": "Application configuration root", "type": "object", - "required": [ - "matrix", - "secrets" - ], "properties": { "clients": { "description": "List of OAuth 2.0/OIDC clients config", @@ -169,7 +165,7 @@ ] }, "rate_limiting": { - "description": "Configuration related to limiting the rate of user actions to prevent abuse", + "description": "Configuration related to limiting the rate of user actions to prevent\n abuse", "allOf": [ { "$ref": "#/definitions/RateLimitingConfig" @@ -201,7 +197,7 @@ ] }, "account": { - "description": "Configuration section to configure features related to account management", + "description": "Configuration section to configure features related to account\n management", "allOf": [ { "$ref": "#/definitions/AccountConfig" @@ -217,14 +213,14 @@ ] } }, + "required": [ + "secrets", + "matrix" + ], "definitions": { "ClientConfig": { "description": "An OAuth 2.0 client configuration", "type": "object", - "required": [ - "client_auth_method", - "client_id" - ], "properties": { "client_id": { "description": "A ULID as per https://github.com/ulid/spec", @@ -241,24 +237,31 @@ }, "client_name": { "description": "Name of the `OAuth2` client", - "type": "string" + "type": "string", + "nullable": true }, "client_secret": { - "description": "The client secret, used by the `client_secret_basic`, `client_secret_post` and `client_secret_jwt` authentication methods", - "type": "string" + "description": "The client secret, used by the `client_secret_basic`,\n `client_secret_post` and `client_secret_jwt` authentication methods", + "type": "string", + "nullable": true }, "jwks": { - "description": "The JSON Web Key Set (JWKS) used by the `private_key_jwt` authentication method. Mutually exclusive with `jwks_uri`", - "allOf": [ + "description": "The JSON Web Key Set (JWKS) used by the `private_key_jwt` authentication\n method. Mutually exclusive with `jwks_uri`", + "anyOf": [ { "$ref": "#/definitions/JsonWebKeySet_for_JsonWebKeyPublicParameters" + }, + { + "const": null, + "nullable": true } ] }, "jwks_uri": { - "description": "The URL of the JSON Web Key Set (JWKS) used by the `private_key_jwt` authentication method. Mutually exclusive with `jwks`", + "description": "The URL of the JSON Web Key Set (JWKS) used by the `private_key_jwt`\n authentication method. Mutually exclusive with `jwks`", "type": "string", - "format": "uri" + "format": "uri", + "nullable": true }, "redirect_uris": { "description": "List of allowed redirect URIs", @@ -268,7 +271,11 @@ "format": "uri" } } - } + }, + "required": [ + "client_id", + "client_auth_method" + ] }, "ClientAuthMethodConfig": { "description": "Authentication method used by clients", @@ -276,45 +283,32 @@ { "description": "`none`: No authentication", "type": "string", - "enum": [ - "none" - ] + "const": "none" }, { - "description": "`client_secret_basic`: `client_id` and `client_secret` used as basic authorization credentials", + "description": "`client_secret_basic`: `client_id` and `client_secret` used as basic\n authorization credentials", "type": "string", - "enum": [ - "client_secret_basic" - ] + "const": "client_secret_basic" }, { - "description": "`client_secret_post`: `client_id` and `client_secret` sent in the request body", + "description": "`client_secret_post`: `client_id` and `client_secret` sent in the\n request body", "type": "string", - "enum": [ - "client_secret_post" - ] + "const": "client_secret_post" }, { - "description": "`client_secret_basic`: a `client_assertion` sent in the request body and signed using the `client_secret`", + "description": "`client_secret_basic`: a `client_assertion` sent in the request body and\n signed using the `client_secret`", "type": "string", - "enum": [ - "client_secret_jwt" - ] + "const": "client_secret_jwt" }, { - "description": "`client_secret_basic`: a `client_assertion` sent in the request body and signed by an asymmetric key", + "description": "`client_secret_basic`: a `client_assertion` sent in the request body and\n signed by an asymmetric key", "type": "string", - "enum": [ - "private_key_jwt" - ] + "const": "private_key_jwt" } ] }, "JsonWebKeySet_for_JsonWebKeyPublicParameters": { "type": "object", - "required": [ - "keys" - ], "properties": { "keys": { "type": "array", @@ -322,114 +316,210 @@ "$ref": "#/definitions/JsonWebKey_for_JsonWebKeyPublicParameters" } } - } + }, + "required": [ + "keys" + ] }, "JsonWebKey_for_JsonWebKeyPublicParameters": { "type": "object", + "properties": { + "use": { + "anyOf": [ + { + "$ref": "#/definitions/JsonWebKeyUse" + }, + { + "const": null, + "nullable": true + } + ] + }, + "key_ops": { + "type": "array", + "items": { + "$ref": "#/definitions/JsonWebKeyOperation" + }, + "nullable": true + }, + "alg": { + "anyOf": [ + { + "$ref": "#/definitions/JsonWebSignatureAlg" + }, + { + "const": null, + "nullable": true + } + ] + }, + "kid": { + "type": "string", + "nullable": true + }, + "x5u": { + "type": "string", + "nullable": true + }, + "x5c": { + "type": "array", + "items": { + "type": "string" + } + }, + "x5t": { + "type": "string", + "nullable": true + }, + "x5t#S256": { + "type": "string", + "nullable": true + } + }, "oneOf": [ { "type": "object", - "required": [ - "e", - "kty", - "n" - ], "properties": { "kty": { "type": "string", - "enum": [ - "RSA" - ] - }, - "n": { - "type": "string" - }, - "e": { - "type": "string" + "const": "RSA" } - } + }, + "required": [ + "kty" + ], + "allOf": [ + { + "$ref": "#/definitions/RsaPublicParameters" + } + ] }, { "type": "object", - "required": [ - "crv", - "kty", - "x", - "y" - ], "properties": { "kty": { "type": "string", - "enum": [ - "EC" - ] - }, - "crv": { - "$ref": "#/definitions/JsonWebKeyEcEllipticCurve" - }, - "x": { - "type": "string" - }, - "y": { - "type": "string" + "const": "EC" } - } + }, + "required": [ + "kty" + ], + "allOf": [ + { + "$ref": "#/definitions/EcPublicParameters" + } + ] }, { "type": "object", - "required": [ - "crv", - "kty", - "x" - ], "properties": { "kty": { "type": "string", - "enum": [ - "OKP" - ] - }, - "crv": { - "$ref": "#/definitions/JsonWebKeyOkpEllipticCurve" - }, - "x": { - "type": "string" + "const": "OKP" } - } + }, + "required": [ + "kty" + ], + "allOf": [ + { + "$ref": "#/definitions/OkpPublicParameters" + } + ] } - ], + ] + }, + "RsaPublicParameters": { + "type": "object", "properties": { - "use": { - "$ref": "#/definitions/JsonWebKeyUse" + "n": { + "type": "string" }, - "key_ops": { - "type": "array", - "items": { - "$ref": "#/definitions/JsonWebKeyOperation" - } + "e": { + "type": "string" + } + }, + "required": [ + "n", + "e" + ] + }, + "JsonWebKeyEcEllipticCurve": { + "description": "JSON Web Key EC Elliptic Curve", + "anyOf": [ + { + "description": "P-256 Curve", + "const": "P-256" }, - "alg": { - "$ref": "#/definitions/JsonWebSignatureAlg" + { + "description": "P-384 Curve", + "const": "P-384" }, - "kid": { + { + "description": "P-521 Curve", + "const": "P-521" + }, + { + "description": "SECG secp256k1 curve", + "const": "secp256k1" + } + ] + }, + "EcPublicParameters": { + "type": "object", + "properties": { + "crv": { + "$ref": "#/definitions/JsonWebKeyEcEllipticCurve" + }, + "x": { "type": "string" }, - "x5u": { + "y": { "type": "string" + } + }, + "required": [ + "crv", + "x", + "y" + ] + }, + "JsonWebKeyOkpEllipticCurve": { + "description": "JSON Web Key OKP Elliptic Curve", + "anyOf": [ + { + "description": "Ed25519 signature algorithm key pairs", + "const": "Ed25519" }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } + { + "description": "Ed448 signature algorithm key pairs", + "const": "Ed448" }, - "x5t": { - "type": "string" + { + "description": "X25519 function key pairs", + "const": "X25519" }, - "x5t#S256": { + { + "description": "X448 function key pairs", + "const": "X448" + } + ] + }, + "OkpPublicParameters": { + "type": "object", + "properties": { + "crv": { + "$ref": "#/definitions/JsonWebKeyOkpEllipticCurve" + }, + "x": { "type": "string" } - } + }, + "required": [ + "crv", + "x" + ] }, "JsonWebKeyUse": { "description": "JSON Web Key Use", @@ -554,65 +644,25 @@ } ] }, - "JsonWebKeyEcEllipticCurve": { - "description": "JSON Web Key EC Elliptic Curve", - "anyOf": [ - { - "description": "P-256 Curve", - "const": "P-256" - }, - { - "description": "P-384 Curve", - "const": "P-384" - }, - { - "description": "P-521 Curve", - "const": "P-521" - }, - { - "description": "SECG secp256k1 curve", - "const": "secp256k1" - } - ] - }, - "JsonWebKeyOkpEllipticCurve": { - "description": "JSON Web Key OKP Elliptic Curve", - "anyOf": [ - { - "description": "Ed25519 signature algorithm key pairs", - "const": "Ed25519" - }, - { - "description": "Ed448 signature algorithm key pairs", - "const": "Ed448" - }, - { - "description": "X25519 function key pairs", - "const": "X25519" - }, - { - "description": "X448 function key pairs", - "const": "X448" - } - ] - }, "HttpConfig": { "description": "Configuration related to the web server", "type": "object", - "required": [ - "public_base" - ], "properties": { "listeners": { "description": "List of listeners to run", - "default": [], "type": "array", "items": { "$ref": "#/definitions/ListenerConfig" - } + }, + "default": [] }, "trusted_proxies": { - "description": "List of trusted reverse proxies that can set the `X-Forwarded-For` header", + "description": "List of trusted reverse proxies that can set the `X-Forwarded-For`\n header", + "type": "array", + "items": { + "type": "string", + "format": "ip" + }, "default": [ "192.168.0.0/16", "172.16.0.0/12", @@ -620,11 +670,7 @@ "127.0.0.1/8", "fd00::/8", "::1/128" - ], - "type": "array", - "items": { - "$ref": "#/definitions/IpNetwork" - } + ] }, "public_base": { "description": "Public URL base from where the authentication service is reachable", @@ -634,21 +680,22 @@ "issuer": { "description": "OIDC issuer URL. Defaults to `public_base` if not set.", "type": "string", - "format": "uri" + "format": "uri", + "nullable": true } - } + }, + "required": [ + "public_base" + ] }, "ListenerConfig": { "description": "Configuration of a listener", "type": "object", - "required": [ - "binds", - "resources" - ], "properties": { "name": { - "description": "A unique name for this listener which will be shown in traces and in metrics labels", - "type": "string" + "description": "A unique name for this listener which will be shown in traces and in\n metrics labels", + "type": "string", + "nullable": true }, "resources": { "description": "List of resources to mount", @@ -659,7 +706,8 @@ }, "prefix": { "description": "HTTP prefix to mount the resources on", - "type": "string" + "type": "string", + "nullable": true }, "binds": { "description": "List of sockets to bind", @@ -670,18 +718,26 @@ }, "proxy_protocol": { "description": "Accept `HAProxy`'s Proxy Protocol V1", - "default": false, - "type": "boolean" + "type": "boolean", + "default": false }, "tls": { "description": "If set, makes the listener use TLS with the provided certificate and key", - "allOf": [ + "anyOf": [ { "$ref": "#/definitions/TlsConfig" + }, + { + "const": null, + "nullable": true } ] } - } + }, + "required": [ + "resources", + "binds" + ] }, "Resource": { "description": "HTTP resources to mount", @@ -689,76 +745,59 @@ { "description": "Healthcheck endpoint (/health)", "type": "object", - "required": [ - "name" - ], "properties": { "name": { "type": "string", - "enum": [ - "health" - ] + "const": "health" } - } + }, + "required": [ + "name" + ] }, { "description": "Prometheus metrics endpoint (/metrics)", "type": "object", - "required": [ - "name" - ], "properties": { "name": { "type": "string", - "enum": [ - "prometheus" - ] + "const": "prometheus" } - } + }, + "required": [ + "name" + ] }, { "description": "OIDC discovery endpoints", "type": "object", - "required": [ - "name" - ], "properties": { "name": { "type": "string", - "enum": [ - "discovery" - ] + "const": "discovery" } - } + }, + "required": [ + "name" + ] }, { "description": "Pages destined to be viewed by humans", "type": "object", - "required": [ - "name" - ], "properties": { "name": { "type": "string", - "enum": [ - "human" - ] + "const": "human" } - } + }, + "required": [ + "name" + ] }, { "description": "GraphQL endpoint", "type": "object", - "required": [ - "name" - ], "properties": { - "name": { - "type": "string", - "enum": [ - "graphql" - ] - }, "playground": { "description": "Enabled the GraphQL playground", "type": "boolean" @@ -766,87 +805,84 @@ "undocumented_oauth2_access": { "description": "Allow access for OAuth 2.0 clients (undocumented)", "type": "boolean" + }, + "name": { + "type": "string", + "const": "graphql" } - } + }, + "required": [ + "name" + ] }, { "description": "OAuth-related APIs", "type": "object", - "required": [ - "name" - ], "properties": { "name": { "type": "string", - "enum": [ - "oauth" - ] + "const": "oauth" } - } + }, + "required": [ + "name" + ] }, { "description": "Matrix compatibility API", "type": "object", - "required": [ - "name" - ], "properties": { "name": { "type": "string", - "enum": [ - "compat" - ] + "const": "compat" } - } + }, + "required": [ + "name" + ] }, { "description": "Static files", "type": "object", - "required": [ - "name" - ], "properties": { - "name": { - "type": "string", - "enum": [ - "assets" - ] - }, "path": { "description": "Path to the directory to serve.", "type": "string" + }, + "name": { + "type": "string", + "const": "assets" } - } + }, + "required": [ + "name" + ] }, { "description": "Admin API, served at `/api/admin/v1`", "type": "object", - "required": [ - "name" - ], "properties": { "name": { "type": "string", - "enum": [ - "adminapi" - ] + "const": "adminapi" } - } + }, + "required": [ + "name" + ] }, { - "description": "Mount a \"/connection-info\" handler which helps debugging informations on the upstream connection", + "description": "Mount a \"/connection-info\" handler which helps debugging informations on\n the upstream connection", "type": "object", - "required": [ - "name" - ], "properties": { "name": { "type": "string", - "enum": [ - "connection-info" - ] + "const": "connection-info" } - } + }, + "required": [ + "name" + ] } ] }, @@ -856,67 +892,69 @@ { "description": "Listen on the specified host and port", "type": "object", - "required": [ - "port" - ], "properties": { "host": { - "description": "Host on which to listen.\n\nDefaults to listening on all addresses", - "type": "string" + "description": "Host on which to listen.\n\n Defaults to listening on all addresses", + "type": "string", + "nullable": true }, "port": { "description": "Port on which to listen.", "type": "integer", "format": "uint16", - "minimum": 0.0 + "minimum": 0, + "maximum": 65535 } - } + }, + "required": [ + "port" + ] }, { "description": "Listen on the specified address", "type": "object", - "required": [ - "address" - ], "properties": { "address": { "description": "Host and port on which to listen", + "type": "string", "examples": [ "[::1]:8080", "[::]:8080", "127.0.0.1:8080", "0.0.0.0:8080" - ], - "type": "string" + ] } - } + }, + "required": [ + "address" + ] }, { "description": "Listen on a UNIX domain socket", "type": "object", - "required": [ - "socket" - ], "properties": { "socket": { "description": "Path to the socket", "type": "string" } - } + }, + "required": [ + "socket" + ] }, { - "description": "Accept connections on file descriptors passed by the parent process.\n\nThis is useful for grabbing sockets passed by systemd.\n\nSee ", + "description": "Accept connections on file descriptors passed by the parent process.\n\n This is useful for grabbing sockets passed by systemd.\n\n See ", "type": "object", "properties": { "fd": { - "description": "Index of the file descriptor. Note that this is offseted by 3 because of the standard input/output sockets, so setting here a value of `0` will grab the file descriptor `3`", - "default": 0, + "description": "Index of the file descriptor. Note that this is offseted by 3\n because of the standard input/output sockets, so setting\n here a value of `0` will grab the file descriptor `3`", "type": "integer", "format": "uint", - "minimum": 0.0 + "minimum": 0, + "default": 0 }, "kind": { - "description": "Whether the socket is a TCP socket or a UNIX domain socket. Defaults to TCP.", + "description": "Whether the socket is a TCP socket or a UNIX domain socket. Defaults\n to TCP.", "default": "tcp", "allOf": [ { @@ -934,16 +972,12 @@ { "description": "UNIX domain socket", "type": "string", - "enum": [ - "unix" - ] + "const": "unix" }, { "description": "TCP socket", "type": "string", - "enum": [ - "tcp" - ] + "const": "tcp" } ] }, @@ -952,169 +986,165 @@ "type": "object", "properties": { "certificate": { - "description": "PEM-encoded X509 certificate chain\n\nExactly one of `certificate` or `certificate_file` must be set.", - "type": "string" + "description": "PEM-encoded X509 certificate chain\n\n Exactly one of `certificate` or `certificate_file` must be set.", + "type": "string", + "nullable": true }, "certificate_file": { - "description": "File containing the PEM-encoded X509 certificate chain\n\nExactly one of `certificate` or `certificate_file` must be set.", - "type": "string" + "description": "File containing the PEM-encoded X509 certificate chain\n\n Exactly one of `certificate` or `certificate_file` must be set.", + "type": "string", + "nullable": true }, "key": { - "description": "PEM-encoded private key\n\nExactly one of `key` or `key_file` must be set.", - "type": "string" + "description": "PEM-encoded private key\n\n Exactly one of `key` or `key_file` must be set.", + "type": "string", + "nullable": true }, "key_file": { - "description": "File containing a PEM or DER-encoded private key\n\nExactly one of `key` or `key_file` must be set.", - "type": "string" + "description": "File containing a PEM or DER-encoded private key\n\n Exactly one of `key` or `key_file` must be set.", + "type": "string", + "nullable": true }, "password": { - "description": "Password used to decode the private key\n\nOne of `password` or `password_file` must be set if the key is encrypted.", - "type": "string" + "description": "Password used to decode the private key\n\n One of `password` or `password_file` must be set if the key is\n encrypted.", + "type": "string", + "nullable": true }, "password_file": { - "description": "Password file used to decode the private key\n\nOne of `password` or `password_file` must be set if the key is encrypted.", - "type": "string" + "description": "Password file used to decode the private key\n\n One of `password` or `password_file` must be set if the key is\n encrypted.", + "type": "string", + "nullable": true } } }, - "IpNetwork": { - "oneOf": [ - { - "title": "v4", - "allOf": [ - { - "$ref": "#/definitions/Ipv4Network" - } - ] - }, - { - "title": "v6", - "allOf": [ - { - "$ref": "#/definitions/Ipv6Network" - } - ] - } - ], - "x-rust-type": "ipnetwork::IpNetwork" - }, - "Ipv4Network": { - "type": "string", - "pattern": "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\/(3[0-2]|[0-2]?[0-9])$", - "x-rust-type": "ipnetwork::Ipv4Network" - }, - "Ipv6Network": { - "type": "string", - "pattern": "^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\")[/](12[0-8]|1[0-1][0-9]|[0-9]?[0-9])$", - "x-rust-type": "ipnetwork::Ipv6Network" - }, "DatabaseConfig": { "description": "Database connection configuration", "type": "object", "properties": { "uri": { - "description": "Connection URI\n\nThis must not be specified if `host`, `port`, `socket`, `username`, `password`, or `database` are specified.", - "default": "postgresql://", + "description": "Connection URI\n\n This must not be specified if `host`, `port`, `socket`, `username`,\n `password`, or `database` are specified.", "type": "string", - "format": "uri" + "format": "uri", + "default": "postgresql://", + "nullable": true }, "host": { - "description": "Name of host to connect to\n\nThis must not be specified if `uri` is specified.", - "allOf": [ + "description": "Name of host to connect to\n\n This must not be specified if `uri` is specified.", + "anyOf": [ { "$ref": "#/definitions/Hostname" + }, + { + "const": null, + "nullable": true } ] }, "port": { - "description": "Port number to connect at the server host\n\nThis must not be specified if `uri` is specified.", + "description": "Port number to connect at the server host\n\n This must not be specified if `uri` is specified.", "type": "integer", "format": "uint16", - "maximum": 65535.0, - "minimum": 1.0 + "minimum": 1, + "maximum": 65535, + "nullable": true }, "socket": { - "description": "Directory containing the UNIX socket to connect to\n\nThis must not be specified if `uri` is specified.", - "type": "string" + "description": "Directory containing the UNIX socket to connect to\n\n This must not be specified if `uri` is specified.", + "type": "string", + "nullable": true }, "username": { - "description": "PostgreSQL user name to connect as\n\nThis must not be specified if `uri` is specified.", - "type": "string" + "description": "PostgreSQL user name to connect as\n\n This must not be specified if `uri` is specified.", + "type": "string", + "nullable": true }, "password": { - "description": "Password to be used if the server demands password authentication\n\nThis must not be specified if `uri` is specified.", - "type": "string" + "description": "Password to be used if the server demands password authentication\n\n This must not be specified if `uri` is specified.", + "type": "string", + "nullable": true }, "database": { - "description": "The database name\n\nThis must not be specified if `uri` is specified.", - "type": "string" + "description": "The database name\n\n This must not be specified if `uri` is specified.", + "type": "string", + "nullable": true }, "ssl_mode": { "description": "How to handle SSL connections", - "allOf": [ + "anyOf": [ { "$ref": "#/definitions/PgSslMode" + }, + { + "const": null, + "nullable": true } ] }, "ssl_ca": { - "description": "The PEM-encoded root certificate for SSL connections\n\nThis must not be specified if the `ssl_ca_file` option is specified.", - "type": "string" + "description": "The PEM-encoded root certificate for SSL connections\n\n This must not be specified if the `ssl_ca_file` option is specified.", + "type": "string", + "nullable": true }, "ssl_ca_file": { - "description": "Path to the root certificate for SSL connections\n\nThis must not be specified if the `ssl_ca` option is specified.", - "type": "string" + "description": "Path to the root certificate for SSL connections\n\n This must not be specified if the `ssl_ca` option is specified.", + "type": "string", + "nullable": true }, "ssl_certificate": { - "description": "The PEM-encoded client certificate for SSL connections\n\nThis must not be specified if the `ssl_certificate_file` option is specified.", - "type": "string" + "description": "The PEM-encoded client certificate for SSL connections\n\n This must not be specified if the `ssl_certificate_file` option is\n specified.", + "type": "string", + "nullable": true }, "ssl_certificate_file": { - "description": "Path to the client certificate for SSL connections\n\nThis must not be specified if the `ssl_certificate` option is specified.", - "type": "string" + "description": "Path to the client certificate for SSL connections\n\n This must not be specified if the `ssl_certificate` option is specified.", + "type": "string", + "nullable": true }, "ssl_key": { - "description": "The PEM-encoded client key for SSL connections\n\nThis must not be specified if the `ssl_key_file` option is specified.", - "type": "string" + "description": "The PEM-encoded client key for SSL connections\n\n This must not be specified if the `ssl_key_file` option is specified.", + "type": "string", + "nullable": true }, "ssl_key_file": { - "description": "Path to the client key for SSL connections\n\nThis must not be specified if the `ssl_key` option is specified.", - "type": "string" + "description": "Path to the client key for SSL connections\n\n This must not be specified if the `ssl_key` option is specified.", + "type": "string", + "nullable": true }, "max_connections": { "description": "Set the maximum number of connections the pool should maintain", - "default": 10, "type": "integer", "format": "uint32", - "minimum": 1.0 + "minimum": 1, + "default": 10 }, "min_connections": { "description": "Set the minimum number of connections the pool should maintain", - "default": 0, "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0, + "default": 0 }, "connect_timeout": { "description": "Set the amount of time to attempt connecting to the database", - "default": 30, "type": "integer", "format": "uint64", - "minimum": 0.0 + "minimum": 0, + "default": 30 }, "idle_timeout": { "description": "Set a maximum idle duration for individual connections", - "default": 600, "type": "integer", "format": "uint64", - "minimum": 0.0 + "minimum": 0, + "default": 600, + "nullable": true }, "max_lifetime": { "description": "Set the maximum lifetime of individual connections", - "default": 1800, "type": "integer", "format": "uint64", - "minimum": 0.0 + "minimum": 0, + "default": 1800 } } }, @@ -1123,49 +1153,37 @@ "format": "hostname" }, "PgSslMode": { - "description": "Options for controlling the level of protection provided for PostgreSQL SSL connections.", + "description": "Options for controlling the level of protection provided for PostgreSQL SSL\n connections.", "oneOf": [ { "description": "Only try a non-SSL connection.", "type": "string", - "enum": [ - "disable" - ] + "const": "disable" }, { "description": "First try a non-SSL connection; if that fails, try an SSL connection.", "type": "string", - "enum": [ - "allow" - ] + "const": "allow" }, { "description": "First try an SSL connection; if that fails, try a non-SSL connection.", "type": "string", - "enum": [ - "prefer" - ] + "const": "prefer" }, { - "description": "Only try an SSL connection. If a root CA file is present, verify the connection in the same way as if `VerifyCa` was specified.", + "description": "Only try an SSL connection. If a root CA file is present, verify the\n connection in the same way as if `VerifyCa` was specified.", "type": "string", - "enum": [ - "require" - ] + "const": "require" }, { - "description": "Only try an SSL connection, and verify that the server certificate is issued by a trusted certificate authority (CA).", + "description": "Only try an SSL connection, and verify that the server certificate is\n issued by a trusted certificate authority (CA).", "type": "string", - "enum": [ - "verify-ca" - ] + "const": "verify-ca" }, { - "description": "Only try an SSL connection; verify that the server certificate is issued by a trusted CA and that the requested server host name matches that in the certificate.", + "description": "Only try an SSL connection; verify that the server certificate is issued\n by a trusted CA and that the requested server host name matches that\n in the certificate.", "type": "string", - "enum": [ - "verify-full" - ] + "const": "verify-full" } ] }, @@ -1214,27 +1232,29 @@ }, "endpoint": { "description": "OTLP exporter: OTLP over HTTP compatible endpoint", - "default": "https://localhost:4318", "type": "string", - "format": "uri" + "format": "uri", + "default": "https://localhost:4318", + "nullable": true }, "propagators": { "description": "List of propagation formats to use for incoming and outgoing requests", - "default": [], "type": "array", "items": { "$ref": "#/definitions/Propagator" - } + }, + "default": [] }, "sample_rate": { - "description": "Sample rate for traces\n\nDefaults to `1.0` if not set.", + "description": "Sample rate for traces\n\n Defaults to `1.0` if not set.", + "type": "number", + "format": "double", "examples": [ 0.5 ], - "type": "number", - "format": "double", + "minimum": 0.0, "maximum": 1.0, - "minimum": 0.0 + "nullable": true } } }, @@ -1244,23 +1264,17 @@ { "description": "Don't export traces", "type": "string", - "enum": [ - "none" - ] + "const": "none" }, { "description": "Export traces to the standard output. Only useful for debugging", "type": "string", - "enum": [ - "stdout" - ] + "const": "stdout" }, { "description": "Export traces to an OpenTelemetry protocol compatible endpoint", "type": "string", - "enum": [ - "otlp" - ] + "const": "otlp" } ] }, @@ -1270,23 +1284,17 @@ { "description": "Propagate according to the W3C Trace Context specification", "type": "string", - "enum": [ - "tracecontext" - ] + "const": "tracecontext" }, { "description": "Propagate according to the W3C Baggage specification", "type": "string", - "enum": [ - "baggage" - ] + "const": "baggage" }, { "description": "Propagate trace context with Jaeger compatible headers", "type": "string", - "enum": [ - "jaeger" - ] + "const": "jaeger" } ] }, @@ -1305,9 +1313,10 @@ }, "endpoint": { "description": "OTLP exporter: OTLP over HTTP compatible endpoint", - "default": "https://localhost:4318", "type": "string", - "format": "uri" + "format": "uri", + "default": "https://localhost:4318", + "nullable": true } } }, @@ -1317,30 +1326,22 @@ { "description": "Don't export metrics", "type": "string", - "enum": [ - "none" - ] + "const": "none" }, { "description": "Export metrics to stdout. Only useful for debugging", "type": "string", - "enum": [ - "stdout" - ] + "const": "stdout" }, { "description": "Export metrics to an OpenTelemetry protocol compatible endpoint", "type": "string", - "enum": [ - "otlp" - ] + "const": "otlp" }, { - "description": "Export metrics via Prometheus. An HTTP listener with the `prometheus` resource must be setup to expose the Promethes metrics.", + "description": "Export metrics via Prometheus. An HTTP listener with the `prometheus`\n resource must be setup to expose the Promethes metrics.", "type": "string", - "enum": [ - "prometheus" - ] + "const": "prometheus" } ] }, @@ -1350,38 +1351,42 @@ "properties": { "dsn": { "description": "Sentry DSN", + "type": "string", + "format": "uri", "examples": [ "https://public@host:port/1" ], - "type": "string", - "format": "uri" + "nullable": true }, "environment": { - "description": "Environment to use when sending events to Sentry\n\nDefaults to `production` if not set.", + "description": "Environment to use when sending events to Sentry\n\n Defaults to `production` if not set.", + "type": "string", "examples": [ "production" ], - "type": "string" + "nullable": true }, "sample_rate": { - "description": "Sample rate for event submissions\n\nDefaults to `1.0` if not set.", + "description": "Sample rate for event submissions\n\n Defaults to `1.0` if not set.", + "type": "number", + "format": "float", "examples": [ 0.5 ], - "type": "number", - "format": "float", + "minimum": 0.0, "maximum": 1.0, - "minimum": 0.0 + "nullable": true }, "traces_sample_rate": { - "description": "Sample rate for tracing transactions\n\nDefaults to `0.0` if not set.", + "description": "Sample rate for tracing transactions\n\n Defaults to `0.0` if not set.", + "type": "number", + "format": "float", "examples": [ 0.5 ], - "type": "number", - "format": "float", + "minimum": 0.0, "maximum": 1.0, - "minimum": 0.0 + "nullable": true } } }, @@ -1391,36 +1396,36 @@ "properties": { "path": { "description": "Path to the folder which holds the templates", - "type": "string" + "type": "string", + "nullable": true }, "assets_manifest": { "description": "Path to the assets manifest", - "type": "string" + "type": "string", + "nullable": true }, "translations_path": { "description": "Path to the translations", - "type": "string" + "type": "string", + "nullable": true } } }, "EmailConfig": { "description": "Configuration related to sending emails", "type": "object", - "required": [ - "transport" - ], "properties": { "from": { "description": "Email address to use as From when sending emails", - "default": "\"Authentication Service\" ", "type": "string", - "format": "email" + "format": "email", + "default": "\"Authentication Service\" " }, "reply_to": { "description": "Email address to use as Reply-To when sending emails", - "default": "\"Authentication Service\" ", "type": "string", - "format": "email" + "format": "email", + "default": "\"Authentication Service\" " }, "transport": { "description": "What backend should be used when sending emails", @@ -1432,41 +1437,56 @@ }, "mode": { "description": "SMTP transport: Connection mode to the relay", - "allOf": [ + "anyOf": [ { "$ref": "#/definitions/EmailSmtpMode" + }, + { + "const": null, + "nullable": true } ] }, "hostname": { "description": "SMTP transport: Hostname to connect to", - "allOf": [ + "anyOf": [ { "$ref": "#/definitions/Hostname" + }, + { + "const": null, + "nullable": true } ] }, "port": { - "description": "SMTP transport: Port to connect to. Default is 25 for plain, 465 for TLS and 587 for `StartTLS`", + "description": "SMTP transport: Port to connect to. Default is 25 for plain, 465 for TLS\n and 587 for `StartTLS`", "type": "integer", "format": "uint16", - "maximum": 65535.0, - "minimum": 1.0 + "minimum": 1, + "maximum": 65535, + "nullable": true }, "username": { - "description": "SMTP transport: Username for use to authenticate when connecting to the SMTP server\n\nMust be set if the `password` field is set", - "type": "string" + "description": "SMTP transport: Username for use to authenticate when connecting to the\n SMTP server\n\n Must be set if the `password` field is set", + "type": "string", + "nullable": true }, "password": { - "description": "SMTP transport: Password for use to authenticate when connecting to the SMTP server\n\nMust be set if the `username` field is set", - "type": "string" + "description": "SMTP transport: Password for use to authenticate when connecting to the\n SMTP server\n\n Must be set if the `username` field is set", + "type": "string", + "nullable": true }, "command": { "description": "Sendmail transport: Command to use to send emails", + "type": "string", "default": "sendmail", - "type": "string" + "nullable": true } - } + }, + "required": [ + "transport" + ] }, "EmailTransportKind": { "description": "What backend should be used when sending emails", @@ -1474,23 +1494,17 @@ { "description": "Don't send emails anywhere", "type": "string", - "enum": [ - "blackhole" - ] + "const": "blackhole" }, { "description": "Send emails via an SMTP relay", "type": "string", - "enum": [ - "smtp" - ] + "const": "smtp" }, { "description": "Send emails by calling sendmail", "type": "string", - "enum": [ - "sendmail" - ] + "const": "sendmail" } ] }, @@ -1500,23 +1514,17 @@ { "description": "Plain text", "type": "string", - "enum": [ - "plain" - ] + "const": "plain" }, { "description": "`StartTLS` (starts as plain text then upgrade to TLS)", "type": "string", - "enum": [ - "starttls" - ] + "const": "starttls" }, { "description": "TLS", "type": "string", - "enum": [ - "tls" - ] + "const": "tls" } ] }, @@ -1524,51 +1532,57 @@ "description": "Application secrets", "type": "object", "properties": { - "keys": { - "description": "List of private keys to use for signing and encrypting payloads", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/KeyConfig" - } - }, "encryption_file": { "description": "File containing the encryption key for secure cookies.", - "type": "string" + "type": "string", + "nullable": true }, "encryption": { "description": "Encryption key for secure cookies.", + "type": "string", "examples": [ "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" ], - "type": "string", - "pattern": "[0-9a-fA-F]{64}" + "pattern": "[0-9a-fA-F]{64}", + "nullable": true + }, + "keys": { + "description": "List of private keys to use for signing and encrypting payloads", + "type": "array", + "items": { + "$ref": "#/definitions/KeyConfig" + }, + "default": [] } } }, "KeyConfig": { "description": "A single key with its key ID and optional password.", "type": "object", - "required": [ - "kid" - ], "properties": { "kid": { "type": "string" }, "password_file": { - "type": "string" + "type": "string", + "nullable": true }, "password": { - "type": "string" + "type": "string", + "nullable": true }, "key_file": { - "type": "string" + "type": "string", + "nullable": true }, "key": { - "type": "string" + "type": "string", + "nullable": true } - } + }, + "required": [ + "kid" + ] }, "PasswordsConfig": { "description": "User password hashing config", @@ -1576,44 +1590,42 @@ "properties": { "enabled": { "description": "Whether password-based authentication is enabled", - "default": true, - "type": "boolean" + "type": "boolean", + "default": true }, "schemes": { - "description": "The hashing schemes to use for hashing and validating passwords\n\nThe hashing scheme with the highest version number will be used for hashing new passwords.", + "description": "The hashing schemes to use for hashing and validating passwords\n\n The hashing scheme with the highest version number will be used for\n hashing new passwords.", + "type": "array", + "items": { + "$ref": "#/definitions/HashingScheme" + }, "default": [ { "version": 1, "algorithm": "argon2id" } - ], - "type": "array", - "items": { - "$ref": "#/definitions/HashingScheme" - } + ] }, "minimum_complexity": { - "description": "Score between 0 and 4 determining the minimum allowed password complexity. Scores are based on the ESTIMATED number of guesses needed to guess the password.\n\n- 0: less than 10^2 (100) - 1: less than 10^4 (10'000) - 2: less than 10^6 (1'000'000) - 3: less than 10^8 (100'000'000) - 4: any more than that", - "default": 3, + "description": "Score between 0 and 4 determining the minimum allowed password\n complexity. Scores are based on the ESTIMATED number of guesses\n needed to guess the password.\n\n - 0: less than 10^2 (100)\n - 1: less than 10^4 (10'000)\n - 2: less than 10^6 (1'000'000)\n - 3: less than 10^8 (100'000'000)\n - 4: any more than that", "type": "integer", "format": "uint8", - "minimum": 0.0 + "minimum": 0, + "maximum": 255, + "default": 3 } } }, "HashingScheme": { "description": "Parameters for a password hashing scheme", "type": "object", - "required": [ - "algorithm", - "version" - ], "properties": { "version": { - "description": "The version of the hashing scheme. They must be unique, and the highest version will be used for hashing new passwords.", + "description": "The version of the hashing scheme. They must be unique, and the highest\n version will be used for hashing new passwords.", "type": "integer", "format": "uint16", - "minimum": 0.0 + "minimum": 0, + "maximum": 65535 }, "algorithm": { "description": "The hashing algorithm to use", @@ -1624,25 +1636,32 @@ ] }, "unicode_normalization": { - "description": "Whether to apply Unicode normalization to the password before hashing\n\nDefaults to `false`, and generally recommended to stay false. This is although recommended when importing password hashs from Synapse, as it applies an NFKC normalization to the password before hashing it.", + "description": "Whether to apply Unicode normalization to the password before hashing\n\n Defaults to `false`, and generally recommended to stay false. This is\n although recommended when importing password hashs from Synapse, as it\n applies an NFKC normalization to the password before hashing it.", "type": "boolean" }, "cost": { "description": "Cost for the bcrypt algorithm", - "default": 12, "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0, + "default": 12, + "nullable": true }, "secret": { - "description": "An optional secret to use when hashing passwords. This makes it harder to brute-force the passwords in case of a database leak.", - "type": "string" + "description": "An optional secret to use when hashing passwords. This makes it harder\n to brute-force the passwords in case of a database leak.", + "type": "string", + "nullable": true }, "secret_file": { "description": "Same as `secret`, but read from a file.", - "type": "string" + "type": "string", + "nullable": true } - } + }, + "required": [ + "version", + "algorithm" + ] }, "Algorithm": { "description": "A hashing algorithm", @@ -1650,32 +1669,23 @@ { "description": "bcrypt", "type": "string", - "enum": [ - "bcrypt" - ] + "const": "bcrypt" }, { "description": "argon2id", "type": "string", - "enum": [ - "argon2id" - ] + "const": "argon2id" }, { "description": "PBKDF2", "type": "string", - "enum": [ - "pbkdf2" - ] + "const": "pbkdf2" } ] }, "MatrixConfig": { "description": "Configuration related to the Matrix homeserver", "type": "object", - "required": [ - "secret" - ], "properties": { "kind": { "description": "The kind of homeserver it is.", @@ -1688,8 +1698,8 @@ }, "homeserver": { "description": "The server name of the homeserver.", - "default": "localhost:8008", - "type": "string" + "type": "string", + "default": "localhost:8008" }, "secret": { "description": "Shared secret to use for calls to the admin API", @@ -1697,11 +1707,14 @@ }, "endpoint": { "description": "The base URL of the homeserver's client API", - "default": "http://localhost:8008/", "type": "string", - "format": "uri" + "format": "uri", + "default": "http://localhost:8008/" } - } + }, + "required": [ + "secret" + ] }, "HomeserverKind": { "description": "The kind of homeserver it is.", @@ -1709,16 +1722,12 @@ { "description": "Homeserver is Synapse", "type": "string", - "enum": [ - "synapse" - ] + "const": "synapse" }, { - "description": "Homeserver is Synapse, in read-only mode\n\nThis is meant for testing rolling out Matrix Authentication Service with no risk of writing data to the homeserver.", + "description": "Homeserver is Synapse, in read-only mode\n\n This is meant for testing rolling out Matrix Authentication Service with\n no risk of writing data to the homeserver.", "type": "string", - "enum": [ - "synapse_read_only" - ] + "const": "synapse_read_only" } ] }, @@ -1796,7 +1805,7 @@ ] }, "registration": { - "description": "Controls how many registrations attempts are permitted based on source address.", + "description": "Controls how many registrations attempts are permitted\n based on source address.", "default": { "burst": 3, "per_second": 0.0008333333333333334 @@ -1839,7 +1848,7 @@ "type": "object", "properties": { "per_ip": { - "description": "Controls how many account recovery attempts are permitted based on source IP address. This can protect against causing e-mail spam to many targets.\n\nNote: this limit also applies to re-sends.", + "description": "Controls how many account recovery attempts are permitted\n based on source IP address.\n This can protect against causing e-mail spam to many targets.\n\n Note: this limit also applies to re-sends.", "default": { "burst": 3, "per_second": 0.0008333333333333334 @@ -1851,7 +1860,7 @@ ] }, "per_address": { - "description": "Controls how many account recovery attempts are permitted based on the e-mail address entered into the recovery form. This can protect against causing e-mail spam to one target.\n\nNote: this limit also applies to re-sends.", + "description": "Controls how many account recovery attempts are permitted\n based on the e-mail address entered into the recovery form.\n This can protect against causing e-mail spam to one target.\n\n Note: this limit also applies to re-sends.", "default": { "burst": 3, "per_second": 0.0002777777777777778 @@ -1866,29 +1875,29 @@ }, "RateLimiterConfiguration": { "type": "object", - "required": [ - "burst", - "per_second" - ], "properties": { "burst": { - "description": "A one-off burst of actions that the user can perform in one go without waiting.", + "description": "A one-off burst of actions that the user can perform\n in one go without waiting.", "type": "integer", "format": "uint32", - "minimum": 1.0 + "minimum": 1 }, "per_second": { - "description": "How quickly the allowance replenishes, in number of actions per second. Can be fractional to replenish slower.", + "description": "How quickly the allowance replenishes, in number of actions per second.\n Can be fractional to replenish slower.", "type": "number", "format": "double" } - } + }, + "required": [ + "burst", + "per_second" + ] }, "LoginRateLimitingConfig": { "type": "object", "properties": { "per_ip": { - "description": "Controls how many login attempts are permitted based on source IP address. This can protect against brute force login attempts.\n\nNote: this limit also applies to password checks when a user attempts to change their own password.", + "description": "Controls how many login attempts are permitted\n based on source IP address.\n This can protect against brute force login attempts.\n\n Note: this limit also applies to password checks when a user attempts to\n change their own password.", "default": { "burst": 3, "per_second": 0.05 @@ -1900,7 +1909,7 @@ ] }, "per_account": { - "description": "Controls how many login attempts are permitted based on the account that is being attempted to be logged into. This can protect against a distributed brute force attack but should be set high enough to prevent someone's account being casually locked out.\n\nNote: this limit also applies to password checks when a user attempts to change their own password.", + "description": "Controls how many login attempts are permitted\n based on the account that is being attempted to be logged into.\n This can protect against a distributed brute force attack\n but should be set high enough to prevent someone's account being\n casually locked out.\n\n Note: this limit also applies to password checks when a user attempts to\n change their own password.", "default": { "burst": 1800, "per_second": 0.5 @@ -1917,7 +1926,7 @@ "type": "object", "properties": { "per_ip": { - "description": "Controls how many email authentication attempts are permitted based on the source IP address. This can protect against causing e-mail spam to many targets.", + "description": "Controls how many email authentication attempts are permitted\n based on the source IP address.\n This can protect against causing e-mail spam to many targets.", "default": { "burst": 5, "per_second": 0.016666666666666666 @@ -1929,7 +1938,7 @@ ] }, "per_address": { - "description": "Controls how many email authentication attempts are permitted based on the e-mail address entered into the authentication form. This can protect against causing e-mail spam to one target.\n\nNote: this limit also applies to re-sends.", + "description": "Controls how many email authentication attempts are permitted\n based on the e-mail address entered into the authentication form.\n This can protect against causing e-mail spam to one target.\n\n Note: this limit also applies to re-sends.", "default": { "burst": 3, "per_second": 0.0002777777777777778 @@ -1941,7 +1950,7 @@ ] }, "emails_per_session": { - "description": "Controls how many authentication emails are permitted to be sent per authentication session. This ensures not too many authentication codes are created for the same authentication session.", + "description": "Controls how many authentication emails are permitted to be sent per\n authentication session. This ensures not too many authentication codes\n are created for the same authentication session.", "default": { "burst": 2, "per_second": 0.0033333333333333335 @@ -1953,7 +1962,7 @@ ] }, "attempt_per_session": { - "description": "Controls how many code authentication attempts are permitted per authentication session. This can protect against brute-forcing the code.", + "description": "Controls how many code authentication attempts are permitted per\n authentication session. This can protect against brute-forcing the\n code.", "default": { "burst": 10, "per_second": 0.016666666666666666 @@ -1969,9 +1978,6 @@ "UpstreamOAuth2Config": { "description": "Upstream OAuth 2.0 providers configuration", "type": "object", - "required": [ - "providers" - ], "properties": { "providers": { "description": "List of OAuth 2.0 providers", @@ -1980,19 +1986,17 @@ "$ref": "#/definitions/Provider" } } - } + }, + "required": [ + "providers" + ] }, "Provider": { "description": "Configuration for one upstream OAuth 2 provider.", "type": "object", - "required": [ - "client_id", - "id", - "token_endpoint_auth_method" - ], "properties": { "enabled": { - "description": "Whether this provider is enabled.\n\nDefaults to `true`", + "description": "Whether this provider is enabled.\n\n Defaults to `true`", "type": "boolean" }, "id": { @@ -2001,28 +2005,33 @@ "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$" }, "synapse_idp_id": { - "description": "The ID of the provider that was used by Synapse. In order to perform a Synapse-to-MAS migration, this must be specified.\n\n## For providers that used OAuth 2.0 or OpenID Connect in Synapse\n\n### For `oidc_providers`: This should be specified as `oidc-` followed by the ID that was configured as `idp_id` in one of the `oidc_providers` in the Synapse configuration. For example, if Synapse's configuration contained `idp_id: wombat` for this provider, then specify `oidc-wombat` here.\n\n### For `oidc_config` (legacy): Specify `oidc` here.", - "type": "string" + "description": "The ID of the provider that was used by Synapse.\n In order to perform a Synapse-to-MAS migration, this must be specified.\n\n ## For providers that used OAuth 2.0 or OpenID Connect in Synapse\n\n ### For `oidc_providers`:\n This should be specified as `oidc-` followed by the ID that was\n configured as `idp_id` in one of the `oidc_providers` in the Synapse\n configuration.\n For example, if Synapse's configuration contained `idp_id: wombat` for\n this provider, then specify `oidc-wombat` here.\n\n ### For `oidc_config` (legacy):\n Specify `oidc` here.", + "type": "string", + "nullable": true }, "issuer": { - "description": "The OIDC issuer URL\n\nThis is required if OIDC discovery is enabled (which is the default)", - "type": "string" + "description": "The OIDC issuer URL\n\n This is required if OIDC discovery is enabled (which is the default)", + "type": "string", + "nullable": true }, "human_name": { "description": "A human-readable name for the provider, that will be shown to users", - "type": "string" + "type": "string", + "nullable": true }, "brand_name": { - "description": "A brand identifier used to customise the UI, e.g. `apple`, `google`, `github`, etc.\n\nValues supported by the default template are:\n\n- `apple` - `google` - `facebook` - `github` - `gitlab` - `twitter` - `discord`", - "type": "string" + "description": "A brand identifier used to customise the UI, e.g. `apple`, `google`,\n `github`, etc.\n\n Values supported by the default template are:\n\n - `apple`\n - `google`\n - `facebook`\n - `github`\n - `gitlab`\n - `twitter`\n - `discord`", + "type": "string", + "nullable": true }, "client_id": { "description": "The client ID to use when authenticating with the provider", "type": "string" }, "client_secret": { - "description": "The client secret to use when authenticating with the provider\n\nUsed by the `client_secret_basic`, `client_secret_post`, and `client_secret_jwt` methods", - "type": "string" + "description": "The client secret to use when authenticating with the provider\n\n Used by the `client_secret_basic`, `client_secret_post`, and\n `client_secret_jwt` methods", + "type": "string", + "nullable": true }, "token_endpoint_auth_method": { "description": "The method to authenticate the client with the provider", @@ -2034,22 +2043,30 @@ }, "sign_in_with_apple": { "description": "Additional parameters for the `sign_in_with_apple` method", - "allOf": [ + "anyOf": [ { "$ref": "#/definitions/SignInWithApple" + }, + { + "const": null, + "nullable": true } ] }, "token_endpoint_auth_signing_alg": { - "description": "The JWS algorithm to use when authenticating the client with the provider\n\nUsed by the `client_secret_jwt` and `private_key_jwt` methods", - "allOf": [ + "description": "The JWS algorithm to use when authenticating the client with the\n provider\n\n Used by the `client_secret_jwt` and `private_key_jwt` methods", + "anyOf": [ { "$ref": "#/definitions/JsonWebSignatureAlg" + }, + { + "const": null, + "nullable": true } ] }, "id_token_signed_response_alg": { - "description": "Expected signature for the JWT payload returned by the token authentication endpoint.\n\nDefaults to `RS256`.", + "description": "Expected signature for the JWT payload returned by the token\n authentication endpoint.\n\n Defaults to `RS256`.", "allOf": [ { "$ref": "#/definitions/JsonWebSignatureAlg" @@ -2057,11 +2074,11 @@ ] }, "scope": { - "description": "The scopes to request from the provider\n\nDefaults to `openid`.", + "description": "The scopes to request from the provider\n\n Defaults to `openid`.", "type": "string" }, "discovery_mode": { - "description": "How to discover the provider's configuration\n\nDefaults to `oidc`, which uses OIDC discovery with strict metadata verification", + "description": "How to discover the provider's configuration\n\n Defaults to `oidc`, which uses OIDC discovery with strict metadata\n verification", "allOf": [ { "$ref": "#/definitions/DiscoveryMode" @@ -2069,7 +2086,7 @@ ] }, "pkce_method": { - "description": "Whether to use proof key for code exchange (PKCE) when requesting and exchanging the token.\n\nDefaults to `auto`, which uses PKCE if the provider supports it.", + "description": "Whether to use proof key for code exchange (PKCE) when requesting and\n exchanging the token.\n\n Defaults to `auto`, which uses PKCE if the provider supports it.", "allOf": [ { "$ref": "#/definitions/PkceMethod" @@ -2077,48 +2094,60 @@ ] }, "fetch_userinfo": { - "description": "Whether to fetch the user profile from the userinfo endpoint, or to rely on the data returned in the `id_token` from the `token_endpoint`.\n\nDefaults to `false`.", - "default": false, - "type": "boolean" + "description": "Whether to fetch the user profile from the userinfo endpoint,\n or to rely on the data returned in the `id_token` from the\n `token_endpoint`.\n\n Defaults to `false`.", + "type": "boolean", + "default": false }, "userinfo_signed_response_alg": { - "description": "Expected signature for the JWT payload returned by the userinfo endpoint.\n\nIf not specified, the response is expected to be an unsigned JSON payload.", - "allOf": [ + "description": "Expected signature for the JWT payload returned by the userinfo\n endpoint.\n\n If not specified, the response is expected to be an unsigned JSON\n payload.", + "anyOf": [ { "$ref": "#/definitions/JsonWebSignatureAlg" + }, + { + "const": null, + "nullable": true } ] }, "authorization_endpoint": { - "description": "The URL to use for the provider's authorization endpoint\n\nDefaults to the `authorization_endpoint` provided through discovery", + "description": "The URL to use for the provider's authorization endpoint\n\n Defaults to the `authorization_endpoint` provided through discovery", "type": "string", - "format": "uri" + "format": "uri", + "nullable": true }, "userinfo_endpoint": { - "description": "The URL to use for the provider's userinfo endpoint\n\nDefaults to the `userinfo_endpoint` provided through discovery", + "description": "The URL to use for the provider's userinfo endpoint\n\n Defaults to the `userinfo_endpoint` provided through discovery", "type": "string", - "format": "uri" + "format": "uri", + "nullable": true }, "token_endpoint": { - "description": "The URL to use for the provider's token endpoint\n\nDefaults to the `token_endpoint` provided through discovery", + "description": "The URL to use for the provider's token endpoint\n\n Defaults to the `token_endpoint` provided through discovery", "type": "string", - "format": "uri" + "format": "uri", + "nullable": true }, "jwks_uri": { - "description": "The URL to use for getting the provider's public keys\n\nDefaults to the `jwks_uri` provided through discovery", + "description": "The URL to use for getting the provider's public keys\n\n Defaults to the `jwks_uri` provided through discovery", "type": "string", - "format": "uri" + "format": "uri", + "nullable": true }, "response_mode": { "description": "The response mode we ask the provider to use for the callback", - "allOf": [ + "anyOf": [ { "$ref": "#/definitions/ResponseMode" + }, + { + "const": null, + "nullable": true } ] }, "claims_imports": { - "description": "How claims should be imported from the `id_token` provided by the provider", + "description": "How claims should be imported from the `id_token` provided by the\n provider", "allOf": [ { "$ref": "#/definitions/ClaimsImports" @@ -2126,18 +2155,23 @@ ] }, "additional_authorization_parameters": { - "description": "Additional parameters to include in the authorization request\n\nOrders of the keys are not preserved.", + "description": "Additional parameters to include in the authorization request\n\n Orders of the keys are not preserved.", "type": "object", "additionalProperties": { "type": "string" } }, "forward_login_hint": { - "description": "Whether the `login_hint` should be forwarded to the provider in the authorization request.\n\nDefaults to `false`.", - "default": false, - "type": "boolean" + "description": "Whether the `login_hint` should be forwarded to the provider in the\n authorization request.\n\n Defaults to `false`.", + "type": "boolean", + "default": false } - } + }, + "required": [ + "id", + "client_id", + "token_endpoint_auth_method" + ] }, "TokenAuthMethod": { "description": "Authentication methods used against the OAuth 2.0 provider", @@ -2145,61 +2179,47 @@ { "description": "`none`: No authentication", "type": "string", - "enum": [ - "none" - ] + "const": "none" }, { - "description": "`client_secret_basic`: `client_id` and `client_secret` used as basic authorization credentials", + "description": "`client_secret_basic`: `client_id` and `client_secret` used as basic\n authorization credentials", "type": "string", - "enum": [ - "client_secret_basic" - ] + "const": "client_secret_basic" }, { - "description": "`client_secret_post`: `client_id` and `client_secret` sent in the request body", + "description": "`client_secret_post`: `client_id` and `client_secret` sent in the\n request body", "type": "string", - "enum": [ - "client_secret_post" - ] + "const": "client_secret_post" }, { - "description": "`client_secret_jwt`: a `client_assertion` sent in the request body and signed using the `client_secret`", + "description": "`client_secret_jwt`: a `client_assertion` sent in the request body and\n signed using the `client_secret`", "type": "string", - "enum": [ - "client_secret_jwt" - ] + "const": "client_secret_jwt" }, { - "description": "`private_key_jwt`: a `client_assertion` sent in the request body and signed by an asymmetric key", + "description": "`private_key_jwt`: a `client_assertion` sent in the request body and\n signed by an asymmetric key", "type": "string", - "enum": [ - "private_key_jwt" - ] + "const": "private_key_jwt" }, { "description": "`sign_in_with_apple`: a special method for Signin with Apple", "type": "string", - "enum": [ - "sign_in_with_apple" - ] + "const": "sign_in_with_apple" } ] }, "SignInWithApple": { "type": "object", - "required": [ - "key_id", - "team_id" - ], "properties": { "private_key_file": { "description": "The private key file used to sign the `id_token`", - "type": "string" + "type": "string", + "nullable": true }, "private_key": { "description": "The private key used to sign the `id_token`", - "type": "string" + "type": "string", + "nullable": true }, "team_id": { "description": "The Team ID of the Apple Developer Portal", @@ -2209,7 +2229,11 @@ "description": "The key ID of the Apple Developer Portal", "type": "string" } - } + }, + "required": [ + "team_id", + "key_id" + ] }, "DiscoveryMode": { "description": "How to discover the provider's configuration", @@ -2217,49 +2241,37 @@ { "description": "Use OIDC discovery with strict metadata verification", "type": "string", - "enum": [ - "oidc" - ] + "const": "oidc" }, { "description": "Use OIDC discovery with relaxed metadata verification", "type": "string", - "enum": [ - "insecure" - ] + "const": "insecure" }, { "description": "Use a static configuration", "type": "string", - "enum": [ - "disabled" - ] + "const": "disabled" } ] }, "PkceMethod": { - "description": "Whether to use proof key for code exchange (PKCE) when requesting and exchanging the token.", + "description": "Whether to use proof key for code exchange (PKCE) when requesting and\n exchanging the token.", "oneOf": [ { - "description": "Use PKCE if the provider supports it\n\nDefaults to no PKCE if provider discovery is disabled", + "description": "Use PKCE if the provider supports it\n\n Defaults to no PKCE if provider discovery is disabled", "type": "string", - "enum": [ - "auto" - ] + "const": "auto" }, { "description": "Always use PKCE with the S256 challenge method", "type": "string", - "enum": [ - "always" - ] + "const": "always" }, { "description": "Never use PKCE", "type": "string", - "enum": [ - "never" - ] + "const": "never" } ] }, @@ -2267,18 +2279,14 @@ "description": "The response mode we ask the provider to use for the callback", "oneOf": [ { - "description": "`query`: The provider will send the response as a query string in the URL search parameters", + "description": "`query`: The provider will send the response as a query string in the\n URL search parameters", "type": "string", - "enum": [ - "query" - ] + "const": "query" }, { - "description": "`form_post`: The provider will send the response as a POST request with the response parameters in the request body\n\n", + "description": "`form_post`: The provider will send the response as a POST request with\n the response parameters in the request body\n\n ", "type": "string", - "enum": [ - "form_post" - ] + "const": "form_post" } ] }, @@ -2311,7 +2319,7 @@ ] }, "email": { - "description": "Import the email address of the user based on the `email` and `email_verified` claims", + "description": "Import the email address of the user based on the `email` and\n `email_verified` claims", "allOf": [ { "$ref": "#/definitions/EmailImportPreference" @@ -2333,8 +2341,9 @@ "type": "object", "properties": { "template": { - "description": "The Jinja2 template to use for the subject attribute\n\nIf not provided, the default template is `{{ user.sub }}`", - "type": "string" + "description": "The Jinja2 template to use for the subject attribute\n\n If not provided, the default template is `{{ user.sub }}`", + "type": "string", + "nullable": true } } }, @@ -2351,8 +2360,9 @@ ] }, "template": { - "description": "The Jinja2 template to use for the localpart attribute\n\nIf not provided, the default template is `{{ user.preferred_username }}`", - "type": "string" + "description": "The Jinja2 template to use for the localpart attribute\n\n If not provided, the default template is `{{ user.preferred_username }}`", + "type": "string", + "nullable": true } } }, @@ -2362,30 +2372,22 @@ { "description": "Ignore the claim", "type": "string", - "enum": [ - "ignore" - ] + "const": "ignore" }, { "description": "Suggest the claim value, but allow the user to change it", "type": "string", - "enum": [ - "suggest" - ] + "const": "suggest" }, { "description": "Force the claim value, but don't fail if it is missing", "type": "string", - "enum": [ - "force" - ] + "const": "force" }, { "description": "Force the claim value, and fail if it is missing", "type": "string", - "enum": [ - "require" - ] + "const": "require" } ] }, @@ -2402,8 +2404,9 @@ ] }, "template": { - "description": "The Jinja2 template to use for the displayname attribute\n\nIf not provided, the default template is `{{ user.name }}`", - "type": "string" + "description": "The Jinja2 template to use for the displayname attribute\n\n If not provided, the default template is `{{ user.name }}`", + "type": "string", + "nullable": true } } }, @@ -2420,8 +2423,9 @@ ] }, "template": { - "description": "The Jinja2 template to use for the email address attribute\n\nIf not provided, the default template is `{{ user.email }}`", - "type": "string" + "description": "The Jinja2 template to use for the email address attribute\n\n If not provided, the default template is `{{ user.email }}`", + "type": "string", + "nullable": true } } }, @@ -2430,8 +2434,9 @@ "type": "object", "properties": { "template": { - "description": "The Jinja2 template to use for the account name. This name is only used for display purposes.\n\nIf not provided, it will be ignored.", - "type": "string" + "description": "The Jinja2 template to use for the account name. This name is only used\n for display purposes.\n\n If not provided, it will be ignored.", + "type": "string", + "nullable": true } } }, @@ -2441,26 +2446,31 @@ "properties": { "service_name": { "description": "A human-readable name. Defaults to the server's address.", - "type": "string" + "type": "string", + "nullable": true }, "policy_uri": { - "description": "Link to a privacy policy, displayed in the footer of web pages and emails. It is also advertised to clients through the `op_policy_uri` OIDC provider metadata.", + "description": "Link to a privacy policy, displayed in the footer of web pages and\n emails. It is also advertised to clients through the `op_policy_uri`\n OIDC provider metadata.", "type": "string", - "format": "uri" + "format": "uri", + "nullable": true }, "tos_uri": { - "description": "Link to a terms of service document, displayed in the footer of web pages and emails. It is also advertised to clients through the `op_tos_uri` OIDC provider metadata.", + "description": "Link to a terms of service document, displayed in the footer of web\n pages and emails. It is also advertised to clients through the\n `op_tos_uri` OIDC provider metadata.", "type": "string", - "format": "uri" + "format": "uri", + "nullable": true }, "imprint": { - "description": "Legal imprint, displayed in the footer in the footer of web pages and emails.", - "type": "string" + "description": "Legal imprint, displayed in the footer in the footer of web pages and\n emails.", + "type": "string", + "nullable": true }, "logo_uri": { "description": "Logo displayed in some web pages.", "type": "string", - "format": "uri" + "format": "uri", + "nullable": true } } }, @@ -2470,19 +2480,25 @@ "properties": { "service": { "description": "Which service should be used for CAPTCHA protection", - "allOf": [ + "anyOf": [ { "$ref": "#/definitions/CaptchaServiceKind" + }, + { + "const": null, + "nullable": true } ] }, "site_key": { "description": "The site key to use", - "type": "string" + "type": "string", + "nullable": true }, "secret_key": { "description": "The secret key to use", - "type": "string" + "type": "string", + "nullable": true } } }, @@ -2492,23 +2508,17 @@ { "description": "Use Google's reCAPTCHA v2 API", "type": "string", - "enum": [ - "recaptcha_v2" - ] + "const": "recaptcha_v2" }, { "description": "Use Cloudflare Turnstile", "type": "string", - "enum": [ - "cloudflare_turnstile" - ] + "const": "cloudflare_turnstile" }, { "description": "Use ``HCaptcha``", "type": "string", - "enum": [ - "hcaptcha" - ] + "const": "hcaptcha" } ] }, @@ -2517,101 +2527,106 @@ "type": "object", "properties": { "email_change_allowed": { - "description": "Whether users are allowed to change their email addresses. Defaults to `true`.", + "description": "Whether users are allowed to change their email addresses. Defaults to\n `true`.", "type": "boolean" }, "displayname_change_allowed": { - "description": "Whether users are allowed to change their display names. Defaults to `true`.\n\nThis should be in sync with the policy in the homeserver configuration.", + "description": "Whether users are allowed to change their display names. Defaults to\n `true`.\n\n This should be in sync with the policy in the homeserver configuration.", "type": "boolean" }, "password_registration_enabled": { - "description": "Whether to enable self-service password registration. Defaults to `false` if password authentication is enabled.\n\nThis has no effect if password login is disabled.", + "description": "Whether to enable self-service password registration. Defaults to\n `false` if password authentication is enabled.\n\n This has no effect if password login is disabled.", "type": "boolean" }, "password_change_allowed": { - "description": "Whether users are allowed to change their passwords. Defaults to `true`.\n\nThis has no effect if password login is disabled.", + "description": "Whether users are allowed to change their passwords. Defaults to `true`.\n\n This has no effect if password login is disabled.", "type": "boolean" }, "password_recovery_enabled": { - "description": "Whether email-based password recovery is enabled. Defaults to `false`.\n\nThis has no effect if password login is disabled.", + "description": "Whether email-based password recovery is enabled. Defaults to `false`.\n\n This has no effect if password login is disabled.", "type": "boolean" }, "account_deactivation_allowed": { - "description": "Whether users are allowed to delete their own account. Defaults to `true`.", + "description": "Whether users are allowed to delete their own account. Defaults to\n `true`.", "type": "boolean" }, "login_with_email_allowed": { - "description": "Whether users can log in with their email address. Defaults to `false`.\n\nThis has no effect if password login is disabled.", + "description": "Whether users can log in with their email address. Defaults to `false`.\n\n This has no effect if password login is disabled.", "type": "boolean" }, "registration_token_required": { - "description": "Whether registration tokens are required for password registrations. Defaults to `false`.\n\nWhen enabled, users must provide a valid registration token during password registration. This has no effect if password registration is disabled.", + "description": "Whether registration tokens are required for password registrations.\n Defaults to `false`.\n\n When enabled, users must provide a valid registration token during\n password registration. This has no effect if password registration\n is disabled.", "type": "boolean" } } }, "ExperimentalConfig": { - "description": "Configuration sections for experimental options\n\nDo not change these options unless you know what you are doing.", + "description": "Configuration sections for experimental options\n\n Do not change these options unless you know what you are doing.", "type": "object", "properties": { "access_token_ttl": { "description": "Time-to-live of access tokens in seconds. Defaults to 5 minutes.", "type": "integer", "format": "uint64", - "maximum": 86400.0, - "minimum": 60.0 + "minimum": 60, + "maximum": 86400 }, "compat_token_ttl": { - "description": "Time-to-live of compatibility access tokens in seconds. Defaults to 5 minutes.", + "description": "Time-to-live of compatibility access tokens in seconds. Defaults to 5\n minutes.", "type": "integer", "format": "uint64", - "maximum": 86400.0, - "minimum": 60.0 + "minimum": 60, + "maximum": 86400 }, "inactive_session_expiration": { - "description": "Experimetal feature to automatically expire inactive sessions\n\nDisabled by default", - "allOf": [ + "description": "Experimetal feature to automatically expire inactive sessions\n\n Disabled by default", + "anyOf": [ { "$ref": "#/definitions/InactiveSessionExpirationConfig" + }, + { + "const": null, + "nullable": true } ] }, "plan_management_iframe_uri": { - "description": "Experimental feature to show a plan management tab and iframe. This value is passed through \"as is\" to the client without any validation.", - "type": "string" + "description": "Experimental feature to show a plan management tab and iframe.\n This value is passed through \"as is\" to the client without any\n validation.", + "type": "string", + "nullable": true } } }, "InactiveSessionExpirationConfig": { "description": "Configuration options for the inactive session expiration feature", "type": "object", - "required": [ - "ttl" - ], "properties": { "ttl": { "description": "Time after which an inactive session is automatically finished", "type": "integer", "format": "uint64", - "maximum": 7776000.0, - "minimum": 600.0 + "minimum": 600, + "maximum": 7776000 }, "expire_compat_sessions": { "description": "Should compatibility sessions expire after inactivity", - "default": true, - "type": "boolean" + "type": "boolean", + "default": true }, "expire_oauth_sessions": { "description": "Should OAuth 2.0 sessions expire after inactivity", - "default": true, - "type": "boolean" + "type": "boolean", + "default": true }, "expire_user_sessions": { "description": "Should user sessions expire after inactivity", - "default": true, - "type": "boolean" + "type": "boolean", + "default": true } - } + }, + "required": [ + "ttl" + ] } } } \ No newline at end of file diff --git a/policies/schema/authorization_grant_input.json b/policies/schema/authorization_grant_input.json index f23bf7a73..501c46b92 100644 --- a/policies/schema/authorization_grant_input.json +++ b/policies/schema/authorization_grant_input.json @@ -3,16 +3,11 @@ "title": "AuthorizationGrantInput", "description": "Input for the authorization grant policy.", "type": "object", - "required": [ - "client", - "grant_type", - "requester", - "scope" - ], "properties": { "user": { "type": "object", - "additionalProperties": true + "additionalProperties": true, + "nullable": true }, "client": { "type": "object", @@ -28,6 +23,12 @@ "$ref": "#/definitions/Requester" } }, + "required": [ + "client", + "scope", + "grant_type", + "requester" + ], "definitions": { "GrantType": { "type": "string", @@ -44,11 +45,13 @@ "ip_address": { "description": "IP address of the entity making the request", "type": "string", - "format": "ip" + "format": "ip", + "nullable": true }, "user_agent": { "description": "User agent of the entity making the request", - "type": "string" + "type": "string", + "nullable": true } } } diff --git a/policies/schema/client_registration_input.json b/policies/schema/client_registration_input.json index 461645126..d4ffe366f 100644 --- a/policies/schema/client_registration_input.json +++ b/policies/schema/client_registration_input.json @@ -3,10 +3,6 @@ "title": "ClientRegistrationInput", "description": "Input for the client registration policy.", "type": "object", - "required": [ - "client_metadata", - "requester" - ], "properties": { "client_metadata": { "type": "object", @@ -16,6 +12,10 @@ "$ref": "#/definitions/Requester" } }, + "required": [ + "client_metadata", + "requester" + ], "definitions": { "Requester": { "description": "Identity of the requester", @@ -24,11 +24,13 @@ "ip_address": { "description": "IP address of the entity making the request", "type": "string", - "format": "ip" + "format": "ip", + "nullable": true }, "user_agent": { "description": "User agent of the entity making the request", - "type": "string" + "type": "string", + "nullable": true } } } diff --git a/policies/schema/email_input.json b/policies/schema/email_input.json index d97f291be..df6bd91fc 100644 --- a/policies/schema/email_input.json +++ b/policies/schema/email_input.json @@ -3,10 +3,6 @@ "title": "EmailInput", "description": "Input for the email add policy.", "type": "object", - "required": [ - "email", - "requester" - ], "properties": { "email": { "type": "string" @@ -15,6 +11,10 @@ "$ref": "#/definitions/Requester" } }, + "required": [ + "email", + "requester" + ], "definitions": { "Requester": { "description": "Identity of the requester", @@ -23,11 +23,13 @@ "ip_address": { "description": "IP address of the entity making the request", "type": "string", - "format": "ip" + "format": "ip", + "nullable": true }, "user_agent": { "description": "User agent of the entity making the request", - "type": "string" + "type": "string", + "nullable": true } } } diff --git a/policies/schema/register_input.json b/policies/schema/register_input.json index cd8868cd4..17b7c2f0a 100644 --- a/policies/schema/register_input.json +++ b/policies/schema/register_input.json @@ -3,11 +3,6 @@ "title": "RegisterInput", "description": "Input for the user registration policy.", "type": "object", - "required": [ - "registration_method", - "requester", - "username" - ], "properties": { "registration_method": { "$ref": "#/definitions/RegistrationMethod" @@ -16,12 +11,18 @@ "type": "string" }, "email": { - "type": "string" + "type": "string", + "nullable": true }, "requester": { "$ref": "#/definitions/Requester" } }, + "required": [ + "registration_method", + "username", + "requester" + ], "definitions": { "RegistrationMethod": { "type": "string", @@ -37,11 +38,13 @@ "ip_address": { "description": "IP address of the entity making the request", "type": "string", - "format": "ip" + "format": "ip", + "nullable": true }, "user_agent": { "description": "User agent of the entity making the request", - "type": "string" + "type": "string", + "nullable": true } } }